Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [inny][Silex][Doctrine][DQL] Podzapytania w WHERE
sebul
post 21.11.2017, 18:05:24
Post #1





Grupa: Zarejestrowani
Postów: 3
Pomógł: 0
Dołączył: 20.10.2014

Ostrzeżenie: (0%)
-----


Witam, próbuję rozwiązać problem podzapytania w where w doctrine i zaciąłem się na takiej sytuacji. Mam 3 pliki
1.
  1. <?php
  2.  
  3. namespace App\Entity;
  4.  
  5. use Doctrine\Common\Collections\ArrayCollection;
  6. use Doctrine\ORM\Mapping as ORM;
  7.  
  8. /**
  9.  *
  10.  * @ORM\Entity(repositoryClass="App\Entity\NotificationRepository")
  11.  * @ORM\Table(name="notifications")
  12.  */
  13. class Notification
  14. {
  15. /**
  16.   * @var int
  17.   *
  18.   * @ORM\Id
  19.   * @ORM\Column(name="id", type="integer")
  20.   * @ORM\GeneratedValue(strategy="AUTO")
  21.   */
  22. private $id;
  23.  
  24. /**
  25.   * @var ArrayCollection
  26.   *
  27.   * @ORM\ManyToMany(targetEntity="App\Entity\Service")
  28.   * @ORM\JoinTable(name="notification_services",
  29.   * joinColumns={@ORM\JoinColumn(name="notification_id", referencedColumnName="id")},
  30.   * inverseJoinColumns={@ORM\JoinColumn(name="service_id", referencedColumnName="id")}
  31.   * )
  32.   */
  33. private $services;
  34.  
  35. }

2.
  1. <?php
  2.  
  3. namespace App\Entity;
  4.  
  5. use Doctrine\ORM\Mapping as ORM;
  6.  
  7. /**
  8.  *
  9.  * @ORM\Table(name="services")
  10.  */
  11. class Service
  12. {
  13. /**
  14.   * @var int
  15.   *
  16.   * @ORM\Id
  17.   * @ORM\GeneratedValue
  18.   * @ORM\Column(type="integer")
  19.   */
  20. private $id;
  21.  
  22. /**
  23.   * @var bool
  24.   *
  25.   * @ORM\Column(type="boolean")
  26.   */
  27. private $failure;
  28.  
  29. }

3.
  1. <?php
  2.  
  3. namespace App\Entity;
  4.  
  5. use Doctrine\ORM\QueryBuilder;
  6.  
  7. class NotificationRepository
  8. {
  9.  
  10. /**
  11.   * @param null|bool $failure
  12.   * @return QueryBuilder
  13.   */
  14. public function getList(bool $failure = null): QueryBuilder
  15. {
  16. $subRepo = $this->getEntityManager()->getRepository(Service::class);
  17. $query = $this->createQueryBuilder('n');
  18. $subService = $subRepo->createQueryBuilder('ns');
  19.  
  20. return $query;
  21. }
  22.  
  23. }

i chciałbym pobrać wpisy z Notification, które nie mają serwisów failure na true, czyli w mysql było by mniej więcej coś takiego
  1. SELECT
  2. n.*
  3. FROM
  4. `notifications` n
  5. WHERE
  6. (SELECT
  7. s.id
  8. FROM
  9. `notification_services` ns
  10. INNER JOIN
  11. `services` s ON ns.service_id = s.id
  12. WHERE
  13. ns.notification_id = n.id
  14. AND s.failure = 1
  15. LIMIT 1) IS NULL;

lub też odpowiednio na odwrót - wpisy z Notification, które mają serwisy z failure na false. Jak to zrobić za pomocą query buildera, ewentualnie bezpośrednio w DQL?

Ten post edytował sebul 21.11.2017, 19:35:47
Go to the top of the page
+Quote Post
Pyton_000
post 21.11.2017, 20:53:57
Post #2





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


To napisz to RawSQL, nie nic złego w tym podejściu.
Go to the top of the page
+Quote Post
markuz
post 21.11.2017, 21:16:49
Post #3





Grupa: Zarejestrowani
Postów: 1 240
Pomógł: 278
Dołączył: 11.03.2008

Ostrzeżenie: (0%)
-----


Ciekawostka odnośnie Silex: https://leftontheweb.com/blog/2017/11/17/Si...ong-live-mylex/


--------------------
Go to the top of the page
+Quote Post
Pyton_000
post 22.11.2017, 08:44:29
Post #4





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

Ostrzeżenie: (0%)
-----


Nie ma jeszcze oficialnego potrierdzenia tego faktu ale raczej tak, z wejściem SF4 nie ma sensu rozwijane Silex
Go to the top of the page
+Quote Post
Pilsener
post 22.11.2017, 11:22:43
Post #5





Grupa: Zarejestrowani
Postów: 1 590
Pomógł: 185
Dołączył: 19.04.2006
Skąd: Gdańsk

Ostrzeżenie: (0%)
-----


  1. $qb = $this->createQueryBuilder('a');
  2. $qb2 = $this->createQueryBuilder('aa');
  3. $qb->orWhere($qb->expr()->in('a.id', $qb2->getDQL()));


Zapytanie wygląda mniej więcej:
  1. WHERE c0_.id IN (SELECT c4_.id FROM competition c4_)


Najpierw musisz mieć dwa dobre query buildery, jeden do głównej tabeli a drugi do filtrowania, potem już nie powinno sprawić żadnego problemu połączenie tego.
Go to the top of the page
+Quote Post
sebul
post 22.11.2017, 20:06:12
Post #6





Grupa: Zarejestrowani
Postów: 3
Pomógł: 0
Dołączył: 20.10.2014

Ostrzeżenie: (0%)
-----


Trochę dziwne podejście jak dla mnie z tym sprawdzaniem id notification, no ale działa i chyba tak zostawię.


@Edit
A jednak jeszcze inaczej to zrobiłem
  1. /**
  2.   * @param null|bool $failure
  3.   * @return QueryBuilder
  4.   */
  5. public function getList(bool $failure = null): QueryBuilder
  6. {
  7. $subRepo = $this->getEntityManager()->getRepository(Service::class);
  8. $query = $this->createQueryBuilder('n');
  9. $subService = $subRepo->createQueryBuilder('ns')
  10. ->where('ns.failure=:failure')
  11. ->andWhere($query->expr()->isMemberOf('ns','n.services'));
  12.  
  13. $query->where($query->expr()->exists($subQuery->getDQL()))
  14. ->setParameter('failure', $failure);
  15.  
  16. return $query;
  17. }

nie wiem czy bardziej optymalnie, bo w mysql wygląda to tak, że są dwa "exists", a tym wcześniejszym sposobem są dwa joiny.

Ten post edytował sebul 22.11.2017, 20:34:20
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 24.04.2024 - 20:06