par*_*s93 1 orm symfony fosuserbundle
我想知道是否有一种方法可以使用FOSUserBundle的实体User初始化属性所有者,以便它包含创建Post的用户
我想在构造函数中执行此操作,如下所示.
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="post")
* @ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository")
*/
class Post
{
/* here are defined some attributs */
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="posts")
* @ORM\JoinColumn(name="owner", referencedColumnName="id")
*/
private $owner;
public function __construct()
{
$this->owner = /* get current user */ ;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法通过替换构造函数中的注释来做到这一点?
谢谢您的回答
不,没有.[*]
至少有两种方法可以解决这个问题:
通过填充owner属性的工厂服务创建Post实体
:
namespace My\Bundle\EntityFactory;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use My\Bundle\Entity\Post;
class PostFactory
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function createPost()
{
$user = $this->tokenStorage()->getToken()->getUser();
$post = new Post($user);
}
}
Run Code Online (Sandbox Code Playgroud)
(对于此示例,您必须修改Post构造函数以接受所有者作为参数)
在services.yml中:
services:
post_factory:
class: My\Bundle\EntityFactory\PostFactory
arguments: [@security.token_storage]
Run Code Online (Sandbox Code Playgroud)
要从控制器创建实体:
$post = $this->container->get('post_factory')->createPost();
Run Code Online (Sandbox Code Playgroud)如果您可以容忍只有在持久化实体后才设置所有者,则可以使用doctrine事件监听器:
namespace My\Bundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use My\Bundle\Entity\Post;
class PostOwnerAssignmentListener
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function prePersist(LifecycleEventArgs $event)
{
$entity = $event->getEntity();
if ($entity instanceof Post && !$entity->getOwner()) {
$entity->setOwner($this->tokenStorage->getToken()->getUser());
}
}
}
Run Code Online (Sandbox Code Playgroud)
在services.yml中:
services:
post_owner_assignment_listener:
class: My\Bundle\EventListener\PostOwnerAssignmentListener
arguments: [@security.token_storage]
tags:
- { name: doctrine.event_listener, event: prePersit }
Run Code Online (Sandbox Code Playgroud)
这里的优点是无论Post创建方式和位置如何,都会分配所有者.
[*]:从技术上来说,默认情况下app.php你可以通过global $kernel;在你的构造函数中声明并从那里开始访问内核,然而这是非常强烈的劝阻并且可能以奇怪和微妙的方式打破.
我认为你把这个问题过于复杂化了。当您在控制器中创建新帖子时,在控制器或存储库中执行如下操作:
use AppBundle\Entity\Post; //at top of controller
$em = $this->getDoctrine()->getManager();
$user = $this->container->get('security.token_storage')->getToken()->getUser();
$post = new Post();
$em->persist( $post );
$post->setOwner( $user );
// set other fields in your post entity
$em->flush();
Run Code Online (Sandbox Code Playgroud)