【问题标题】:How to use a custom collection in Symfony 4如何在 Symfony 4 中使用自定义集合
【发布时间】:2019-02-25 13:10:37
【问题描述】:

我想为我的 Symfony 4 应用程序使用自定义集合类。以下场景是我想要实现的一个示例:

我有一个帖子收集类,它有一些用于过滤和映射数据的实用程序。

class PostArrayCollection extends ArrayCollection implements PostCollectionInterface
{
    public function mapTitles()
    {
        return $this->map(function (Post $post) {
            return $post->getTitle();
        });
    }

    public function filterPublishedAfterDate(DateTime $from)
    {
        return $this->filter(function (Post $post) use ($from) {
            return $post->publishedDate() > $from;
        });
    }
}

也是用户类,它是一个 Doctrine 实体。

class User
{
    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Post", mappedBy="post", cascade={"persist"})
     */
    private $posts;

    public function __construct()
    {
        $this->posts = new PostArrayCollection();
    }

    public function getPosts(): PostCollectionInterface
    {
        return $this->posts;
    }
}

然后在助手或控制器中有一个方法将访问用户的数据,如下所示:

public function showPublishedPostTitlesForUser(User $user)
{
    $publishedPostTitles = $user->getPosts()
        ->filterPublishedAfterDate(new DateTime())
        ->mapTitles();

    // Render the titles...
}

上述方法在手动创建新对象时有效,例如在单元测试中。但是从存储库加载实体时它不起作用,因为这样集合将被Doctrine\ORM\PersistentCollection 对象填充。

我现在的问题是,如何配置我的应用,以便在加载实体时可以使用自定义持久集合(例如 PersistentPostCollection)?

我确实找到了这个页面https://www.doctrine-project.org/projects/doctrine-collections/en/latest/lazy-collections.html#lazy-collections,但我找不到如何将它集成到 Symfony 4 中。

注意:上面的场景是一个简单的例子,目的是为了让这个问题简短易懂。我知道在使用存储库获取正确数据时可以避免整个问题。但这不是我在这里寻找的。这个问题是关于理解 Symfony 4 中 Doctrine 集合的可能性。

【问题讨论】:

  • 您是否尝试过使用存储库而不是扩展 ArrayCollection?例如。 $userRepository->getUserPostsFrom(User $user, DateTime $from) 获取帖子“createdBy”用户和“发布”日期?可以通过单个请求完成您的操作,而不是事后过滤...

标签: php symfony doctrine-orm doctrine symfony4


【解决方案1】:

你找到的是 Doctrine Collections 包的文档。

Doctrine ORM 使用 Doctrine Collections 包,但它们是相互独立的包。因此,您可以创建自定义集合这一事实并不意味着 ORM 会尊重这一点。

Doctrine ORM 现在无法实现您想要做的事情。

feature of custom collections 预定为next major Doctrine ORM version

【讨论】:

    【解决方案2】:

    如果它是您的自定义集合,您的自定义集合必须充当装饰器并检查您的 getPosts() 方法。

    PostArrayCollection 看起来像这样

    class PostArrayCollection implements Collection, Selectable, PostCollectionInterface
    {
        /**
         * @var ArrayCollection|PersistentCollection
         */
        private $collection;
    
        public static function fromItems(Post ...$elements)
        {
            return new self(new ArrayCollection($elements));
        }
    
        public static function fromDoctrine(PersistentCollection $collection)
        {
            return new self($collection);
        }
    
        private function __construct(Collection $collection)
        {
            $this->collection = $collection;
        }
    
        public function mapTitles()
        {
            return $this->collection->map(function (Post $post) {
                return $post->getTitle();
            });
        }
    
        public function filterPublishedAfterDate(DateTime $from)
        {
            return $this->collection->filter(function (Post $post) use ($from) {
                return $post->publishedDate() > $from;
            });
        }
    
        // TODO implement all other methods and delegate it to $this->collection
    }
    

    User 类将如下所示。

    class User
    {
        /**
         * @ORM\OneToMany(targetEntity="App\Entity\Post", mappedBy="post", cascade={"persist"})
         */
        private $posts;
    
        public function __construct()
        {
            $this->posts = PostArrayCollection::fromItems();
        }
    
        public function getPosts(): PostCollectionInterface
        {
            if ($this->posts instanceof PersistentCollection) {
                $this->posts = PostArrayCollection::fromDoctrine($this->posts);
            }
            return $this->posts;
        }
    }
    

    【讨论】:

      【解决方案3】:

      优秀的解决方案。就我而言,这不是一个完整的解决方案,因为我使用的是 DDD,并且我想让域与 Doctrine 无关。我正在使用自定义集合,但我不知道如何映射 Doctrine Collection tu 我的自定义集合

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-05
        • 2014-06-30
        • 2018-10-18
        • 2019-05-23
        • 1970-01-01
        • 2018-06-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多