【问题标题】:Doctrine2 ManyToMany bidirectionnal attribute populated by find method由 find 方法填充的多对多双向属性
【发布时间】:2018-05-24 02:49:21
【问题描述】:

我想从现有数据库中创建我的实体,它是一个 N - N 关系,它创建了 articleCategories 表。

我目前有 2 个实体,Article 和 Category,我想要一个多对多双向关系。

但是当我尝试使用 findByXXX 或 findOneByXXX 方法获取文章或类别时,我的 ManyToMany 属性为 NULL 或者我有 ORM 异常:Entity 'App\Models\Article' 有没有字段“类别”。因此,您不能在实体的存储库中调用“findByCategories”

数据库:

表格文章:idArticle, name, description, priceHT, size

表格类别:idCategory, name, percentTaxe

表格文章类别:idArticle、idCategory

实体:

类别

/**
* @Entity
* @Table(name="category")
*/
class Category
{
/**
 * @var integer
 *
 * @Id
 * @Column(name="idCategory", type="integer", nullable=false)
 * @GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 * @Column(name="name", type="string", length=45, nullable=false)
 */
private $name;


/**
 * @var string
 * @Column(name="percentTaxe",type="decimal", precision=10, scale=0, nullable=false)
 */
private $percentTaxe;

/*
 * Many categories have many articles
 * @ManyToMany(targetEntity="App\Models\Article", inversedBy="categories")
 * @JoinTable(name="articlesCategories",
 *  joinColumns={@JoinColumn(name="idCategory", referencedColumnName="idCategory")},
 *  inverseJoinColumns={@JoinColumn(name="idArticle", referencedColumnName="idArticle")}
 * )
*/
private $articles;


/*Constructor*/
public function __construct(){
    $toto = "toto";
    var_dump($toto);
    $this->articles = new ArrayCollection();
}

/***************************
    Getters / Setters
****************************/

public function getId(){
    return $this->id;
}
public function getName(){
    return $this->name;
}
public function getPercentTaxe(){
    return $this->percentTaxe;
}
public function getArticles(){
    return $this->articles;
}

/************************/

public function setId($id){
    $this->id = $id;
}
public function setName($name){

    $this->name = htmlspecialchars($name);  
}
public function setPercentTaxe($percentTaxe){
    $this->percentTaxe = htmlspecialchars($percentTaxe);    
}
public function setArticles(\Doctrine\Common\Collections\Collection $articles)
{
    $this->articles = $articles;
}

/***************************
    Getters / Setters
****************************/

public function addArticle(App\Models\Article $article)
{
    var_dump($article);
    $article->addCategory($this); // synchronously updating inverse side
    $this->articles[] = $article;
}

文章

/**
* @Entity
* @Table(name="article")
*/
class Article
{
/**
 * @var integer
 *
 * @Id
 * @Column(name="idArticle", type="integer", nullable=false)
 * @GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 * @Column(name="name", type="string", length=45, nullable=false)
 */
private $name;

/**
 * @var string
 * @Column(name="description",type="string", nullable=true)
 */
private $description;

/**
 * @var string
 * @Column(name="priceHT",type="decimal", precision=10, scale=3, nullable=false)
 */
private $priceHT;

/**
 * @var string
 * @Column(name="size", type="string", length=3, nullable=true)
 */
private $size;

/*
 * Many articles have many categories
 * @ManyToMany(targetEntity="App\Models\Category", inversedBy="articles")
 * @JoinTable(name="articlesCategories",
 *  joinColumns={@JoinColumn(name="idArticle", referencedColumnName="idArticle")},
 *  inverseJoinColumns={@JoinColumn(name="idCategory", referencedColumnName="idCategory")}
 * )
*/
private $categories;

/*Constructor*/
public function __construct(){
    echo"tata";
    $this->categories = new ArrayCollection();
    echo"tata";
}

/***************************
    Getters / Setters
****************************/

public function getId(){
    return $this->id;
}
public function getName(){
    return $this->name;
}
public function getDescription(){
    return $this->description;
}
public function getPriceHT(){
    return $this->priceHT;
}
public function getSize(){
    return $this->size;
}
public function getCategories(){
    return $this->categories;
}

/************************/

public function setId($id){
    $this->id = $id;
}
public function setName($name){

    $this->name = htmlspecialchars($name);  
}
public function setDescription($description){
    $this->description = htmlspecialchars($description);    
}
public function setPriceHT($priceHT){
    $this->priceHT = htmlspecialchars($priceHT);    
}
public function setSize($size){
    $this->size = htmlspecialchars($size);  
}
public function setCategories($categories){
    $this->categories = $categories;
}

/***************************
    Getters / Setters
****************************/

public function addCategory(App\Models\Category $category)
{
    $category->addArticle($this); // synchronously updating inverse side
    $this->categories[] = $category;
}

/************************/

public function hydrate($data)
{
    foreach($data as $key => $value)
    {
        // Get back the setter name wich correspond to the attribute 
        $method = 'set'.ucfirst($key);
        // if the good setter exist.
        if(methodexists($this, $method))
        {
            $this->$method($value);
        }
    }
}
}

经理

 /**
 * @param category : category of article we want
 * @return an array of Article object or null 
*/
public function getArticlesByCategory($categoryName)
{
    $articles = NULL;

    $repository = $this->getEntityManager()->getRepository("App\Models\Category");

    $category = $repository->findOneByName($categoryName);
    var_dump($category);

    if($category != NULL)
    {
        $articles = $category->getArticles();
    }
    return $articles;
}

当我 var_dump 我的 $category 时,我有:class App\Models\Category#122 (4) { private $id => int(2) private $name => string(7) "clothes"私人 $percentTaxe => string(2) "20" 私人 $articles => NULL }


由于Doctrine create instances of mapped entities without invoking constructor,我发现我的类别和文章为空而不是空数组,但我不明白为什么它没有填充它。

我只使用 Doctrine2,我不使用 symfony。

【问题讨论】:

    标签: php doctrine-orm orm


    【解决方案1】:

    首先,您对两个实体的 categoriesarticles 字段的注释都有错误。为了有效,它们应该以 /** 而不是 /*.Change 开头:

    /*
    * Many categories have many articles
    

    /**
    * Many categories have many articles
    

    文章实体的 $categories 字段也是如此。

    还将其中一个字段(文章或类别)更改为关系的反面,例如

    inversedBy="categories"
    

    到 mappedBy="类别"

    在您问题的另一部分,默认的 EntityRepository 查找方法(findBy,findOneBy)不支持按多对多关系过滤(至少目前还不支持)。您将不得不付出额外的努力并使用 createQueryBuilder,例如:

    $qb = $doctrine->getRepository(Article::class)->createQueryBuilder('a');
    
        $qb->select(
                'a',
                'cat'
            )
            ->innerJoin( 'a.categories', 'cat' )
            ->where('cat.id =1');
    

    更好地创建您自己的 ArticleRepository 和 CategoryRepository 并在那里定义您的查找方法。 7.8.8. Custom repositories

    【讨论】:

    • 这真的很狡猾,谢谢你准确指出如何解决我的问题。我将为高级查询创建一个构建器,但目前我可以在没有它的情况下完成我的工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多