Php 如何在Symfony 4中使用自定义集合

Php 如何在Symfony 4中使用自定义集合,php,symfony,doctrine-orm,doctrine,symfony4,Php,Symfony,Doctrine Orm,Doctrine,Symfony4,我想为我的Symfony 4应用程序使用自定义集合类。以下场景是我试图实现的一个示例: 我有一个post-collection类,它有一些用于过滤和映射数据的实用程序 class PostArrayCollection extends ArrayCollection implements PostCollectionInterface { public function mapTitles() { return $this->map(function (Po

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

我有一个post-collection类,它有一些用于过滤和映射数据的实用程序

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;
        });
    }
}
也是作为条令实体的用户类

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...
}
当手动创建一个新对象时,例如在单元测试中,上面的方法是有效的。但从存储库加载实体时,它将不起作用,因为这样集合将填充
doctor\ORM\PersistentCollection
对象

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

我确实找到了这个页面,但我找不到如何将它集成到Symfony 4中

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


您找到的是doc for Doctrine Collections软件包

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

你想做的事现在用ORM是不可能的


已计划。

如果是自定义集合,则您的自定义集合必须充当装饰程序,并签入您的
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;
    }
}

优秀的解决方案。在我的例子中,这不是一个完整的解决方案,因为我使用DDD,我想使领域不可知于教义。我正在使用自定义集合,我不知道如何将集合映射到我的自定义集合

您是否尝试过使用存储库而不是扩展ArrayCollection?例如,
$userRepository->getUserPostsFrom(User$User,DateTime$from)
哪个用户“创建”帖子,哪个日期“发布”帖子?可以通过单个请求完成操作,而不是事后筛选。。。