How to join multiple entities on a foreign ID in Symfony 4 using a query builder?

后端 未结 3 941
一整个雨季
一整个雨季 2021-01-21 09:07

I\'m trying to learn Symfony. Today I was following The associations tutorial. I decided to make a small application that a House, Kitchens, Bedrooms, and cabinets. I (tried to

相关标签:
3条回答
  • 2021-01-21 09:33

    In your debug bar in symfony you should probably be seeing some errors in doctrine. These won't show up in PHPStorm. You need to rename $kitchen and $bedroom to their plural forms $kitchens and $bedrooms (and change your getters/setters to match) since this is how you define things in the owning side of your doctrine relationships.

    A simpler approach than your repository method would be to do what you want in your controller to let doctrine do your heavy lifting:

    $cabinets = [];
    
    $house = $bedroom->getHouse();
    $kitchens = $house->getKitchens();
    foreach ($kitchens as $kitchen) {
        $kitchenCabinets = $kitchen->getCabinets();
        $cabinets = array_merge($cabinets, $kitchenCabinets);
    }
    
    0 讨论(0)
  • 2021-01-21 09:38

    There are several minor problems in your code, more on that later.

    Here is \App\Repository\CabinetRepository::findByBedroom:

        public function findByBedroom(Bedroom $bedroom) //use joins??
        {
            return $this->createQueryBuilder('cabinet')
                ->join('cabinet.kitchen', 'kitchen')
                ->join('kitchen.house', 'house')
                ->join('house.bedroom', 'bedroom')
                ->addSelect('cabinet')
                ->andWhere('bedroom = :bedroom')
                ->setParameter('bedroom', $bedroom)
                ->getQuery()
                ->getResult();
        }
    

    For bedroom entity with ID 815 the code above returns the following (formatted as symfony/var-dumper would do that):

    array:2 [▼
      0 => Cabinet {#387 ▼
        -id: 88
        -shopUrl: "co.m"
        -account_id: null
        -kitchen: Kitchen {#354 ▼
          +__isInitialized__: false
          -cabinet: null
          -house: null
          -id: 2
          -name: null
           …2
        }
      }
      1 => Cabinet {#364 ▼
        -id: 1
        -shopUrl: "ur.l "
        -account_id: null
        -kitchen: Kitchen {#370 ▼
          +__isInitialized__: false
          -cabinet: null
          -house: null
          -id: 55
          -name: null
           …2
        }
      }
    ]
    

    Note: house references are null because of lazy loading.

    So, small problems in your code:

    1. Your query in CabinerRepository was doing wrong joins. For correct joins see code above.

    2. That query referring to unknown field time. I have removed that reference.

    3. And also was using bedroom ID instead of bedroom entity.

    4. Your Kitchen.php is incomplete, it refers Collection and ArrayCollection classes, but there are no corresponding use directives. Just add this after namespace before class:

    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    

    Update: here is how to get repository reference:

    public function myControllerAction(/* other parameters */, CabinetRepository $cabRepo)
    {
        $cabinet = $cabRepo->find($id);
        // OR, if you don't want to add parameter for some reason:
        $cabRepo = $this->getDoctrine()->getRepository(Cabinet::class);
        $cabinet = $cabRepo->find($id);
    }
    
    0 讨论(0)
  • 2021-01-21 09:38

    First I think because you joining with both entities at the same time in this

    ...
                ->join('cabinet.bedroom', 'bedroom')
                ->join('cabinet.kitchen', 'kitchen')
    ...
    

    and because that will be with INNER JOIN, it will require that cabined is required both bedroom and kitchen cabinet.

    For that there is few solutions to work through:

    • Proper one would be redesign you entities. I think it might not be hard to use Doctrine inheritance
    • you might change joins to left, so relation is not mandatory (will work, but in general its not good solution because of wrong design)
    0 讨论(0)
提交回复
热议问题