在 Symfony 中加载固定装置时订阅者是否工作?
Do Subscribers work while loading Fixtures in Symfony?
我尝试使用命令 php bin/console d:f:l
在 Symfony 5 上 运行 下面的 fixture。
我收到此错误:SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'contact_email' cannot be null
通过 CRUD 手动创建 Post 实体时,相同的代码逻辑工作正常。固定装置与订阅者(事件)不兼容还是我弄错了?
谢谢。
编辑:我也在使用 EasyAdmin Bundle 3。
App\DataFixtures.php\AppFixtures.php
<?php
namespace App\DataFixtures;
use App\Entity\User;
use App\Entity\Author;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class AppFixtures extends Fixture
{
/** @var User[] */
private $users = [];
/** @var Author[] */
private $authors = [];
/** @var UserPasswordHasherInterface */
private $hasher;
public function __construct(UserPasswordHasherInterface $hasher)
{
$this->hasher = $hasher;
}
public function load(ObjectManager $manager): void
{
$this->createUsers();
foreach($this->users as $user) $manager->persist($user);
$this->createAuthors();
foreach($this->authors as $author) $manager->persist($author);
$manager->flush();
}
public function createUsers(): void
{
$admin = (new User)
->setUsername('admin')
->setEmail('admin@admin.com')
->setRoles(['ROLE_ADMIN'])
->setFirstname('Edouard')
->setLastname('Proust');
$admin->setPassword($this->hasher->hashPassword($admin, 'admin'));
$this->users[] = $admin;
}
public function createAuthors(): void
{
foreach($this->users as $user) {
if(in_array('ROLE_ADMIN', $user->getRoles())) {
$author = (new Author)
->setUser($user)
->setAvatar('#')
->setBio('Bio')
// The line i want to get rid of:
// ->setContactEmail($user->getEmail())
;
$this->authors[] = $author;
}
}
}
}
App\EventListener\AuthorSubscriber.php
<?php
namespace App\EventListener;
use App\Entity\Author;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
class AuthorSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
BeforeEntityPersistedEvent::class => 'setContactEmail',
];
}
public function setContactEmail(BeforeEntityPersistedEvent $event)
{
/** @var Author */
$entity = $event->getEntityInstance();
if($entity instanceof Author) {
if(!$entity->getContactEmail()) {
$user = $entity->getUser();
$contactEmail = $user ? $user->getEmail() : '#';
$entity->setContactEmail($contactEmail);
}
}
}
}
EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent:class
不是正确的 Symfony 事件名称。您可能应该使用 Doctrine\ORM\Events::prePersist
.
另请检查您的 DoctrineBundle 版本。如果你使用默认的 services.yaml 配置和低于 2.1 的 DoctrineBundle,你必须配置 services.yaml
为:
App\EventListener\AuthorSubscriber:
tags:
- name: 'doctrine.event_subscriber'
您可以在这里阅读更多内容:https://symfony.com/doc/current/doctrine/events.html#doctrine-lifecycle-subscribers
我尝试使用命令 php bin/console d:f:l
在 Symfony 5 上 运行 下面的 fixture。
我收到此错误:SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'contact_email' cannot be null
通过 CRUD 手动创建 Post 实体时,相同的代码逻辑工作正常。固定装置与订阅者(事件)不兼容还是我弄错了?
谢谢。
编辑:我也在使用 EasyAdmin Bundle 3。
App\DataFixtures.php\AppFixtures.php
<?php
namespace App\DataFixtures;
use App\Entity\User;
use App\Entity\Author;
use Doctrine\Persistence\ObjectManager;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
class AppFixtures extends Fixture
{
/** @var User[] */
private $users = [];
/** @var Author[] */
private $authors = [];
/** @var UserPasswordHasherInterface */
private $hasher;
public function __construct(UserPasswordHasherInterface $hasher)
{
$this->hasher = $hasher;
}
public function load(ObjectManager $manager): void
{
$this->createUsers();
foreach($this->users as $user) $manager->persist($user);
$this->createAuthors();
foreach($this->authors as $author) $manager->persist($author);
$manager->flush();
}
public function createUsers(): void
{
$admin = (new User)
->setUsername('admin')
->setEmail('admin@admin.com')
->setRoles(['ROLE_ADMIN'])
->setFirstname('Edouard')
->setLastname('Proust');
$admin->setPassword($this->hasher->hashPassword($admin, 'admin'));
$this->users[] = $admin;
}
public function createAuthors(): void
{
foreach($this->users as $user) {
if(in_array('ROLE_ADMIN', $user->getRoles())) {
$author = (new Author)
->setUser($user)
->setAvatar('#')
->setBio('Bio')
// The line i want to get rid of:
// ->setContactEmail($user->getEmail())
;
$this->authors[] = $author;
}
}
}
}
App\EventListener\AuthorSubscriber.php
<?php
namespace App\EventListener;
use App\Entity\Author;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
class AuthorSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
BeforeEntityPersistedEvent::class => 'setContactEmail',
];
}
public function setContactEmail(BeforeEntityPersistedEvent $event)
{
/** @var Author */
$entity = $event->getEntityInstance();
if($entity instanceof Author) {
if(!$entity->getContactEmail()) {
$user = $entity->getUser();
$contactEmail = $user ? $user->getEmail() : '#';
$entity->setContactEmail($contactEmail);
}
}
}
}
EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent:class
不是正确的 Symfony 事件名称。您可能应该使用 Doctrine\ORM\Events::prePersist
.
另请检查您的 DoctrineBundle 版本。如果你使用默认的 services.yaml 配置和低于 2.1 的 DoctrineBundle,你必须配置 services.yaml
为:
App\EventListener\AuthorSubscriber:
tags:
- name: 'doctrine.event_subscriber'
您可以在这里阅读更多内容:https://symfony.com/doc/current/doctrine/events.html#doctrine-lifecycle-subscribers