{"id":292177,"date":"2019-07-17T09:01:56","date_gmt":"2019-07-17T09:01:56","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=292177"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=292177","title":{"rendered":"\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Sonata Admin \u043d\u0430 Symfony 4"},"content":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/n2\/xh\/96\/n2xh96fzfztxqianwy4t1pehha4.png\"><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e \u0432\u0441\u0435\u0445. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 Symfony 4 \u0438 Sonata Admin.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u0440\u0435\u0439 \u0448\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u043e\u0439 \u0434\u043b\u044f \u043c\u0435\u043d\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u043c\u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c<br \/>  \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Sonata Admin \u043d\u0430 Symfony 4, \u0442\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043c\u0430\u0441\u0441\u043e\u0439 \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0435\u0439<br \/>  \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0441\u0430\u043c\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u0440\u0430\u0441\u043a\u0438\u0434\u0430\u043d\u0430 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u0430\u043c.<\/p>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u044f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044e \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0432\u0437\u044f\u0442\u044b \u0438\u0437 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u0447\u0430\u0441\u0442\u044c \u0431\u0440\u0430\u043b\u0430\u0441\u044c \u0438\u0437 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432 \u043d\u0430 GitHub, \u0433\u0434\u0435 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u0438\u0441\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u0438 \u043f\u0443\u0442\u0438 \u0438\u0445 \u043e\u0431\u0445\u043e\u0434\u0430.<\/p>\n<p><a name=\"habracut\"><\/a>   <\/p>\n<h2 id=\"sozdaem-proekt-na-symfony\">\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 symfony<\/h2>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer create-project symfony\/skeleton sonatademo<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">$ cd sonatademo<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432\u0435\u0431 \u0441\u0435\u0440\u0432\u0435\u0440 Symfony.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ symfony serve<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"http:\/\/127.0.0.1:8000\/\">http:\/\/127.0.0.1:8000\/<\/a> \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 Symfony. \u0417\u043d\u0430\u0447\u0438\u0442 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/or\/fj\/is\/orfjisfkh5hnvoxwf2nwqrmpkxi.png\"><\/p>\n<p>  <\/p>\n<h2 id=\"ustanavlivaem-sonata-admin\">\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c Sonata Admin<\/h2>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer require sonata-project\/admin-bundle<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043e\u0434\u043d\u0443 \u0438\u0437 \u0442\u0440\u0435\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"http:\/\/sonata-project.org\/bundles\/doctrine-orm-admin\/master\/doc\/index.html\">SonataDoctrineORMAdminBundle<\/a> (\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Doctrine ORM);<\/li>\n<li><a href=\"http:\/\/sonata-project.org\/bundles\/mongo-admin\/master\/doc\/index.html\">SonataDoctrineMongoDBAdminBundle<\/a> (\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Doctrine MongoDB ODM);<\/li>\n<li><a href=\"http:\/\/sonata-project.org\/bundles\/doctrine-phpcr-admin\/master\/doc\/index.html\">SonataDoctrinePhpcrAdminBundle<\/a> (\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 Doctrine PHPCR ODM).<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u044f \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <code>SonataDoctrineORMAdminBundle<\/code>, \u0447\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 <code>MySQL<\/code> \u0438\u043b\u0438 <code>Sqlite<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c <code>SonataDoctrineORMAdminBundle<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer require sonata-project\/doctrine-orm-admin-bundle<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 <code>Sqlite<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c .env \u0444\u0430\u0439\u043b \u0438 \u0432 \u0441\u0435\u043a\u0446\u0438\u0438 <code>###&gt; doctrine\/doctrine-bundle ###<\/code> \u043c\u0435\u043d\u044f\u0435\u043c <code>DATABASE_URL<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">DATABASE_URL=\"sqlite:\/\/\/%kernel.project_dir%\/var\/data.db\"<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a Symfony Flex \u0434\u0435\u043b\u0430\u0435\u0442 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0443 \u0437\u0430 \u043d\u0430\u0441 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435, \u0442\u043e \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/framework.yaml framework:     translator: { fallbacks: ['%locale%'] }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer dump-env dev<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"http:\/\/127.0.0.1:8000\/admin\">http:\/\/127.0.0.1:8000\/admin<\/a> \u0438 \u0432\u0438\u0434\u0438\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/mk\/d9\/th\/mkd9thdshpjvqwx4vihqq2faqky.png\"><\/p>\n<p>  <\/p>\n<h2 id=\"sozdanie-suschnostey\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0434\u0432\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0441\u0432\u044f\u0437\u044c\u044e \u043e\u0434\u0438\u043d \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?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-&gt;addresses = new ArrayCollection();     }      public function getAddresses()     {         return $this-&gt;addresses;     }      \/**      * @return string      *\/     public function getTitle(): ?string     {         return $this-&gt;title;     }      \/**      * @param string $title      * @return City      *\/     public function setTitle(string $title): City     {         $this-&gt;title = $title;         return $this;     }      \/**      * @return string      *\/     public function getDescription(): ?string     {         return $this-&gt;description;     }      \/**      * @param string $description      * @return City      *\/     public function setDescription(string $description): City     {         $this-&gt;description = $description;         return $this;     }      \/**      * @return bool      *\/     public function isBig(): ?bool     {         return $this-&gt;isBig;     }      \/**      * @param bool $isBig      * @return City      *\/     public function setIsBig(bool $isBig): City     {         $this-&gt;isBig = $isBig;         return $this;     }      public function __toString()     {         return $this-&gt;title;     } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?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-&gt;title;     }      \/**      * @param string $title      * @return Address      *\/     public function setTitle(string $title): Address     {         $this-&gt;title = $title;         return $this;     }      \/**      * @return string      *\/     public function getDescription(): ?string     {         return $this-&gt;description;     }      \/**      * @param string $description      * @return Address      *\/     public function setDescription(string $description): Address     {         $this-&gt;description = $description;         return $this;     }      \/**      * @return City      *\/     public function getCity(): ?City     {         return $this-&gt;city;     }      \/**      * @param City $city      * @return Address      *\/     public function setCity(City $city)     {         $this-&gt;city = $city;         return $this;     }      public function __toString()     {         return $this-&gt;title;     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u043c\u0441\u044f \u0441 \u0411\u0414.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">bin\/console doctrine:schema:create<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"nastroyka-suschnostey-dlya-sonata-admin\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f Sonata Admin<\/h2>\n<p>  <\/p>\n<p>\u041d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c,<br \/>  \u043a\u0430\u043a Sonata Admin \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?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-&gt;add('title', TextType::class);         $formMapper-&gt;add('description', TextareaType::class);         $formMapper-&gt;add('isBig', CheckboxType::class);     }      protected function configureDatagridFilters(DatagridMapper $datagridMapper)     {         $datagridMapper-&gt;add('title');         $datagridMapper-&gt;add('isBig');     }      protected function configureListFields(ListMapper $listMapper)     {         $listMapper-&gt;addIdentifier('title');         $listMapper-&gt;addIdentifier('isBig');     } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?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-&gt;add('title', TextType::class);         $formMapper-&gt;add('description', TextareaType::class);         $formMapper-&gt;add('city', ModelType::class, [             'class' =&gt; City::class,             'property' =&gt; 'title',         ]);     }      protected function configureDatagridFilters(DatagridMapper $datagridMapper)     {         $datagridMapper-&gt;add('title');     }      protected function configureListFields(ListMapper $listMapper)     {         $listMapper-&gt;addIdentifier('title');     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u0438 \u043a\u043b\u0430\u0441\u0441\u044b \u043d\u0443\u0436\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0432 <code>service.yaml<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># 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 }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438 \u0437\u0430\u0445\u043e\u0434\u0435 \u0432 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043e\u0448\u0438\u0431\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440<br \/>  <code>Unable to generate a URL for the named route<\/code>, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u043a\u044d\u0448 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<br \/>  \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u043d\u043e\u0432\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">bin\/console cache:clear<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 <a href=\"http:\/\/127.0.0.1:8000\/admin\">http:\/\/127.0.0.1:8000\/admin<\/a> \u0443\u0432\u0438\u0434\u0438\u043c<br \/>  \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0437 \u0434\u0432\u0443\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 <code>Address<\/code> \u0438 <code>City<\/code>, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043a\u0438 \u0438<br \/>  \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/v5\/v-\/x-\/v5v-x-c76ucdru47nfew_kbnhsu.png\"><\/p>\n<p>  <\/p>\n<h2 id=\"avtorizaciya-i-autentifikaciya\">\u0410\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?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-&gt;id;     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418 \u0437\u0430\u043e\u0434\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u0433\u0440\u0443\u043f\u043f\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<p>  <\/p>\n<pre><code class=\"php\">&lt;?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-&gt;id;     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c Twig \u043a\u0430\u043a \u0434\u0432\u0438\u0436\u043e\u043a \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">framework:     ...     templating:         engines: ['twig']<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0440\u0430\u0431\u043e\u0442\u043e\u0439 Symfony Flex \u0438 FOSUserBundle.<br \/>  \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c <a href=\"https:\/\/github.com\/FriendsOfSymfony\/FOSUserBundle\/issues\/2562\">#2562<\/a>, <a href=\"https:\/\/github.com\/FriendsOfSymfony\/FOSUserBundle\/pull\/2708\">#2708<\/a> \u0438 <a href=\"https:\/\/github.com\/FriendsOfSymfony\/FOSUserBundle\/pull\/2801\">#2801<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043d\u0435 \u0440\u0435\u0448\u0435\u043d\u044b, \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0430\u0440\u0443 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439<br \/>  \u043f\u0435\u0440\u0435\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 <code>Sonata User Bundle<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/service.yaml services:     ...     mailer:         alias: fos_user.mailer.noop         public: true<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># 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<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e, \u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0431\u0430\u043d\u0434\u043b.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ composer require sonata-project\/user-bundle<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"nastroyka-acl\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 ACL<\/h3>\n<p>  <\/p>\n<p>\u0412 Symfony 4 ACL \u0432\u044b\u043d\u0435\u0441\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u043d\u0434\u043b <code>symfony\/acl-bundle<\/code>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">composer require symfony\/acl-bundle<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/sonata_user.yaml sonata_user:     security_acl: true     manager_type: orm<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/acl.yaml acl:     connection: default<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"nastroyka-doctrine\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Doctrine<\/h3>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/doctrine.yaml doctrine:     orm:         entity_managers:             default:                 mappings:                     SonataUserBundle: ~                     FOSUserBundle: ~<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"nastroyka-raboty-s-pochtoy\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u043e\u0447\u0442\u043e\u0439<\/h3>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043f\u043e\u0447\u0442\u043e\u0439 \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u0435\u0441\u044f, \u0442\u043e<br \/>  \u0443\u043a\u0430\u0436\u0435\u043c \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0443 \u0432\u043c\u0435\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/sonata_user.yaml  sonata_user:     mailer: fos_user.mailer.noop<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"integraciya-user-bundle-v-sonata-admin\">\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f User Bundle \u0432 Sonata Admin<\/h3>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># 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<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/security.yaml security:     encoders:         FOS\\UserBundle\\Model\\UserInterface: sha512     acl:         connection: default     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          # -&gt; 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          # -&gt; 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 } <\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># config\/packages\/sonata_user.yaml sonata_user:   ...   class:     user: App\\Entity\\User     group: App\\Entity\\Group<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c ACL \u0438 \u0411\u0414.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ bin\/console init:acl<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">$ php bin\/console doctrine:schema:update --force<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0443\u043f\u0435\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0438\u043c\u044f <code>demo<\/code> \u0438 \u043f\u0430\u0440\u043e\u043b\u044c <code>demo<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ 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<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0448\u0438\u0445 Admin \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 ACL \u043d\u0443\u0436\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">sonata_admin:     ...     security:          handler: sonata.admin.security.handler.acl<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ bin\/console sonata:admin:setup-acl Starting ACL AdminBundle configuration  &gt; 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\"]  &gt; 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\"]  &gt; 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\"]  &gt; 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\"]<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0437\u0430\u0439\u0442\u0438 \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 <a href=\"http:\/\/127.0.0.1:8000\/admin\">http:\/\/127.0.0.1:8000\/admin<\/a> \u043d\u0430\u0441 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u0442<br \/>  \u043d\u0430 <a href=\"http:\/\/127.0.0.1:8000\/admin\/login\">http:\/\/127.0.0.1:8000\/admin\/login<\/a>.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/d_\/lp\/tb\/d_lptbxdgrx4tlwjld8xosducio.png\"><\/p>\n<p>  <\/p>\n<p>\u0412\u0432\u043e\u0434\u0438\u043c demo\/demo \u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u043c \u0432 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/gp\/lm\/p9\/gplmp9c_xk6qvkisevlrit9u3z0.png\"><\/p>\n<p>  <\/p>\n<h2 id=\"itogi\">\u0418\u0442\u043e\u0433\u0438<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0445 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0443\u044e \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c Sonata Admin<br \/>  \u043d\u0430 Symfony 4 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 c \u043f\u043e\u043c\u043e\u0449\u044c\u044e Sonata User + ACL.<\/p>\n<p>  <\/p>\n<p>\u0412\u0441\u0435\u043c \u0441\u043f\u0430\u0441\u0438\u0431\u043e. \u0415\u0441\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f, \u0442\u043e \u044f \u0432\u044b\u0441\u043b\u0443\u0448\u0430\u044e \u0438\u0445 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<\/div>\n<p>               <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/460345\/\"> https:\/\/habr.com\/ru\/post\/460345\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/n2\/xh\/96\/n2xh96fzfztxqianwy4t1pehha4.png\"><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e \u0432\u0441\u0435\u0445. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 Symfony 4 \u0438 Sonata Admin.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u0440\u0435\u0439 \u0448\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u043e\u0439 \u0434\u043b\u044f \u043c\u0435\u043d\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u043c\u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c<br \/>  \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c Sonata Admin \u043d\u0430 Symfony 4, \u0442\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u043c\u0430\u0441\u0441\u043e\u0439 \u043d\u0435\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u0435\u0439<br \/>  \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0441\u0430\u043c\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u0440\u0430\u0441\u043a\u0438\u0434\u0430\u043d\u0430 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u0430\u043c.<\/p>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u044f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044e \u0432\u0435\u0441\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439. \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0432\u0437\u044f\u0442\u044b \u0438\u0437 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u0447\u0430\u0441\u0442\u044c \u0431\u0440\u0430\u043b\u0430\u0441\u044c \u0438\u0437 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432 \u043d\u0430 GitHub, \u0433\u0434\u0435 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u043b\u0438\u0441\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u044b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0435 \u043a\u0430\u043c\u043d\u0438 \u0438 \u043f\u0443\u0442\u0438 \u0438\u0445 \u043e\u0431\u0445\u043e\u0434\u0430.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-292177","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/292177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=292177"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/292177\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=292177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=292177"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=292177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}