Installieren und konfigurieren Sie Sonata Admin auf Symfony 4


Grüße an alle. In diesem Artikel wird über Symfony 4 und Sonata Admin gesprochen.


Während des Installationsprozesses stieß ich auf viele Ungenauigkeiten in der Dokumentation und die Dokumentation selbst war an mehreren Stellen verstreut. Hier werde ich den gesamten Prozess von der Erstellung des Projekts über die Autorisierung bis hin zur Authentifizierung betrachten.


Einige Teile der Einstellungen stammen aus der offiziellen Dokumentation, andere aus den Kommentaren zu GitHub, in denen Installationsprobleme besprochen wurden. Mögliche Fallstricke und Wege um sie herum werden ebenfalls gemalt.


Erstellen eines Symfony-Projekts


$ composer create-project symfony/skeleton sonatademo 

 $ cd sonatademo 

Um den Symfony Embedded Web Server verwenden zu können, müssen Sie den Symfony Client installieren.


Wir fangen an.


 $ symfony serve 

Wir folgen dem Link http://127.0.0.1:8000/ und erhalten die Standard-Symfony-Begrüßung. Also funktioniert alles richtig.



Installieren Sie Sonata Admin


 $ composer require sonata-project/admin-bundle 

Sonata Admin und DB


Um mit der Datenbank zu interagieren, müssen Sie eine von drei Bibliotheken installieren:



In diesem Artikel verwende ich SonataDoctrineORMAdminBundle , was mehr als genug ist, um mit MySQL oder Sqlite .


Installieren Sie SonataDoctrineORMAdminBundle .


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

Jetzt konfigurieren wir die Arbeit mit Sqlite .


Öffnen Sie die ENV-Datei und ändern Sie im Abschnitt ###> doctrine/doctrine-bundle ### DATABASE_URL .


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

Da Symfony Flex während der Installation fast die gesamte Arbeit für uns erledigt, müssen noch einige Manipulationen vorgenommen werden, um das Endergebnis zu erhalten.


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

Wir führen aus


 $ composer dump-env dev 

Jetzt folgen wir dem Link http://127.0.0.1:8000/admin und sehen eine leere Standard-Verwaltungsoberfläche.



Entitätserstellung


Erstellen wir beispielsweise zwei Entitäten, die durch eine Eins-zu-Viele-Beziehung verbunden sind.


 <?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; } } 

Wir synchronisieren mit der Datenbank.


 bin/console doctrine:schema:create 

Entitätskonfiguration für Sonata Admin


Für jede Entität muss eine separate Datei mit einer Beschreibung der Funktionsweise von Sonata Admin erstellt werden.


 <?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'); } } 

Diese Klassen müssen in 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 } 

Wenn beim Eingeben des Verwaltungsteils Fehler auftreten, z. B. Unable to generate a URL for the named route kann, müssen Sie den Anwendungscache leeren und es erneut versuchen.


 bin/console cache:clear 

Wenn Sie nun auf den Link http://127.0.0.1:8000/admin klicken, wird eine Liste mit zwei Elementen Address und City Address , in der Sie Listen anzeigen und neue Entitäten erstellen können.



Autorisierung und Authentifizierung


Erstellen Sie zunächst eine Benutzerentität.


 <?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; } } 

Und gleichzeitig die Essenz der Benutzergruppe erstellen.


 <?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; } } 

Nachdem wir Twig als Template-Engine konfiguriert haben.


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

Derzeit gibt es Probleme mit Symfony Flex und FOSUserBundle. Weitere Einzelheiten finden Sie unter den Links Nr. 2562 , Nr. 2708 und Nr. 2801 .


Obwohl diese Probleme nicht behoben sind, müssen Sie vor der Installation des Sonata User Bundle einige zusätzliche Manipulationen 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 

Danach können Sie das Bundle installieren.


 $ composer require sonata-project/user-bundle 

ACL-Einrichtung


In Symfony 4 wurden die ACLs in ein separates symfony/acl-bundle . Daher muss es separat installiert werden.


 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 

Lehre konfigurieren


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

Arbeit mit Mail einrichten


Da die Arbeit mit E-Mails im Rahmen dieses Artikels nicht berücksichtigt wird, geben wir einen Stub anstelle eines echten Dienstes an.


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

Benutzerpaket-Integration in 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 

Jetzt können Sie die ACL und die Datenbank aktualisieren.


 $ bin/console acl:init 

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

Erstellen Sie einen Superuser. Geben Sie die Namens- und Kennwortdemo an.


 $ 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 

Um unsere Admin-Klassen zusammen mit ACLs korrekt zu konfigurieren, müssen Sie Änderungen an den Einstellungen vornehmen.


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

Nach dem Ausführen der folgenden:


 $ 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"] 

Wenn Sie nun versuchen, zur Adresse http://127.0.0.1:8000/admin zu wechseln, werden wir zu http://127.0.0.1:8000/admin/login weitergeleitet .



Geben Sie Demo / Demo ein und gelangen Sie in den administrativen Teil.



Zusammenfassung


Nach all den Manipulationen haben wir einen funktionierenden administrativen Teil von Sonata Admin auf Symfony 4 zusammen mit der Authentifizierung und Autorisierung mit Sonata User + ACL erhalten.


Danke an alle. Wenn Sie Fragen und Kommentare haben, werde ich diese in den Kommentaren anhören.

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


All Articles