Je ne vais pas rentrer dans les détails de l'installation des Bundles nécessaires, la documentation officielle était assez bien détaillée. Pour ce tuto, j'utilise :
- Sonata Admin Bundle - tuto
- Sonata User Bundle - tuto
- Fos User Bundle -tuto
- Symfony 2.8 ( Fos et User Bundle pas compatibles avec Symfony 3.2)
Objectif : Les utilisateurs sont des élèves. Ajouter aux utilisateurs une relation avec un ou plusieurs responsables légaux, sachant qu'un utilisateur peut avoir plusieurs responsables légaux, mais aussi qu'un responsable légal peut avoir plusieurs utilisateurs (frères et soeurs par exemple)
Dans un premier temps, définition des annotations pour les entités :
<?php /** * src/Application/Sonata/UserBundle/Entity/LegalResponsible.php */ namespace Application\Sonata\UserBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * LegalResponsible * * @ORM\Table(name="legal_reponsible") * @ORM\Entity(repositoryClass="Application\Sonata\UserBundle\Repository\LegalResponsibleRepository") */ class LegalResponsible { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="name", type="string", length=255, nullable=true) */ private $name; /** * @var string * * @ORM\Column(name="first_name", type="string", length=255, nullable=true) */ private $first_name; /** * @var string * * @ORM\Column(name="email", type="string", length=255, nullable=true) */ private $email; /** * @var string * * @ORM\Column(name="gender", type="string", length=1, nullable=true) */ private $gender='u'; /** * @ORM\ManyToMany(targetEntity="User", mappedBy="legal") */ private $userlegal; public function __toString() { return ($this->getName().' '.$this->getFirstName()) ? : ''; } public function getLegalNameFirstName() { return sprintf('%s - %s', $this->name, $this->first_name); } /** * Constructor */ public function __construct() { $this->userlegal = new \Doctrine\Common\Collections\ArrayCollection(); } }
On ajoute notre relation dans l'entité User :
<?php namespace Application\Sonata\UserBundle\Entity; use Sonata\UserBundle\Entity\BaseUser as BaseUser; use Doctrine\ORM\EntityManager; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="fos_user_user") */ class User extends BaseUser { //----------- /** * @ORM\ManyToMany(targetEntity="LegalResponsible", inversedBy="userlegal") * @ORM\JoinColumn(name="legal_id", referencedColumnName="id") */ private $legal; public function __construct(){ parent::__construct(); //------ $this->file = new \Doctrine\Common\Collections\ArrayCollection(); //------ }
Création du formulaire d'administration pour la gestion des responsables légaux :
<?php /** * Application/UserBundle/Admin/LegalResponsibleAdmin.php */ namespace Application\Sonata\UserBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Form\FormMapper; class LegalResponsibleAdmin extends AbstractAdmin { protected $translationDomain = 'SonataUserBundle'; // default is 'messages' protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('gender', 'sonata_user_gender', array( 'required' => true, 'translation_domain' => $this->translationDomain, 'label' => 'form.label_gender' )) ->add('name', 'text',['required' => false, 'label' => 'form.label_lastname']) ->add('first_name', 'text',['required' => false, 'label' => 'form.label_firstname']) ->add('email', 'text',['required' => false, 'label' => 'form.label_email']) /*->add('userlegal', 'sonata_type_model_autocomplete', [ 'required' => false, 'label' => 'Students', 'property' => 'getUniqueUserForm', 'multiple' => true ])*/ ; } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper->add('name'); } protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('gender','',['label' => 'form.label_gender']) ->addIdentifier('name','',['label' => 'form.label_lastname']) ->addIdentifier('first_name','',['label' => 'form.label_firstname']) ->addIdentifier('userlegal','',['label' => 'form.label_students']) ->add('_action', 'actions', array( 'actions' => array( 'show' => array(), ) )) ; } public function toString($object) { return $object->getName().' '.$object->getFirstName(); } }
Nous obtenons ce genre de résultat :
Ajout dans l'admin user du champ des responsables légaux. Pour mon cas, j'ai choisi d'ajouter un onglet :
<?php /** * Application/UserBundle/Admin/UserAdmin.php */ class UserAdmin extends BaseUserAdmin { protected function configureFormFields( FormMapper $formMapper ) { //------- parent::configureFormFields($formMapper); ->tab('menu_legal_responsible') ->with('menu_legal_responsible') ->add('legal', 'Sonata\AdminBundle\Form\Type\ModelType', [ 'property' => 'getLegalNameFirstName', 'label' => 'menu_legal_responsible', 'required' => false, 'multiple' => true, 'class' => 'Application\Sonata\UserBundle\Entity\LegalResponsible', 'translation_domain' => 'SonataUserBundle' ] ) ->end() ->end() //------- } }
Ensuite, il suffit de générer les getters et setters pour nos deux entités :
php app/console doctrine:generate ApplicationUserBundle:User php app/console doctrine:generate ApplicationUserBundle:LegalResponsible
Mise à jour du schéma de la base de donnée (validation et mise à jour)
php app/console doctrine:schema:validate php app/console doctrine:schema:update --force
Il ne reste plus qu'à ajouter le lien vers la gestion de nos responsables légaux au menu :
#app/services.yml services: #service_name: # class: AppBundle\Directory\ClassName # arguments: ['@another_service_name', 'plain_value', '%parameter_name%'] sonata.admin.legalresponsible: class: Application\Sonata\UserBundle\Admin\LegalResponsibleAdmin arguments: [~, Application\Sonata\UserBundle\Entity\LegalResponsible, ~] tags: - { name: sonata.admin, manager_type: orm, group: %sonata.user.admin.legal_responsible%, label: menu_legal_responsible, on_top: true, icon: <i class="fa fa-user-circle"></i>, label_translator_strategy: sonata.admin.label.strategy.underscore }
Et voilà, vous pouvez maintenant créer vos responsables légaux et les mettre en relations avec vos utilisateurs. Ce principe peut-être étendu à n'importe qu'elle autre entité (des fichiers liés à un utilisateur, des commandes, ....), le principe est le même, si ce n'est l'utilisation de manyToOne au lieu de many-to-many dans certains cas (pour des commandes par exemple, un utilisateur peut avoir plusieurs commandes qui lui seront liées, mais une commande ne serait liée qu'à un seul utilisateur, etc ...)