簡體   English   中英

Symfony Doctrine 查詢構建器查找具有多對一關系的實體

[英]Symfony Doctrine query builder find entity with many to one relation

我正在使用 Symfony 為一個項目構建一個網站,該網站的行為類似於“booking.com”網站,但要簡單得多,並且有一些變化。

數據庫字段上的一些錯誤,但對我的問題並不重要。

在此處輸入圖片說明

如您所見,這些表涉及兩個實體:公寓和訪問。 客戶可以要求參觀公寓。 這是多對一的關系。

我有一個搜索表格來搜索符合條件的公寓。 我只想顯示在用戶提供的到達和離開日期之間沒有任何訪問的公寓。 因此,我最終在 apartmentRepository 中創建了一個函數來管理該情況和其他情況。

問題是:我怎樣才能得到這些公寓?

這是這個功能的草稿,當然還沒有完成,也不完美(如果你有一些評論來改進它,那就太好了!)。

public function findByCustom($parameters): ?array
{
   $query =  $this->createQueryBuilder('a');

   foreach ($parameters as $key=> $parameter){
       if($key != 'keywords' and $key!= 'priceMin' & $key!='priceMax' and $key!="typeAp" and $key!="searchVisitDate") $query->orWhere('a.'.$key." = '".$parameter."'");

       if($key == "typeAp")
       {
           $typeApQuery = "";
           foreach ($parameters[$key] as $index => $type)
           {
               if($index !== count($parameters[$key])-1)
               {
                   $typeApQuery.=" a.typeAp = '".$type."' or";
               }
               else
               {
                   $typeApQuery.= " a.typeAp = '".$type."'";
               }
           }
           $query->andWhere($typeApQuery);
       }
   }

   $query->andWhere('a.rentPrice >='.$parameters['priceMin']." and a.rentPrice <= ".$parameters['priceMax']);
   $withoutInner = $query;
   $query
       ->join('App\Entity\Visit', 'v', Join::ON, 'a = v.apartment')
       ->where("v.date between '2020-03-15' and '2020-03-19'");
    $query->getQuery()->getResult();
    $sorted = $withoutInner->andWhere($this->createQueryBuilder('a')->expr()->notIn('a.id', $query));

   return array($sorted);

當然,公寓有一個訪問和訪問的集合,作為一個名為“公寓”的字段,與公寓對象相關。

我真的沒有找到合適的方法來做到這一點,我想避免使用 SQL,以提高我對 Doctrine 的理解。

感謝您的幫助,因為我現在被困住了:/

編輯 1:忘了提到我想要在規定的日期之間沒有訪問或根本沒有訪問的公寓

編輯 2:

public function findByCustom($parameters): ?array
{
   $query =  $this->createQueryBuilder('a');
    $withoutInner = $this->createQueryBuilder("a");

   foreach ($parameters as $key=> $parameter){
       if($key != 'keywords' and $key!= 'priceMin' & $key!='priceMax' and $key!="typeAp" and $key!="searchVisitDate")
       {
           $withoutInner->orWhere('a.'.$key." = '".$parameter."'");
           $query->orWhere('a.'.$key." = '".$parameter."'");
       }


       if($key == "typeAp")
       {
           $typeApQuery = "";
           foreach ($parameters[$key] as $index => $type)
           {
               if($index !== count($parameters[$key])-1)
               {
                   $typeApQuery.=" a.typeAp = '".$type."' or";
               }
               else
               {
                   $typeApQuery.= " a.typeAp = '".$type."'";
               }
           }
           $withoutInner->andWhere($typeApQuery);
           $query->andWhere($typeApQuery);
       }
   }

   $query->andWhere('a.rentPrice >='.$parameters['priceMin']." and a.rentPrice <= ".$parameters['priceMax']);
   $withoutInner->andWhere('a.rentPrice >='.$parameters['priceMin']." and a.rentPrice <= ".$parameters['priceMax']);
   $query
       ->join('App\Entity\Visit', 'v', Join::WITH, 'a.id = v.apartment')
       ->where("v.date between '2020-03-15' and '2020-03-19'");

    $query->getQuery()->getResult();
    $sorted = $withoutInner->andWhere($this->createQueryBuilder('a')->expr()->notIn('a.id', $query));

有了這個功能,我得到了學說錯誤:

Error: Method Doctrine\Common\Collections\ArrayCollection::__toString() must not throw an exception, caught ErrorException: Catchable Fatal Error: Object of class Doctrine\ORM\EntityManager could not be converted to string

我自己還沒有測試過,但是這樣的事情應該可行:

$query
    ->leftJoin('App\Entity\Visit', 'v', Join::WITH, 'a = v.apartment AND v.date between "2020-03-15" and "2020-03-19"')
    ->where('a.visits IS EMPTY');

這里的想法是使用leftJoin並僅選擇那些在visit表中沒有相應條目的結果。

我找到了一個解決方案來獲取所有沒有租金的公寓(連接為空)。 是的,我改變了租金的訪問,因為這是我的主要問題中的一個錯誤。

 $query->leftJoin('a.rents', 'r',Join::WITH,'a = r.apartment')
        ->where(
            $query->expr()->andX($query->expr()->isNull('r')))
        ->orWhere($query->expr()-> **);

我的公寓實體中有一個屬性,其中包含當前公寓的所有租金。 所以我用它來進行連接。 使用表達式 isNull 我讓它在沒有訪問的情況下為公寓工作。

** :我希望能夠獲得沒有用戶輸入所需到達日期不在 r.arrival 和 r.departure 之間的位置的公寓。 這將給我所有沒有租金的公寓和那些可以免費預訂的公寓。

我想過做另一個查詢並做一個 notIn 但我也不知道該怎么做。

謝謝你。

編輯和解決方案:

我自己發現了如何做到這一點。 這絕對不是最好的方法,也不是最好的解決方案,但我的項目沒時間了,所以我需要完成這項工作。

$rents = $this->getEntityManager()->createQueryBuilder()
        ->select("a.id")->from('App:Rent', 'r')
        ->andWhere('r.arrival between :arrival and :departure')
        ->leftJoin('r.apartment', 'a')
        ->setParameters(array("arrival"=>\DateTime::createFromFormat('Y-m-d', "2020-04-20")->setTime(00,00,00), "departure"=>\DateTime::createFromFormat('Y-m-d',"2020-04-31")->setTime(00,00,00)))
        ->getQuery()->getArrayResult();


    $rentsSorted = array();
    foreach ($rents as $rent)
    {
        if(!in_array( $rent['id'],$rentsSorted))
        {
            $rentsSorted[] = $rent['id'];
        }
    }
    if(count($rentsSorted)>0)
    {
        $withRentsNotBetweenDates->andWhere('a1.rentPrice >=' . $parameters['priceMin'] . " and a1.rentPrice <= " . $parameters['priceMax'])
            ->andWhere($withRentsNotBetweenDates->expr()->notIn('a1.id', $rentsSorted));
    }
    else
    {
        $withRentsNotBetweenDates->andWhere('a1.rentPrice >=' . $parameters['priceMin'] . " and a1.rentPrice <= " . $parameters['priceMax']);
    }

當然,我要將參數更改為我的表單給出的所需日期。

此代碼允許我獲得這些所需日期內存在的所有租金。 然后我將每個公寓 id 存儲在一個數組中,我將傳入 not in 以排除這些公寓,因為它們在此期間有租金。

如果您有任何改進或更好的方法來做到這一點,請不要害羞 xD。

祝你有美好的一天。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM