Vedremo come si costruisce un'interfaccia di’amministratore,
composée di diverse tabelle che hanno relazioni Many2Many.
Riprendiamo il nostro esempio di’interfaccia
disponibile molti/molti qui
Abbiamo un tavolo zona, che è compostoé di diversi élémenti del tavolo diéappartamenti.
Su questi déappartamenti, abbiamo delle agenzie.
Per coronare il tutto, e per dare un senso à questa
chaînato da donneésì, aggiungiamo una tabella zx_credential, che riprendeésente dei commerciali.
Ecco la nostra chaînato da donneée:
Commerciali->Zone>Déappartamenti->Agenzie.
Per il nostro progetto, abbiamo modélisé
l’insieme del database tramite MySQL Workbench, ed esportazioneé
le schéma in MySql.
Non ci resta più che’à esportare le entity (con getter e setter), e créper i CRUD Sonata
php bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity
php bin/console make:entity --regenerate App
php bin/console make:sonata:admin App/Entity/ZxZone
php bin/console make:sonata:admin App/Entity/ZxCredential
php bin/console make:sonata:admin App/Entity/Agences
php bin/console make:sonata:admin App/Entity/Departement
php bin/console cache:clear
Per la forma, rinominiamo la nostra tabella
« zx_credential » in
« Accècommerciali ».
Nel file service.yaml basta modificare l’argomento
« etichetta ».
admin.zx_credential:
class: App\Admin\ZxCredentialAdmin
arguments: [~, App\Entity\ZxCredential, App\Controller\ZxCredentialAdminController]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: "Accès commerciaux" }
public: true
Fino’qui, niente di più classico. Ma quello che l’si desidera c’è avere un'interfaccia con tutta la chaînato da donneée liée tra di loro, in modo che
quando il’acceso édite a un commerciale, abbiamo la possibilitàé d’andare direttamente nella configurazione della sua zona, poi i suoi déappartamenti, poi le sue agenzie.
Per questo, noi andiamo spéidentificare le connessioni tra le tabelle tramite una chiamata à la méthode
« aggiungiFiglio » nel servizio del nostro CRUD. E noi andremo spécifié i bambini di ogni tavolo.
Perché il processo possa funzionare dobbiamo
spéspecificare il servizio per bambini, così come il campo del genitore utilizzatoé per fare il legame.
Nella nostra connessione
ZxCredential->ZxZone, abbiamo il seguente campo nella nostra entità figlio (ZxZone) :
C’è quindi quello che è utilizzatoé per fare il collegamento, e che useremo nella nostra configurazione.
admin.zx_credential:
class: App\Admin\ZxCredentialAdmin
arguments: [~, App\Entity\ZxCredential, App\Controller\ZxCredentialAdminController]
calls:
- [addChild, ["@admin.zx_zone", 'zxCredential']]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: "Accès commerciaux" }
public: true
La configurazione complèci dà questo:
admin.departement:
class: App\Admin\DepartementAdmin
arguments: [~, App\Entity\Departement, ~]
calls:
- [addChild, ["@admin.agences","departement"]]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: Departement }
public: true
admin.zx_zone:
class: App\Admin\ZxZoneAdmin
arguments: [~, App\Entity\ZxZone, App\Controller\ZxZoneAdminController]
calls:
- [addChild, ["@admin.departement", "zxZone"]]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: Zones }
public: true
admin.zx_credential:
class: App\Admin\ZxCredentialAdmin
arguments: [~, App\Entity\ZxCredential, App\Controller\ZxCredentialAdminController]
calls:
- [addChild, ["@admin.zx_zone", 'zxCredential']]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: "Accès commerciaux" }
public: true
admin.agences:
class: App\Admin\AgencesAdmin
arguments: [~, App\Entity\Agences, ~]
tags:
- { name: sonata.admin, manager_type: orm, group: admin, label: Agences }
public: true
A questo punto, tutti i nostri tavoli sono collegatiésì, ma sarà necessario configurare il menu per navigare tra di esse.
Per questo, aggiungeremo la méthode configureSideMenu nel nostro admin dei commerciali
« ZxCredentialAdmin ».
Attenzione,
c’è nel punto di’entraé di
l’interfaccia che’bisogna configurare il menu. Quindi tutta la chaîCommerciali>Zone>Déappartamenti->Agenzie andranno a farsi negli Commerciali.
1ª énastro, aggiungiamo gli use in tutte le nostre interfacce d’admin, come ça
c’è chiusoé.
<?php
declare(strict_types=1);
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
/*gestion de nos interfaces imbriquées*/
use Knp\Menu\ItemInterface as MenuItemInterface;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Route\RouteCollection;
Poi aggiungiamo il nostro primo collegamento alla gestione delle zone, dalla’interfaccia Zx_Credential.
protected function configureSideMenu(MenuItemInterface $menu, $action, AdminInterface $childAdmin = null): void
{
if (!$childAdmin && !\in_array($action, ['edit'], true)) {
return;
}
$admin = $this->isChild() ? $this->getParent() : $this;
$id = $admin->getRequest()->get('id');
$label=$this->hasSubject() && null !== $this->getSubject()->getLabel() ? $this->getSubject()->getLabel():null;
$menu->addChild(
'Configuration de l\'accès commercial : '.$label,
$admin->generateMenuUrl('edit', ['id' => $id])
);
$child=$menu->addChild( 'Listes des zones',
[
'uri' => $admin->generateUrl('admin.zx_zone.list', ['id' => $id])
]);
}
In breve, quello che’bisogna ricordare, e che non’non è chiaro nella documentazione, c’è la strada à configurare.
Ci serve il nome della rotta, poi l’id.
Per
l’id, c’è semplice, per un primo livello,
c’è sempre :
$id = $admin->getRequest()->get('id');
E per il viaggio, c’è sempre la mêmi ha scelto,
c’è il nome del servizio seguito dal tipo di vista. Quindi qui
admin.zx_zone.elenco
Che ci dà :
$child=$menu->addChild( 'Listes des zones',
[
'uri' => $admin->generateUrl('admin.zx_zone.list', ['id' => $id])
]);
A questo punto, abbiamo il nostro première interfaccia
incastratoée. Per le seguenti, noi andremo
répéper la configurazione.
Quanto segue non’non spiegatoé nella documentazione, perché c’est
d’una logica implacabile. Ma potrete cercare a lungo se non’non avete capito il funzionamento di’incastro delle interfacce.
Ciò che’bisogna ben capire c’è che tutto si fa à partire dalla
i primière interfaccia. L’inclusione dei pulsanti del menu e la costruzione delle rotte.
La prima, poi la première+la seconda, poi la prima+la seconda+la terzaèio.
L’l'interfaccia deve costruirsi
sempre nel nostro primoère interfaccia, per ogni
énastri. Per questo abbiamo bisogno di rétazzaérer l’ID à ogni ébattute,
e costruire la strada.
E per rétazzaérer les
clés, la cosa c’è di scrutare le strade che sono généréè per symfony, tramite il comando
debug:router
php bin/console debug:router
---------------------------------------------------------- ---------- -------- ------ -------------------------------------------------------------------------------------------------------------
Name Method Scheme Host Path
---------------------------------------------------------- ---------- -------- ------ -------------------------------------------------------------------------------------------------------------
_preview_error ANY ANY ANY /_error/{code}.{_format}
_wdt ANY ANY ANY /_wdt/{token}
_profiler_home ANY ANY ANY /_profiler/
_profiler_search ANY ANY ANY /_profiler/search
_profiler_search_bar ANY ANY ANY /_profiler/search_bar
_profiler_phpinfo ANY ANY ANY /_profiler/phpinfo
_profiler_search_results ANY ANY ANY /_profiler/{token}/search/results
_profiler_open_file ANY ANY ANY /_profiler/open
_profiler ANY ANY ANY /_profiler/{token}
_profiler_router ANY ANY ANY /_profiler/{token}/router
_profiler_exception ANY ANY ANY /_profiler/{token}/exception
_profiler_exception_css ANY ANY ANY /_profiler/{token}/exception.css
admin_app_departement_list ANY ANY ANY /admin/app/departement/list
admin_app_departement_create ANY ANY ANY /admin/app/departement/create
admin_app_departement_batch ANY ANY ANY /admin/app/departement/batch
admin_app_departement_edit ANY ANY ANY /admin/app/departement/{id}/edit
admin_app_departement_delete ANY ANY ANY /admin/app/departement/{id}/delete
admin_app_departement_show ANY ANY ANY /admin/app/departement/{id}/show
admin_app_departement_export ANY ANY ANY /admin/app/departement/export
admin_app_departement_agences_list ANY ANY ANY /admin/app/departement/{id}/agences/list
admin_app_departement_agences_create ANY ANY ANY /admin/app/departement/{id}/agences/create
admin_app_departement_agences_batch ANY ANY ANY /admin/app/departement/{id}/agences/batch
admin_app_departement_agences_edit ANY ANY ANY /admin/app/departement/{id}/agences/{childId}/edit
admin_app_departement_agences_delete ANY ANY ANY /admin/app/departement/{id}/agences/{childId}/delete
admin_app_departement_agences_show ANY ANY ANY /admin/app/departement/{id}/agences/{childId}/show
admin_app_departement_agences_export ANY ANY ANY /admin/app/departement/{id}/agences/export
admin_app_zxcredential_list ANY ANY ANY /admin/app/zxcredential/list
admin_app_zxcredential_create ANY ANY ANY /admin/app/zxcredential/create
admin_app_zxcredential_batch ANY ANY ANY /admin/app/zxcredential/batch
admin_app_zxcredential_edit ANY ANY ANY /admin/app/zxcredential/{id}/edit
admin_app_zxcredential_delete ANY ANY ANY /admin/app/zxcredential/{id}/delete
admin_app_zxcredential_show ANY ANY ANY /admin/app/zxcredential/{id}/show
admin_app_zxcredential_export ANY ANY ANY /admin/app/zxcredential/export
admin_app_zxcredential_zxzone_list ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/list
admin_app_zxcredential_zxzone_create ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/create
admin_app_zxcredential_zxzone_batch ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/batch
admin_app_zxcredential_zxzone_edit ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/edit
admin_app_zxcredential_zxzone_delete ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/delete
admin_app_zxcredential_zxzone_show ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/show
admin_app_zxcredential_zxzone_export ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/export
admin_app_zxcredential_zxzone_departement_list ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/list
admin_app_zxcredential_zxzone_departement_create ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/create
admin_app_zxcredential_zxzone_departement_batch ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/batch
admin_app_zxcredential_zxzone_departement_edit ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/edit
admin_app_zxcredential_zxzone_departement_delete ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/delete
admin_app_zxcredential_zxzone_departement_show ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/show
admin_app_zxcredential_zxzone_departement_export ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/export
admin_app_zxcredential_zxzone_departement_agences_list ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/list
admin_app_zxcredential_zxzone_departement_agences_create ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/create
admin_app_zxcredential_zxzone_departement_agences_batch ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/batch
admin_app_zxcredential_zxzone_departement_agences_edit ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/{childChildChildId}/edit
admin_app_zxcredential_zxzone_departement_agences_delete ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/{childChildChildId}/delete
admin_app_zxcredential_zxzone_departement_agences_show ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/{childChildChildId}/show
admin_app_zxcredential_zxzone_departement_agences_export ANY ANY ANY /admin/app/zxcredential/{id}/zxzone/{childId}/departement/{childChildId}/agences/export
admin_app_agences_list ANY ANY ANY /admin/app/agences/list
admin_app_agences_create ANY ANY ANY /admin/app/agences/create
admin_app_agences_batch ANY ANY ANY /admin/app/agences/batch
admin_app_agences_edit ANY ANY ANY /admin/app/agences/{id}/edit
admin_app_agences_delete ANY ANY ANY /admin/app/agences/{id}/delete
admin_app_agences_show ANY ANY ANY /admin/app/agences/{id}/show
E la nostra attenzione particolare si concentrerà sul nostro percorso
admin_app_zxcredential_zxzone_departement_agences_list che
comprende tutta la nostra catena di datiée.
Lei è
composée delle nostre tabelle con il nome degli id che noi andremo a rétazzaéré per costruire le strade delle nostre interfacce.
/admin/app/zxcredential/{id}/zxzone/{childId}/dipartimento/{childChildId}/agenzie/elenco
zxcredential
: id
zxzone : idBambino
dipartimento : childChildId
Quindi
testando la présenso di queste variabili nei nostri URL in ingresso, potremoéfinire la profondità della nostra interfaccia e costruire i menu in conséuenze.
Per le strade c’è semplice,
per ciascuno étappetini, si aggiunge la strada corrente
séparé con una pipa | :
zxcredential :
admin.zx_zone.list
zxzone :
admin.zx_zone|admin.dipartimento.elenco
dipartimento:
admin.zx_zone|admin.dipartimento|admin.agenzie.elenco
Ciò che
ci dai :
protected function configureSideMenu(MenuItemInterface $menu, $action, AdminInterface $childAdmin = null): void
{
if (!$childAdmin && !\in_array($action, ['edit'], true)) {
return;
}
$admin = $this->isChild() ? $this->getParent() : $this;
$id = $admin->getRequest()->get('id');
$label=$this->hasSubject() && null !== $this->getSubject()->getLabel() ? $this->getSubject()->getLabel():null;
$menu->addChild(
'Configuration de l\'accès commercial : '.$label,
$admin->generateMenuUrl('edit', ['id' => $id])
);
$child=$menu->addChild( 'Listes des zones',
[
'uri' => $admin->generateUrl('admin.zx_zone.list', [
'id' => $id
])
]);
if(!empty($admin->getRequest()->get('childId'))){
$child=$menu->addChild( 'Listes des departements',
[
'uri' => $admin->generateUrl('admin.zx_zone|admin.departement.list', [
'id' => $id,
'childId' => $admin->getRequest()->get('childId')
])
]);
}
if(!empty($admin->getRequest()->get('childChildId'))){
$child=$menu->addChild( 'Listes des agences',
[
'uri' => $admin->generateUrl('admin.zx_zone|admin.departement|admin.agences.list', [
'id' => $id,
'childId' => $admin->getRequest()->get('childId'),
'childChildId' => $admin->getRequest()->get('childChildId')
])
]);
}
}
La nostra interfaccia è ora completaètu :
Adattare l’esempio alla versione installata
Gli esempi Symfony e Sonata rimangono legati alle versioni indicate nell’articolo. Symfony 4.x e Symfony 6.2 non sono più supportati: per un progetto attuale, utilizzate un ramo mantenuto e la documentazione corrispondente esattamente alle vostre dipendenze.
php bin/console about
composer show symfony/framework-bundle sonata-project/admin-bundle
Prima di riprendere il codice, controllate le firme, i servizi, le rotte e i template interessati. Aggiungete poi un test funzionale che copra le autorizzazioni, il codice HTTP e il risultato visibile.
Riferimento : versioni di Symfony supportate.