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

时间:2017-02-03 23:11:26

标签: orm symfony fosuserbundle

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

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

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

}

有没有办法通过用构造函数中的注释替换某些内容来实现这一点?

感谢您的回答

3 个答案:

答案 0 :(得分:6)

不,没有。 [*]

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

  • 通过填充的工厂服务创建您的邮政实体 owner财产:

    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]
    

    要从您的控制器创建实体:

    $post = $this->container->get('post_factory')->createPost();
    
  • 如果您能够容忍只有在您持有后才会设置所有者 实体,您可以使用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());
            }
        }
    }
    

    在services.yml:

    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;并从那里开始, 然而,这是非常强烈气馁,可能会在奇怪和微妙的情况下打破 方式。

答案 1 :(得分:3)

我认为你过分复杂化了这个问题。在控制器中创建新帖子时,无论是在控制器中还是在存储库中都执行以下操作:

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();

答案 2 :(得分:0)

对于具有自动装配和实体事件监听器的Symfony 4 +

/EventListener/PostPrePersistListener.php中:

namespace App\EventListener;

use App\Entity\Post;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class PostPrePersistListener
{
    private $tokenStorage;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function prePersist(Post $post, LifecycleEventArgs $event)
    {
        $post->setOwner($this->tokenStorage->getToken()->getUser());
    }
}

services.yaml中:

services:
    App\EventListener\PostPrePersistListener:
        autowire: true 
        tags:
            - { name: doctrine.orm.event_listener, entity: 'App\Entity\Post', event: prePersist }

需要修改 services.yaml ,因为Symfony无法知道此自定义服务已被标记为挂在doctrine.event_listener

这按要求在实体级别起作用,以确保Controller不处理 owner 值。