2012-11-13 22 views
10

Tôi gặp sự cố khi cố gắng SỬ DỤNG QueryBuilder HOẶC DQL.Sử dụng JOIN trong Symfony2/Doctrine SQL

Tôi có mối quan hệ sau:

tài < -1: n> Hồ sơ < -n: m-> RouteGroup < -1: n> Route

Tôi muốn thực hiện một DQL liệt kê tất cả các tuyến đường mà một người dùng cụ thể có quyền truy cập. Tôi có thể nhận thông tin này bằng mã sau:

$usr = $this->container->get('security.context')->getToken()->getUser(); 
foreach ($usr->getProfiles() as $profile){ 
    foreach ($profile->getRoutegroups() as $routegroup){ 
     var_dump($routegroup->getRoutes()->toArray()); 
    } 
} 

Vì lý do rõ ràng tôi không thể sử dụng mã này, nếu không tôi sẽ quá tải máy chủ, LOL.

Tôi đã thử các phương pháp sau đây:

DQL:

$em->createQuery('SELECT p FROM CRMCoreBundle:User u 
        JOIN CRMCoreBundle:Profile p 
        JOIN CRMCoreBundle:RoleGroup rg 
        JOIN CRMCoreBundle:Role r 
        WHERE 
        u.id=:user') 
     ->setParameter('user', $user->getId()) 
     ->getResult(); 

QueryBuilder (tôi đã cố gắng sử dụng u.profiles - tên của mối quan hệ thay vì thực thể - nhưng điều này không làm việc cũng):

$em->createQueryBuilder() 
     ->select('r') 
     ->from('CRMCoreBundle:User', 'u') 
     ->innerJoin('u.profiles','p') 
     ->where('u.id = :user_id') 
     ->setParameter('user_id', $user->getId()) 
     ->getQuery() 
     ->getResult(); 

Ai đó có thể giúp vui lòng ???

UPDATE: Tôi cố gắng giải pháp Zeljko và làm kịch bản này:

return $this->getEntityManager() 
     ->createQueryBuilder() 
     ->select('u, r') 
     ->from('CRMCoreBundle:User', 'u') 
     ->innerJoin('u.profiles','p') 
     ->innerJoin('p.routegroups','rg') 
     ->innerJoin('rg.routes','r') 
     ->where('u.id = :user_id')->setParameter('user_id', $user->getId()) 
     ->getQuery() 
     ->getResult(); 

Nhưng tôi đã nhận lỗi này:

The parent object of entity result with alias 'r' was not found. The parent alias is 'rg'. 

Nếu tôi thay đổi "-> chọn ('u, r') "tới" -> chọn ('r') "tôi nhận được thông tin này:

[Semantical Error] line 0, col -1 near 'SELECT r FROM': Error: Cannot select entity through identification variables without choosing at least one root entity alias. 
+1

Để trả lời cập nhật, bạn không thể chỉ chọn u và r .. mọi thứ trên đường đi đến r cũng phải được chọn. vì vậy bạn cần chọn ('u, p, rg, r') – intrepion

Trả lời

20

Sau khi thử một số lựa chọn thay thế, tôi phát hiện ra rằng tôi có thể thực hiện tra cứu nghịch đảo, bắt đầu từ các tuyến đường đến người dùng. Giải pháp như sau:

return $this->getEntityManager() 
     ->createQueryBuilder() 
     ->select('r') 
     ->from('CRMCoreBundle:Route', 'r') 
     ->innerJoin('r.routegroup','rg') 
     ->innerJoin('rg.profiles','p') 
     ->innerJoin('p.users','u') 
     ->where('u.id = :user_id') 
     ->setParameter('user_id', $user->getId()) 
     ->getQuery() 
     ->getResult(); 
+2

Bây giờ bạn nên cố gắng tìm hiểu sự khác biệt giữa trái-tham gia và bên trong tham gia, họ rất khác nhau và bên trong có thể giúp bạn tiết kiệm tấn đau đầu. Cách đơn giản nhất; tạo Danh mục có nhiều mối quan hệ Sản phẩm. Khi tìm nạp danh mục, hãy thực hiện innerJoin của sản phẩm; bạn sẽ chỉ nhận được các danh mục thực sự có sản phẩm trong đó. Điều thực sự thú vị, đặc biệt khi bạn kết hợp nó với mệnh đề "WITH". – Zeljko

+0

Không sao cả. Tôi đã biết sự khác biệt giữa tham gia bên trong và bên trái. –

3

Trong DQL của bạn, bạn đang tìm nạp người dùng bu t bạn hỏi làm thế nào để lấy các tuyến đường. Những gì thực sự bạn cần?

Dù sao, trong RoutesRepository:

$this->createQueryBuilder("r") 
    ->innerJoin("r.Profiles", "p") 
    ->innerJoin("p.User", "u") 
    ->where("u=:user")->setParameter("user", $user) 

Tôi có thể không hiểu mối quan hệ nhưng tôi nghĩ bạn có thể thay đổi điều này để phản ánh mã của bạn. Bạn phải sử dụng innerJoin, không phải leftJoin.

+0

Xin chào, tôi đã thử giải pháp của bạn nhưng có một vấn đề khác. Tôi đã cập nhật câu hỏi ở trên. Bạn có thể xem thử không? Cảm ơn –

3

Tôi không phải là chuyên gia về Doctrine, nhưng vừa giải quyết được một vấn đề rất giống nhau. Tôi đã khắc phục sự cố của mình bằng cách bao gồm tất cả các thực thể mà bạn đang sử dụng trong các phép nối trong phần CHỌN của câu lệnh.

Tôi chưa thử nghiệm điều này, nhưng điều này sẽ hoạt động.

$em->createQuery('SELECT u, p, rg, r FROM CRMCoreBundle:User u 
       JOIN CRMCoreBundle:Profile p 
       JOIN CRMCoreBundle:RoleGroup rg 
       JOIN CRMCoreBundle:Role r 
       WHERE 
       u.id=:user') 
    ->setParameter('user', $user->getId()) 
    ->getResult(); 

Tôi không biết chính xác lý do tại sao, nhưng nếu bạn không bao gồm các thực thể thì trình quản lý không biết về bí danh mà bạn đang sử dụng cho các thực thể.

Tôi hy vọng điều này sẽ giúp ích.