Orm Symfony 3获取实体内部的当前用户

Orm Symfony 3获取实体内部的当前用户,orm,symfony,fosuserbundle,Orm,Symfony,Fosuserbundle,我想知道是否有一种方法可以用FOSUserBundle的实体用户初始化属性所有者,以便它包含创建帖子的用户 我希望在构造函数中执行此操作,如下所示 namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Table(name="post") * @ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository") */ class Po

我想知道是否有一种方法可以用FOSUserBundle的实体用户初始化属性所有者,以便它包含创建帖子的用户

我希望在构造函数中执行此操作,如下所示

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 */ ;
  }

}
有没有办法将构造函数中的注释替换为其他内容

谢谢你的回答不,没有。[*]

至少有两种方法可以解决这个问题:

  • 通过工厂服务创建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);
        }
    }
    
    (对于本例,您必须将
    Post
    构造函数修改为 接受所有者作为参数)

    在services.yml中:

    services:
        post_factory:
            class: My\Bundle\EntityFactory\PostFactory
            arguments: [@security.token_storage]
    
    services:
        post_owner_assignment_listener:
            class: My\Bundle\EventListener\PostOwnerAssignmentListener
            arguments: [@security.token_storage]
            tags:
                - { name: doctrine.event_listener, event: prePersit }
    
    要从控制器创建实体,请执行以下操作:

    $post = $this->container->get('post_factory')->createPost();
    
  • 如果您能够容忍,则只有在您坚持使用 实体,您可以使用条令事件侦听器:

    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());
            }
        }
    }
    
    在services.yml中:

    services:
        post_factory:
            class: My\Bundle\EntityFactory\PostFactory
            arguments: [@security.token_storage]
    
    services:
        post_owner_assignment_listener:
            class: My\Bundle\EventListener\PostOwnerAssignmentListener
            arguments: [@security.token_storage]
            tags:
                - { name: doctrine.event_listener, event: prePersit }
    
    这样做的好处是,无论如何、在何处,都可以指定所有者 将创建
    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();

对于具有自动连线和实体事件侦听器的Symfony 4+

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());
        }
    }
}
在/EventListener/postpresistenstener.php中:

namespace-App\EventListener;
使用App\Entity\Post;
使用条令\ORM\Event\LifecycleEventArgs;
使用Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
类后置侦听器
{
私人储存器;;
公共函数构造(TokenStorageInterface$tokenStorage)
{
$this->tokenStorage=$tokenStorage;
}
公共功能前置器(Post$Post,LifecycleEventArgs$event)
{
$post->setOwner($this->tokenStorage->getToken()->getUser());
}
}
在services.yaml中:

服务:
App\EventListener\PostListener:
自动连线:对
标签:
-{name:doctor.orm.event_侦听器,实体:'App\entity\Post',事件:prePersist}
需要修改services.yaml,因为Symfony无法知道此自定义服务已标记为挂接在
原则上。事件\u侦听器


按照要求,这在实体级别起作用,以确保控制器不处理所有者值。

原则实际上不使用构造函数,所以不。为什么不在Post和用户之间设置一个关系?关系已经存在,创建新帖子时,所有者属性将使用当前连接的用户初始化。因此,您只需在首次创建新帖子时初始化所有者?如果是,以下两个答案都是有效的。就我个人而言,我会使用工厂方法,可能会将create方法添加到post存储库中,而不是一个独立的类。但所有列出的方法都有意义。@DonOmondi-没错。懒惰是成为优秀开发人员的关键因素。只有傻瓜才会比他们必须的更努力。事实上,我很懒,我希望代码在Symfony 4中简单易读,在控制器上下文中,你可以做
$this->getUser()
@skirato OP的问题是关于实体上下文,如果您不能这样做,我必须将doctor.orm.event\u listener更改为doctor.event\u listener。@请小心,如果您使用
doctor.event\u listener
您不能在YAML文件中指定“实体”字段。因此,它将被所有实体调用。如果您想为任何实体执行操作,或者使用EntityClass的
$event->getObject()instanceof筛选出实体,这是很好的