Installer et configurer Sonata Admin sur Symfony 4


Salutations à tous. Cet article parlera de Symfony 4 et de Sonata Admin.


Pendant le processus d'installation, j'ai rencontré beaucoup d'inexactitudes dans la documentation et la documentation elle-même était dispersée à plusieurs endroits. Je considérerai ici l'ensemble du processus, de la création du projet à l'autorisation en passant par l'authentification.


Certaines parties des paramètres proviennent de la documentation officielle, d'autres des commentaires sur GitHub, où les problèmes d'installation ont été discutés. Les pièges possibles et les moyens de les contourner sont également peints.


Créer un projet symfony


$ composer create-project symfony/skeleton sonatademo 

 $ cd sonatademo 

Pour utiliser le serveur Web intégré Symfony, vous devez installer le client Symfony .


Nous commençons.


 $ symfony serve 

Nous suivons le lien http://127.0.0.1:8000/ et nous recevrons le message d'accueil Symfony standard. Donc tout fonctionne correctement.



Installer Sonata Admin


 $ composer require sonata-project/admin-bundle 

Admin Sonata et DB


Pour interagir avec la base de données, vous devez installer l'une des trois bibliothèques:



Dans cet article, j'utilise SonataDoctrineORMAdminBundle , qui est plus que suffisant pour fonctionner avec MySQL ou Sqlite .


Installez SonataDoctrineORMAdminBundle .


 $ composer require sonata-project/doctrine-orm-admin-bundle 

Configurons maintenant le travail avec Sqlite .


Ouvrez le fichier .env et dans la section ###> doctrine/doctrine-bundle ### changez DATABASE_URL .


 DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" 

Puisque Symfony Flex fait presque tout le travail pour nous pendant l'installation, il reste à faire quelques manipulations pour obtenir le résultat final.


 # config/packages/framework.yaml framework: translator: { fallbacks: ['en'] } 

Nous réalisons


 $ composer dump-env dev 

Maintenant, nous suivons le lien http://127.0.0.1:8000/admin et nous voyons une interface administrative standard vide.



Création d'entité


Créons par exemple deux entités, connectées par une relation un-à-plusieurs.


 <?php // src/Entity/City.php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class City { /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer", options={"unsigned":true}) */ private $id; /** * @var string * * @ORM\Column(type="string") */ private $title; /** * @var string * * @ORM\Column(type="text") */ private $description; /** * @var bool * * @ORM\Column(type="boolean") */ private $isBig = false; /** * @ORM\OneToMany(targetEntity="Address", mappedBy="city") */ private $addresses; public function __construct() { $this->addresses = new ArrayCollection(); } public function getAddresses() { return $this->addresses; } /** * @return string */ public function getTitle(): ?string { return $this->title; } /** * @param string $title * @return City */ public function setTitle(string $title): City { $this->title = $title; return $this; } /** * @return string */ public function getDescription(): ?string { return $this->description; } /** * @param string $description * @return City */ public function setDescription(string $description): City { $this->description = $description; return $this; } /** * @return bool */ public function isBig(): ?bool { return $this->isBig; } /** * @param bool $isBig * @return City */ public function setIsBig(bool $isBig): City { $this->isBig = $isBig; return $this; } public function __toString() { return $this->title; } } 

 <?php // src/Entity/Address.php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Address { /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer", options={"unsigned":true}) */ private $id; /** * @var string * * @ORM\Column(type="string") */ private $title; /** * @var string * * @ORM\Column(type="text") */ private $description; /** * @ORM\ManyToOne(targetEntity="City", inversedBy="addresses") */ private $city; /** * @return string */ public function getTitle(): ?string { return $this->title; } /** * @param string $title * @return Address */ public function setTitle(string $title): Address { $this->title = $title; return $this; } /** * @return string */ public function getDescription(): ?string { return $this->description; } /** * @param string $description * @return Address */ public function setDescription(string $description): Address { $this->description = $description; return $this; } /** * @return City */ public function getCity(): ?City { return $this->city; } /** * @param City $city * @return Address */ public function setCity(City $city) { $this->city = $city; return $this; } public function __toString() { return $this->title; } } 

Nous synchronisons avec la base de données.


 bin/console doctrine:schema:create 

Configuration d'entité pour Sonata Admin


Il est nécessaire que chaque entité crée un fichier séparé avec une description du fonctionnement de Sonata Admin.


 <?php // src/Admin/CityAdmin.php namespace App\Admin; use App\Entity\Address; use App\Entity\City; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Form\Type\CollectionType; use Sonata\AdminBundle\Form\Type\ModelType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; final class CityAdmin extends AbstractAdmin { protected function configureFormFields(FormMapper $formMapper) { $formMapper->add('title', TextType::class); $formMapper->add('description', TextareaType::class); $formMapper->add('isBig', CheckboxType::class); } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper->add('title'); $datagridMapper->add('isBig'); } protected function configureListFields(ListMapper $listMapper) { $listMapper->addIdentifier('title'); $listMapper->addIdentifier('isBig'); } } 

 <?php // src/Admin/AddressAdmin.php namespace App\Admin; use App\Entity\City; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Form\Type\ModelType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; final class AddressAdmin extends AbstractAdmin { protected function configureFormFields(FormMapper $formMapper) { $formMapper->add('title', TextType::class); $formMapper->add('description', TextareaType::class); $formMapper->add('city', ModelType::class, [ 'class' => City::class, 'property' => 'title', ]); } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper->add('title'); } protected function configureListFields(ListMapper $listMapper) { $listMapper->addIdentifier('title'); } } 

Ces classes doivent être décrites dans service.yaml .


 # config/service.yaml services: ... App\Admin\CityAdmin: arguments: [~, App\Entity\City, ~] tags: - { name: sonata.admin, manager_type: orm, label: City } App\Admin\AddressAdmin: arguments: [~, App\Entity\Address, ~] tags: - { name: sonata.admin, manager_type: orm, label: Address } 

Si des erreurs se produisent lors de la saisie de la partie administrative, par exemple Unable to generate a URL for the named route , vous devez alors vider le cache de l'application et réessayer.


 bin/console cache:clear 

Maintenant, si vous cliquez sur le lien http://127.0.0.1:8000/admin, nous verrons une liste de deux éléments Address et City , où vous pourrez voir les listes et créer de nouvelles entités.



Autorisation et authentification


Créez d'abord une entité utilisateur.


 <?php // src/Entity/User.php namespace App\Entity; use Sonata\UserBundle\Entity\BaseUser as BaseUser; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="fos_user") */ class User extends BaseUser { /** * @ORM\Id * @ORM\Column(type="integer", options={"unsigned":true}) * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @return int */ public function getId() { return $this->id; } } 

Et en même temps, créer l'essence du groupe d'utilisateurs.


 <?php // src/Entity/Group.php namespace App\Entity; use Sonata\UserBundle\Entity\BaseGroup as BaseGroup; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="fos_group") */ class Group extends BaseGroup { /** * @ORM\Id * @ORM\Column(type="integer", options={"unsigned":true}) * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @return int */ public function getId() { return $this->id; } } 

Après avoir configuré Twig comme moteur de modèle.


 framework: ... templating: engines: ['twig'] 

Il existe actuellement des problèmes avec Symfony Flex et FOSUserBundle. Pour plus de détails, consultez les liens # 2562 , # 2708 et # 2801 .


Bien que ces problèmes ne soient pas résolus, vous devez effectuer quelques manipulations supplémentaires avant d'installer le groupe d' Sonata User Bundle .


 # config/service.yaml services: ... mailer: alias: fos_user.mailer.noop public: true 

 # config/packages/fos_user.yaml fos_user: db_driver: orm firewall_name: main user_class: App\Entity\User registration: confirmation: enabled: false from_email: address: '%env(MAILER_USER_ADDRESS)%' sender_name: '%env(MAILER_USER_NAME)%' service: user_manager: sonata.user.orm.user_manager mailer: 'fos_user.mailer.noop' group: group_class: App\Entity\Group group_manager: sonata.user.orm.group_manager 

Après quoi, vous pouvez installer le bundle.


 $ composer require sonata-project/user-bundle 

Configuration de l'ACL


Dans Symfony 4, les ACL ont été déplacées vers un symfony/acl-bundle distinct. Par conséquent, il doit être installé séparément.


 composer require symfony/acl-bundle 

 # config/packages/sonata_user.yaml sonata_user: security_acl: true manager_type: orm 

 # config/packages/acl.yaml acl: connection: default 

Configuration de la doctrine


 # config/packages/doctrine.yaml doctrine: orm: mappings: SonataUserBundle: ~ FOSUserBundle: ~ 

Configuration du travail avec le courrier


Le travail avec le courrier n'étant pas pris en compte dans le cadre de cet article, nous indiquerons un stub au lieu d'un véritable service.


 # config/packages/sonata_user.yaml sonata_user: mailer: fos_user.mailer.noop 

Intégration du groupe d'utilisateurs dans Sonata Admin


 # config/routes.yaml sonata_user_admin_security: resource: '@SonataUserBundle/Resources/config/routing/admin_security.xml' prefix: /admin sonata_user_admin_resetting: resource: '@SonataUserBundle/Resources/config/routing/admin_resetting.xml' prefix: /admin/resetting 

 # config/packages/security.yaml security: encoders: FOS\UserBundle\Model\UserInterface: sha512 providers: fos_userbundle: id: fos_user.user_provider.username role_hierarchy: ROLE_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN] ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false # -> custom firewall for the admin area of the URL admin: pattern: /admin(.*) context: user form_login: provider: fos_userbundle login_path: /admin/login use_forward: false check_path: /admin/login_check failure_path: null logout: path: /admin/logout target: /admin/login anonymous: true # -> end custom configuration # default login area for standard users # This firewall is used to handle the public login area # This part is handled by the FOS User Bundle main: pattern: .* context: user form_login: provider: fos_userbundle login_path: /login use_forward: false check_path: /login_check failure_path: null logout: true anonymous: true access_control: # Admin login page needs to be accessed without credential - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/logout$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } # Secured part of the site # This config requires being logged for the whole site and having the admin role for the admin part. # Change these rules to adapt them to your needs - { path: ^/admin/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] } - { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY } 

 # config/packages/sonata_user.yaml sonata_user: ... class: user: App\Entity\User group: App\Entity\Group 

Vous pouvez maintenant mettre à jour l'ACL et la base de données.


 $ bin/console acl:init 

 $ php bin/console doctrine:schema:update --force 

Créez un super utilisateur. Spécifiez la demo du nom et la demo mot de passe.


 $ bin/console fos:user:create --super-admin Please choose a username:demo Please choose an email:demo@demo.com Please choose a password: Created user demo 

Pour configurer correctement nos classes d'administration, ainsi que l'ACL, vous devez apporter des modifications aux paramètres.


 sonata_admin: ... security: handler: sonata.admin.security.handler.acl 

Après avoir exécuté ce qui suit:


 $ bin/console sonata:admin:setup-acl Starting ACL AdminBundle configuration > install ACL for App\Admin\AddressAdmin - add role: ROLE_APP\ADMIN\ADDRESSADMIN_GUEST, permissions: ["LIST"] - add role: ROLE_APP\ADMIN\ADDRESSADMIN_STAFF, permissions: ["LIST","CREATE"] - add role: ROLE_APP\ADMIN\ADDRESSADMIN_EDITOR, permissions: ["OPERATOR","EXPORT"] - add role: ROLE_APP\ADMIN\ADDRESSADMIN_ADMIN, permissions: ["MASTER"] > install ACL for App\Admin\CityAdmin - add role: ROLE_APP\ADMIN\CITYADMIN_GUEST, permissions: ["LIST"] - add role: ROLE_APP\ADMIN\CITYADMIN_STAFF, permissions: ["LIST","CREATE"] - add role: ROLE_APP\ADMIN\CITYADMIN_EDITOR, permissions: ["OPERATOR","EXPORT"] - add role: ROLE_APP\ADMIN\CITYADMIN_ADMIN, permissions: ["MASTER"] > install ACL for sonata.user.admin.user - add role: ROLE_SONATA_USER_ADMIN_USER_GUEST, permissions: ["LIST"] - add role: ROLE_SONATA_USER_ADMIN_USER_STAFF, permissions: ["LIST","CREATE"] - add role: ROLE_SONATA_USER_ADMIN_USER_EDITOR, permissions: ["OPERATOR","EXPORT"] - add role: ROLE_SONATA_USER_ADMIN_USER_ADMIN, permissions: ["MASTER"] > install ACL for sonata.user.admin.group - add role: ROLE_SONATA_USER_ADMIN_GROUP_GUEST, permissions: ["LIST"] - add role: ROLE_SONATA_USER_ADMIN_GROUP_STAFF, permissions: ["LIST","CREATE"] - add role: ROLE_SONATA_USER_ADMIN_GROUP_EDITOR, permissions: ["OPERATOR","EXPORT"] - add role: ROLE_SONATA_USER_ADMIN_GROUP_ADMIN, permissions: ["MASTER"] 

Maintenant, lorsque vous essayez d'accéder à l'adresse http://127.0.0.1:8000/admin, nous serons redirigés vers http://127.0.0.1:8000/admin/login .



Entrez démo / démo et entrez dans la partie administrative.



Résumé


Après toutes les manipulations, nous avons obtenu une partie administrative fonctionnelle de Sonata Admin sur Symfony 4 ainsi que l'authentification et l'autorisation à l'aide de Sonata User + ACL.


Merci à tous. Si vous avez des questions et des commentaires, je les écouterai dans les commentaires.

Source: https://habr.com/ru/post/fr460345/


All Articles