2014-04-02 56 views
0

我有一個問題,我需要根據各種實體屬性過濾實體。其中一些屬性鏈接到ManyToOne或ManyToMany關係中的其他實體。我在Symfony2中工作,並得出結論,動態編寫單個DQL查詢以僅通過選定的屬性進行過濾對於我的經驗級別來說太複雜,所以我想要做的是爲每個過濾器屬性檢索結果集數組然後合併它們,但這樣只有BOTH數組A和數組B中存在的數組項會出現在我的結果數組中。我一直在努力尋找能輕易讓我做到這一點的東西,但我一直無法找到任何東西。PHP(Symfony2)數組:「INNER JOIN」

如果任何Symfony2開發人員看到這個線程,我意識到以上述方式做它並不理想,所以如果你能幫我創建一個可以做到這一點的DQL查詢,我將非常感激。下面是我需要過濾結果的實體。我需要過濾的屬性是「類別」,「作者」,「流派」和「語言」。假定我從REQUEST中提取了一個看起來類似於array('category' => 1, 'genre' => 6, 'author' => 8, 'language' => 2);的數組,但其中至少有一個數組必須存在,但並非所有數據都必須存在。

<?php 

namespace Pmb\LicensingBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Doctrine\Common\Collections\Criteria; 
use Doctrine\Common\Collections\ArrayCollection; 
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; 
use Symfony\Component\Validator\Constraints as Assert; 
use JMS\Serializer\Annotation as Ser; 
use Gedmo\Mapping\Annotation as Gedmo; 

/** 
* Ebook 
* 
* @ORM\Entity 
* @ORM\Table(name="ebooks") 
* @Ser\ExclusionPolicy("all") 
*/ 
class Ebook 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    * @Ser\Expose 
    */ 
    private $id; 

    /** 
    * @var Category[] 
     * 
     * @ORM\ManyToMany(targetEntity="Pmb\LicensingBundle\Entity\Category", inversedBy="ebooks", cascade={"remove"}) 
     * @ORM\OrderBy({"name" = "ASC"}) 
    **/ 
    private $categories; 

    /** 
    * @var Author[] 
     * 
     * @ORM\ManyToMany(targetEntity="Pmb\LicensingBundle\Entity\Author", inversedBy="ebooks", cascade={"remove"}) 
     * @ORM\OrderBy({"lastname" = "ASC", "firstnames" = "ASC"}) 
     * @Ser\Expose 
    **/ 
    private $authors; 

    /** 
    * @var Curriculum 
     * 
     * @ORM\ManyToOne(targetEntity="Pmb\LicensingBundle\Entity\Curriculum", inversedBy="ebooks", cascade={"remove"}) 
     * @ORM\OrderBy({"name" = "ASC"}) 
     * @Ser\Expose 
    **/ 
    private $curriculum; 

    /** 
    * @var Genre 
     * 
     * @ORM\ManyToOne(targetEntity="Pmb\LicensingBundle\Entity\Genre", inversedBy="ebooks", cascade={"remove"}) 
     * @ORM\OrderBy({"description" = "ASC"}) 
     * @Ser\Expose 
    **/ 
    private $genre; 

    /** 
    * @var Language 
     * 
     * @ORM\ManyToOne(targetEntity="Pmb\LicensingBundle\Entity\Language", inversedBy="ebooks", cascade={"remove"}) 
     * @Ser\Expose 
    **/ 
    private $language; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="isbn", type="string", length=16, unique=true) 
    * @Ser\Expose 
    * @Assert\Length(min=4, max=16) 
    */ 
    private $isbn; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="stock_code", type="string", length=16) 
    * @Ser\Expose 
    * @Assert\Length(min=4, max=16) 
    */ 
    private $stockCode; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="grade", type="integer", nullable=true) 
    * @Ser\Expose 
    * @Assert\Type({"int"}) 
    */ 
    private $grade; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="price", type="float") 
    * @Ser\Expose 
    * @Assert\Type({"float"}) 
    */ 
    private $price; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="name", type="string", length=128) 
    * @Ser\Expose 
    * @Assert\Length(min=3, max=128) 
    */ 
    private $name; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="description", type="string", length=255, nullable=true) 
    * @Ser\Expose 
    * @Assert\Length(max=255) 
    */ 
    private $description; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="year_of_pub", type="datetime", nullable=true) 
    * @Ser\Expose 
    * @Assert\DateTime 
    */ 
    private $yearOfPub; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="ebook_file", type="string", length=256, nullable=true) 
    * @Ser\Expose 
    */ 
    private $ebookFile; 

    /** 
    * @var string 
    * 
    * @ORM\Column(name="thumbnail", type="string", length=256, nullable=true) 
    * @Ser\Expose 
    */ 
    private $thumbnail; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="date_created", type="datetime") 
    * @Ser\Expose 
    * @Assert\DateTime 
    */ 
    private $dateCreated; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="active", type="boolean") 
    * @Ser\Expose 
    */ 
    private $active; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="allow_trial", type="boolean") 
    * @Ser\Expose 
    */ 
    private $allowTrial; 

    /** 
    * @var boolean 
    * 
    * @ORM\Column(name="featured", type="boolean") 
    * @Ser\Expose 
    */ 
    private $featured; 

    ////////////////////////////////////////////////////////////////////////////////////// 
    // METHODS 
    ////////////////////////////////////////////////////////////////////////////////////// 

    ////////////////////////////////////////////////////////////////////////////////////// 
    // GETTERS AND SETTERS 
    ////////////////////////////////////////////////////////////////////////////////////// 

    /** 
    * Constructor 
    */ 
    public function __construct() 
    { 
     $this->categories = new \Doctrine\Common\Collections\ArrayCollection(); 
     $this->authors = new \Doctrine\Common\Collections\ArrayCollection(); 
     $this->curriculums = new \Doctrine\Common\Collections\ArrayCollection(); 
     $this->genres = new \Doctrine\Common\Collections\ArrayCollection(); 
     $this->active = true; 
    } 

    /** 
    * Get id 
    * 
    * @return integer 
    */ 
    public function getId() 
    { 
     return $this->id; 
    } 

    /** 
    * Set isbn 
    * 
    * @param string $isbn 
    * @return Ebook 
    */ 
    public function setIsbn($isbn) 
    { 
     $this->isbn = $isbn; 

     return $this; 
    } 

    /** 
    * Get isbn 
    * 
    * @return string 
    */ 
    public function getIsbn() 
    { 
     return $this->isbn; 
    } 

    /** 
    * Set stockCode 
    * 
    * @param string $stockCode 
    * @return Ebook 
    */ 
    public function setStockCode($stockCode) 
    { 
     $this->stockCode = $stockCode; 

     return $this; 
    } 

    /** 
    * Get stockCode 
    * 
    * @return string 
    */ 
    public function getStockCode() 
    { 
     return $this->stockCode; 
    } 

    /** 
    * Set grade 
    * 
    * @param integer $grade 
    * @return Ebook 
    */ 
    public function setGrade($grade) 
    { 
     $this->grade = $grade; 

     return $this; 
    } 

    /** 
    * Get grade 
    * 
    * @return integer 
    */ 
    public function getGrade() 
    { 
     return $this->grade; 
    } 

    /** 
    * Set price 
    * 
    * @param float $price 
    * @return Ebook 
    */ 
    public function setPrice($price) 
    { 
     $this->price = $price; 

     return $this; 
    } 

    /** 
    * Get price 
    * 
    * @return float 
    */ 
    public function getPrice() 
    { 
     return $this->price; 
    } 

    /** 
    * Set name 
    * 
    * @param string $name 
    * @return Ebook 
    */ 
    public function setName($name) 
    { 
     $this->name = $name; 

     return $this; 
    } 

    /** 
    * Get name 
    * 
    * @return string 
    */ 
    public function getName() 
    { 
     return $this->name; 
    } 

    /** 
    * Set description 
    * 
    * @param string $description 
    * @return Ebook 
    */ 
    public function setDescription($description) 
    { 
     $this->description = $description; 

     return $this; 
    } 

    /** 
    * Get description 
    * 
    * @return string 
    */ 
    public function getDescription() 
    { 
     return $this->description; 
    } 

    /** 
    * Set yearOfPub 
    * 
    * @param \DateTime $yearOfPub 
    * @return Ebook 
    */ 
    public function setYearOfPub($yearOfPub) 
    { 
     $this->yearOfPub = $yearOfPub; 

     return $this; 
    } 

    /** 
    * Get yearOfPub 
    * 
    * @return \DateTime 
    */ 
    public function getYearOfPub() 
    { 
     return $this->yearOfPub; 
    } 

    /** 
    * Set active 
    * 
    * @param boolean $active 
    * @return Ebook 
    */ 
    public function setActive($active) 
    { 
     $this->active = $active; 

     return $this; 
    } 

    /** 
    * Get active 
    * 
    * @return boolean 
    */ 
    public function getActive() 
    { 
     return $this->active; 
    } 

    /** 
    * Add categories 
    * 
    * @param \Pmb\LicensingBundle\Entity\Category $categories 
    * @return Ebook 
    */ 
    public function addCategory(\Pmb\LicensingBundle\Entity\Category $categories) 
    { 
     $this->categories[] = $categories; 

     return $this; 
    } 

    /** 
    * Remove categories 
    * 
    * @param \Pmb\LicensingBundle\Entity\Category $categories 
    */ 
    public function removeCategory(\Pmb\LicensingBundle\Entity\Category $categories) 
    { 
     $this->categories->removeElement($categories); 
    } 

    /** 
    * Get categories 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getCategories() 
    { 
     return $this->categories; 
    } 

    /** 
    * Add authors 
    * 
    * @param \Pmb\LicensingBundle\Entity\Author $authors 
    * @return Ebook 
    */ 
    public function addAuthor(\Pmb\LicensingBundle\Entity\Author $authors) 
    { 
     $this->authors[] = $authors; 

     return $this; 
    } 

    /** 
    * Remove authors 
    * 
    * @param \Pmb\LicensingBundle\Entity\Author $authors 
    */ 
    public function removeAuthor(\Pmb\LicensingBundle\Entity\Author $authors) 
    { 
     $this->authors->removeElement($authors); 
    } 

    /** 
    * Get authors 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getAuthors() 
    { 
     return $this->authors; 
    } 

    /** 
    * Set language 
    * 
    * @param \Pmb\LicensingBundle\Entity\Language $language 
    * @return Ebook 
    */ 
    public function setLanguage(\Pmb\LicensingBundle\Entity\Language $language = null) 
    { 
     $this->language = $language; 

     return $this; 
    } 

    /** 
    * Get language 
    * 
    * @return \Pmb\LicensingBundle\Entity\Language 
    */ 
    public function getLanguage() 
    { 
     return $this->language; 
    } 

    /** 
    * Set allowTrial 
    * 
    * @param boolean $allowTrial 
    * @return Ebook 
    */ 
    public function setAllowTrial($allowTrial) 
    { 
     $this->allowTrial = $allowTrial; 

     return $this; 
    } 

    /** 
    * Get allowTrial 
    * 
    * @return boolean 
    */ 
    public function getAllowTrial() 
    { 
     return $this->allowTrial; 
    } 

    /** 
    * Set dateCreated 
    * 
    * @param \DateTime $dateCreated 
    * @return Ebook 
    */ 
    public function setDateCreated($dateCreated) 
    { 
     $this->dateCreated = $dateCreated; 

     return $this; 
    } 

    /** 
    * Get dateCreated 
    * 
    * @return \DateTime 
    */ 
    public function getDateCreated() 
    { 
     return $this->dateCreated; 
    } 

    /** 
    * Set featured 
    * 
    * @param boolean $featured 
    * @return Ebook 
    */ 
    public function setFeatured($featured) 
    { 
     $this->featured = $featured; 

     return $this; 
    } 

    /** 
    * Get featured 
    * 
    * @return boolean 
    */ 
    public function getFeatured() 
    { 
     return $this->featured; 
    } 

    /** 
    * Add categories 
    * 
    * @param \Pmb\LicensingBundle\Entity\Category $categories 
    * @return Ebook 
    */ 
    public function addCategorie(\Pmb\LicensingBundle\Entity\Category $categories) 
    { 
     $this->categories[] = $categories; 

     return $this; 
    } 

    /** 
    * Remove categories 
    * 
    * @param \Pmb\LicensingBundle\Entity\Category $categories 
    */ 
    public function removeCategorie(\Pmb\LicensingBundle\Entity\Category $categories) 
    { 
     $this->categories->removeElement($categories); 
    } 

    /** 
    * Set curriculum 
    * 
    * @param \Pmb\LicensingBundle\Entity\Curriculum $curriculum 
    * @return Ebook 
    */ 
    public function setCurriculum(\Pmb\LicensingBundle\Entity\Curriculum $curriculum = null) 
    { 
     $this->curriculum = $curriculum; 

     return $this; 
    } 

    /** 
    * Get curriculum 
    * 
    * @return \Pmb\LicensingBundle\Entity\Curriculum 
    */ 
    public function getCurriculum() 
    { 
     return $this->curriculum; 
    } 

    /** 
    * Set genre 
    * 
    * @param \Pmb\LicensingBundle\Entity\Genre $genre 
    * @return Ebook 
    */ 
    public function setGenre(\Pmb\LicensingBundle\Entity\Genre $genre = null) 
    { 
     $this->genre = $genre; 

     return $this; 
    } 

    /** 
    * Get genre 
    * 
    * @return \Pmb\LicensingBundle\Entity\Genre 
    */ 
    public function getGenre() 
    { 
     return $this->genre; 
    } 

    /** 
    * Set ebookFile 
    * 
    * @param string $ebookFile 
    * @return Ebook 
    */ 
    public function setEbookFile($ebookFile) 
    { 
     $this->ebookFile = $ebookFile; 

     return $this; 
    } 

    /** 
    * Get ebookFile 
    * 
    * @return string 
    */ 
    public function getEbookFile() 
    { 
     return $this->ebookFile; 
    } 

    /** 
    * Set thumbnail 
    * 
    * @param string $thumbnail 
    * @return Ebook 
    */ 
    public function setThumbnail($thumbnail) 
    { 
     $this->thumbnail = $thumbnail; 

     return $this; 
    } 

    /** 
    * Get thumbnail 
    * 
    * @return string 
    */ 
    public function getThumbnail() 
    { 
     return $this->thumbnail; 
    } 
} 
+0

看看:http://es1.php.net/array_intersect。另外,我試圖用你的規範編寫DQL查詢,但我不太明白。你能否發表更詳細的信息? –

+0

嗨阿爾貝託,前提是用戶在列出所有電子書的網站上。現在,他可以按照類別,流派,語言和作者(每個電子書鏈接的實體)來過濾電子書。電子書可以有多個類別和作者,但用戶只能選擇一個。他可以爲所有這些選擇其中一種,或者他只能選擇其中的一種(例如流派),然後「張貼」他的過濾請求。我的控制器功能必須過濾電子書並根據他的過濾請求返回結果。 – Magnanimity

+0

因此,如果只選擇了「GENRE A」,那麼如果選擇了「GENRE A」和「AUTHOR C」和「LANGUAGE ENGLISH」,則該功能必須返回鏈接到「GENRE A」的所有電子書,必須返回鏈接到「GENRE A」和「AUTHOR C」的所有英文電子書。 – Magnanimity

回答

1

下面是一個簡單的例子,說明如何實現這一點。假設你有一個BookRepository,也是一個BookFilterType定義什麼樣的過濾器,用戶可以使用:

class BookRepository extends EntityRepository 
{ 
    protected $queryBuilder; 

    public function filterByGenre($genre) 
    { 
     return $this->getQueryBuilder() 
      ->andWhere("b.genre = :genre") 
      ->setParameter('genre', $genre); 
    } 

    public function filterByWhatever($whatever) 
    { 
     return $this->getQueryBuilder() 
      ->andWhere("b.whatever = :whatever") 
      ->setParameter('whatever', $whatever); 
    } 

    public function getFilterResult() 
    { 
     $result = $this->getQueryBuilder() 
      ->getQuery->getResult(); 

     $this->queryBuilder = null; 

     return $result; 
    } 


    public function getQueryBuilder() 
    { 
     if(!$this->queryBuilder) 
      $this->queryBuilder = $this->createQueryBuilder("b"); 

     return $this->queryBuilder; 
    } 
} 

在你的控制器:

public function indexAction(Request $request) 
{ 
    $form = $this->createForm(new BookFilterType()); 

    if($request->isMethod("POST")) 
    { 
     $form->submit($request); 

     if($form->isValid()) 
     { 
      $filters = $form->getData(); 

      // pass filters to the repository 
      $books = $bookRepository 
       ->filterByGenre($filters['genre']) 
       ->filterByWhatever($filters['whatever']) 
       ->getFilterResult(); 

      return ['books' => $books]; // render filtered books in template 
     } 
    } 
} 

您也可以使用GET形式(超過通濾波器URL);這並不重要,因爲它是由bind方法在引擎蓋下處理的。

+0

非常感謝,這裏只有一個問題,這主要是我卡住的地方。類別,例如是一個ManyToOne關係(所以一個電子書可以有很多類別),所以如果我寫' - >和Where(b.category =:category)'我會得到一個錯誤,'category'不存在(因爲它被定義爲類別)和' - >和其中(b.categories =:category)'也不起作用。 – Magnanimity

+0

在這種關係中(還有'ManyToMany'),您需要首先加入關係,然後查詢:'join('b.categories','cat') - > andWhere('cat IN )')'。當您需要屬於*多個*類別的書籍時,請注意'IN'上的用法,而不僅僅是一種。您可能還想查看其他字段。 –