覆盖方法或 EventListener:在 EasyAdmin 中第一次停止创建过程并显示警告?
Override Method or EventListener: stop creation process and show warning just the first time in EasyAdmin?
我在我的 SF 3.3 项目中使用 EasyAdmin,但我需要实现一些与 EasyAdmin 的构建方式不同的东西。看看下面的图片:
您可能会注意到,一个用户可以在多个 GroupingRole
中。获得这些信息的挑战是:
- 检查用户是否已分配给任何其他
GroupingRole
- 如果条件满足条件,则显示警告消息 "The user A is already assigned to GroupingRole A" 并阻止创建记录。 (此消息可能在弹出窗口、javascript 警报或来自 Bootstrap 的警报中 - 因为 EA 已经在使用它)
- 当管理员再次单击 "Save changes" 时,应该会创建记录。
我想用这种方法实现的是提醒管理员该用户已经加入任何其他组,但不会阻止他创建记录。
我已经通过重写该实体的 prePersist
方法实现了其中的一部分(见下文):
class AdminController extends BaseAdminController
{
/**
* Check if the users has been assigned to any group
*/
protected function prePersistGroupingRoleEntity($entity)
{
$usersToGroupRoleEntities = $this->em->getRepository('CommonBundle:UsersToGroupRole')->findAll();
$usersToGroupRole = [];
/** @var UsersToGroupRole $groupRole */
foreach ($usersToGroupRoleEntities as $groupRole) {
$usersToGroupRole[$groupRole->getGroupingRoleId()][] = $groupRole->getUsersId();
}
$usersInGroup = [];
/** @var Users $userEntity */
foreach ($entity->getUsersInGroup() as $userEntity) {
foreach ($usersToGroupRole as $group => $users) {
if (\in_array($userEntity->getId(), $users, true)) {
$usersInGroup[$group][] = $userEntity->getId();
}
}
}
$groupingRoleEnt = $this->em->getRepository('CommonBundle:GroupingRole');
$usersEnt = $this->em->getRepository('CommonBundle:Users');
$message = [];
foreach ($usersInGroup as $group => $user) {
foreach($user as $usr) {
$message[] = sprintf(
'The user %s already exists in %s group!',
$usersEnt->find($usr)->getEmail(),
$groupingRoleEnt->find($group)->getName()
);
}
}
}
}
我不知道如何停止创建记录,而是仅在第一次单击按钮时显示警告,因为第二次并发出警告我应该允许创建记录.
任何人都可以给我一些想法and/or建议吗?
更新:添加实体信息
除了上面显示的代码之外,还有参与此过程的实体:
/**
* @ORM\Entity
* @ORM\Table(name="grouping_role")
*/
class GroupingRole
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer",unique=true,nullable=false)
* @ORM\GeneratedValue
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="role_name", type="string", nullable=false)
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="role_description", type="string", nullable=false)
*/
private $description;
/**
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="Schneider\QuoteBundle\Entity\Distributor", inversedBy="groupingRole")
* @ORM\JoinTable(name="grouping_to_role",
* joinColumns={
* @ORM\JoinColumn(name="grouping_role_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="DistributorID", referencedColumnName="DistributorID", nullable=false)
* }
* )
*
* @Assert\Count(
* min = 1,
* minMessage = "You must select at least one Distributor"
* )
*/
private $distributorGroup;
/**
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="CommonBundle\Entity\Users", inversedBy="usersGroup")
* @ORM\JoinTable(name="users_to_group_role",
* joinColumns={
* @ORM\JoinColumn(name="grouping_role_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="users_id", referencedColumnName="users_id", nullable=false)
* }
* )
*
* @Assert\Count(
* min = 1,
* minMessage = "You must select at least one user"
* )
*/
private $usersInGroup;
/**
* Constructor
*/
public function __construct()
{
$this->distributorGroup = new ArrayCollection();
$this->usersInGroup = new ArrayCollection();
}
}
/**
* @ORM\Entity()
* @ORM\Table(name="users_to_group_role")
*/
class UsersToGroupRole
{
/**
* @var int
*
* @ORM\Id()
* @ORM\Column(type="integer",nullable=false)
* @Assert\Type(type="integer")
* @Assert\NotNull()
*/
protected $usersId;
/**
* @var int
*
* @ORM\Id()
* @ORM\Column(type="integer", nullable=false)
* @Assert\Type(type="integer")
* @Assert\NotNull()
*/
protected $groupingRoleId;
}
在 EasyAdminBundle 中使用表单验证方法的一个小例子:
class AdminController extends EasyAdminController
{
// ...
protected function create<EntityName>EntityFormBuilder($entity, $view)
{
$builder = parent::createEntityFormBuilder($entity, $view);
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
$flag = false;
if (isset($data['flag'])) {
$flag = $data['flag'];
unset($data['flag']);
}
$key = md5(json_encode($data));
if ($flag !== $key) {
$event->getForm()->add('flag', HiddenType::class, ['mapped' => false]);
$data['flag'] = $key;
$event->setData($data);
}
});
return $builder;
}
protected function get<EntityName>EntityFormOptions($entity, $view)
{
$options = parent::getEntityFormOptions($entity, $view);
$options['validation_groups'] = function (FormInterface $form) {
if ($form->has('flag')) {
return ['Default', 'CheckUserGroup'];
}
return ['Default'];
};
$options['constraints'] = new Callback([
'callback' => function($entity, ExecutionContextInterface $context) {
// validate here and adds the violation if applicable.
$context->buildViolation('Warning!')
->atPath('<field>')
->addViolation();
},
'groups' => 'CheckUserGroup',
]);
return $options;
}
}
请注意,PRE_SUBMIT
事件在验证过程发生之前触发。
flag
字段是在提交表单后第一次(动态)添加的,因此添加了验证组 CheckUserGroup
并且回调约束完成了它的工作。后来第二次提交的数据中包含flag
hash(如果数据没有变化),没有添加flag
字段,所以也没有添加验证组,保存实体(同上)如果回调约束第一次没有添加违规)。
此外(如果您愿意)您可以在目标实体的自定义表单类型中执行所有这些操作。
我在我的 SF 3.3 项目中使用 EasyAdmin,但我需要实现一些与 EasyAdmin 的构建方式不同的东西。看看下面的图片:
您可能会注意到,一个用户可以在多个 GroupingRole
中。获得这些信息的挑战是:
- 检查用户是否已分配给任何其他
GroupingRole
- 如果条件满足条件,则显示警告消息 "The user A is already assigned to GroupingRole A" 并阻止创建记录。 (此消息可能在弹出窗口、javascript 警报或来自 Bootstrap 的警报中 - 因为 EA 已经在使用它)
- 当管理员再次单击 "Save changes" 时,应该会创建记录。
我想用这种方法实现的是提醒管理员该用户已经加入任何其他组,但不会阻止他创建记录。
我已经通过重写该实体的 prePersist
方法实现了其中的一部分(见下文):
class AdminController extends BaseAdminController
{
/**
* Check if the users has been assigned to any group
*/
protected function prePersistGroupingRoleEntity($entity)
{
$usersToGroupRoleEntities = $this->em->getRepository('CommonBundle:UsersToGroupRole')->findAll();
$usersToGroupRole = [];
/** @var UsersToGroupRole $groupRole */
foreach ($usersToGroupRoleEntities as $groupRole) {
$usersToGroupRole[$groupRole->getGroupingRoleId()][] = $groupRole->getUsersId();
}
$usersInGroup = [];
/** @var Users $userEntity */
foreach ($entity->getUsersInGroup() as $userEntity) {
foreach ($usersToGroupRole as $group => $users) {
if (\in_array($userEntity->getId(), $users, true)) {
$usersInGroup[$group][] = $userEntity->getId();
}
}
}
$groupingRoleEnt = $this->em->getRepository('CommonBundle:GroupingRole');
$usersEnt = $this->em->getRepository('CommonBundle:Users');
$message = [];
foreach ($usersInGroup as $group => $user) {
foreach($user as $usr) {
$message[] = sprintf(
'The user %s already exists in %s group!',
$usersEnt->find($usr)->getEmail(),
$groupingRoleEnt->find($group)->getName()
);
}
}
}
}
我不知道如何停止创建记录,而是仅在第一次单击按钮时显示警告,因为第二次并发出警告我应该允许创建记录.
任何人都可以给我一些想法and/or建议吗?
更新:添加实体信息
除了上面显示的代码之外,还有参与此过程的实体:
/**
* @ORM\Entity
* @ORM\Table(name="grouping_role")
*/
class GroupingRole
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer",unique=true,nullable=false)
* @ORM\GeneratedValue
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="role_name", type="string", nullable=false)
*/
private $name;
/**
* @var string
*
* @ORM\Column(name="role_description", type="string", nullable=false)
*/
private $description;
/**
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="Schneider\QuoteBundle\Entity\Distributor", inversedBy="groupingRole")
* @ORM\JoinTable(name="grouping_to_role",
* joinColumns={
* @ORM\JoinColumn(name="grouping_role_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="DistributorID", referencedColumnName="DistributorID", nullable=false)
* }
* )
*
* @Assert\Count(
* min = 1,
* minMessage = "You must select at least one Distributor"
* )
*/
private $distributorGroup;
/**
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="CommonBundle\Entity\Users", inversedBy="usersGroup")
* @ORM\JoinTable(name="users_to_group_role",
* joinColumns={
* @ORM\JoinColumn(name="grouping_role_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="users_id", referencedColumnName="users_id", nullable=false)
* }
* )
*
* @Assert\Count(
* min = 1,
* minMessage = "You must select at least one user"
* )
*/
private $usersInGroup;
/**
* Constructor
*/
public function __construct()
{
$this->distributorGroup = new ArrayCollection();
$this->usersInGroup = new ArrayCollection();
}
}
/**
* @ORM\Entity()
* @ORM\Table(name="users_to_group_role")
*/
class UsersToGroupRole
{
/**
* @var int
*
* @ORM\Id()
* @ORM\Column(type="integer",nullable=false)
* @Assert\Type(type="integer")
* @Assert\NotNull()
*/
protected $usersId;
/**
* @var int
*
* @ORM\Id()
* @ORM\Column(type="integer", nullable=false)
* @Assert\Type(type="integer")
* @Assert\NotNull()
*/
protected $groupingRoleId;
}
在 EasyAdminBundle 中使用表单验证方法的一个小例子:
class AdminController extends EasyAdminController
{
// ...
protected function create<EntityName>EntityFormBuilder($entity, $view)
{
$builder = parent::createEntityFormBuilder($entity, $view);
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
$flag = false;
if (isset($data['flag'])) {
$flag = $data['flag'];
unset($data['flag']);
}
$key = md5(json_encode($data));
if ($flag !== $key) {
$event->getForm()->add('flag', HiddenType::class, ['mapped' => false]);
$data['flag'] = $key;
$event->setData($data);
}
});
return $builder;
}
protected function get<EntityName>EntityFormOptions($entity, $view)
{
$options = parent::getEntityFormOptions($entity, $view);
$options['validation_groups'] = function (FormInterface $form) {
if ($form->has('flag')) {
return ['Default', 'CheckUserGroup'];
}
return ['Default'];
};
$options['constraints'] = new Callback([
'callback' => function($entity, ExecutionContextInterface $context) {
// validate here and adds the violation if applicable.
$context->buildViolation('Warning!')
->atPath('<field>')
->addViolation();
},
'groups' => 'CheckUserGroup',
]);
return $options;
}
}
请注意,PRE_SUBMIT
事件在验证过程发生之前触发。
flag
字段是在提交表单后第一次(动态)添加的,因此添加了验证组 CheckUserGroup
并且回调约束完成了它的工作。后来第二次提交的数据中包含flag
hash(如果数据没有变化),没有添加flag
字段,所以也没有添加验证组,保存实体(同上)如果回调约束第一次没有添加违规)。
此外(如果您愿意)您可以在目标实体的自定义表单类型中执行所有这些操作。