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

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

报告相同问题?

悬赏问题

  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历