【问题标题】:PHP Doctrine2 persisted Entity vs new EntityPHP Doctrine2 持久化实体与新实体
【发布时间】:2016-02-24 21:37:29
【问题描述】:

我浏览了整个网络,似乎只有我对此感到恼火/沮丧...
让我解释一下。

我正在使用 Doctrine2 构建一系列实体
像这样的
(省略所有 Doctrine 注释、getter 和 setter):

<?php

class Article
{
    protected $id;
    protected $name;
    protected $categories = [];
}

class Category
{
    protected $id;
    protected $name;
    protected $articles = [];
}

// create some categories
$cat1 = new Category();
$cat1->setName('cat-01');

$cat2 = new Category();
$cat2->setName('cat-02');

$cat3 = new Category();
$cat3->setName('cat-03');

// new Article
$article = new Article();
$article->setName('foo');
$article->setCategories([$cat1, $cat2, $cat3]);

现在,如果你需要过滤文章的类别,你必须使用 array_filter();

$cats = array_filter($article->getCategories(), function($cat) {
    return $cat->getName() === 'cat-01';
});

对....有道理。

但是,一旦 Article 对象被持久化并从 DB 中恢复,您就可以使用 PersistentCollection::filter(Closure $c) 方法 array_filter 不起作用

$entityManager->persist($article);
$entityManager->flush();


$article = $entityManager->getRepository('Article')->findById(1);
$cats = $article->getCategories()->filter(function($cat) {
    return $cat->getName() === 'cat-01';
});

array_map() 与 PersistentCollection::map() 相同
或 current() 与 PersistentCollection::current()
等等等等等等。

现在...
问题是,有没有办法让我的非持久实体以与持久实体相同的方式工作?
或者有没有办法在持久和非持久实体上进行这项工作?

$cats = $article->getCategories()->filter(function($cat) {
    return $cat->getName() === 'cat-01';
});

【问题讨论】:

    标签: php doctrine-orm


    【解决方案1】:

    不要使用原生数组,而是尝试使用学说的ArrayCollection,这可能与您的持久化实体使用的类型相同:

    use Doctrine\Common\Collections\ArrayCollection;
    
    class Article
    {
        protected $id;
        protected $name;
        protected $categories;
    
        function __construct() {
           $this->categories = new ArrayCollection();
        }        
    }
    
    class Category
    {
        protected $id;
        protected $name;
        protected $articles;
    
        function __construct() {
           $this->articles = new ArrayCollection();
        }        
    }
    

    以下内容现在应该适用于非持久实体:

    // create some categories
    $cat1 = new Category();
    $cat1->setName('cat-01');
    
    $cat2 = new Category();
    $cat2->setName('cat-02');
    
    $cat3 = new Category();
    $cat3->setName('cat-03');
    
    // new Article
    $article = new Article();
    $article->setName('foo');
    $article->setCategories([$cat1, $cat2, $cat3]);
    
    $cats = $article->getCategories()->filter(function($cat) {
        return $cat->getName() === 'cat-01';
    });
    

    您没有显示代码,但我猜问题出在您的 Articles::setCategories 方法上。我怀疑你有

    class Articles {
      public function setCategories(array categories) {
        $this->categories = $categories;
    

    这会导致您的 ArrayCollection 被常规 php 数组覆盖。

    改为:

    class Articles {
      public function setCategories(array categories) {
        foreach($categories as $category) {
          $this->categories[] = $category;
    

    这将保留数组集合并允许过滤器功能对新实体以及检索到的实体起作用。

    【讨论】:

    • 我猜 Doctrine2 将能够处理 OneToMany、ManyToOne 或 ManyToMany 关联的 ArrayCollection?
    • 在构造函数中初始化 ArrayCollections 是个好习惯?
    • @dGo 是的,我通常在构造函数中初始化数组集合。您应该能够将其用于任何类型的关联
    • @FuzzyTree - 可能想用我的 setCategories 方法更新你的答案,然后我会删除我的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    • 2015-11-15
    相关资源
    最近更新 更多