dongxiee0744 2017-12-10 11:31
浏览 40
已采纳

由find方法填充的Doctrine2 ManyToMany bidirectionnal属性

I want to create my entities from an existing database, it's an N - N relation which create articlesCategories table.

I currently have 2 entities, Article and Category, and I want to have a ManyToMany bidirectionnal relationship.

But when I try to get article or category with a findByXXX or findOneByXXX method, my ManyToMany attribute is NULL or I have an ORM Exception : Entity 'App\Models\Article' has no field 'categories'. You can therefore not call 'findByCategories' on the entities' repository

Database :

Table article : idArticle, name, description, priceHT, size

Table category : idCategory, name, percentTaxe

Table articlesCategories : idArticle, idCategory

Entities :

Category

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

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

Manager

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

And when I var_dump my $category, I have : class App\Models\Category#122 (4) { private $id => int(2) private $name => string(7) "clothes" private $percentTaxe => string(2) "20" private $articles => NULL }


I found my categories and articles are null instead of to be an empty array because of Doctrine create instances of mapped entities without invoking constructor but I don't understand why It doesn't populate it.

I just use Doctrine2, I don't use symfony.

  • 写回答

1条回答 默认 最新

  • dorv56831 2017-12-14 22:57
    关注

    First, you have an error at your annotations on categories and articles fields of both entities. To be valid they should start with /** not /*.Change:

    /*
    * Many categories have many articles
    

    to

    /**
    * Many categories have many articles
    

    Same for $categories field of Article Entity.

    Also change one of the fields(articles or categories) to be the inverse side of the relation, e.g.

    inversedBy="categories"
    

    to mappedBy="categories"

    On the other part of your question, default EntityRepository find methods(findBy, findOneBy) of the does not support filter by many to many relation(at least not yet). You will have to do the extra effort and use createQueryBuilder, e.g.:

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

    And better create your own ArticleRepository and CategoryRepository and define your find methods there. 7.8.8. Custom repositories

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)
  • ¥15 keil里为什么main.c定义的函数在it.c调用不了
  • ¥50 切换TabTip键盘的输入法
  • ¥15 可否在不同线程中调用封装数据库操作的类
  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思