У меня есть сущность пользователя и сущность события. Пользователи могут уведомить о том, что хотят перейти на какие-то мероприятия. У этих пользователей также есть друзья, которые сами являются пользователями (ссылаясь на отношение многие ко многим).
Я хочу получить из своей базы данных друзей пользователя, которые удовлетворяют следующим условиям: они хотят пойти на то же мероприятие. они рядом друг с другом.
Хотя со вторым условием все в порядке, я пытаюсь создать наилучший запрос, чтобы убедиться, что первое условие соблюдается.
Вот что я сделал до сих пор:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select( 'USER', 'FRIENDS' ) // Selecting Me, the user who is asking to retrieve the users matched, and the friends who fill the criterias below
->from( 'Entity\User', 'USER' ) // we start with the user
->where( 'USER.id = :userId' ) // And I want the user the be me
->leftJoin('USER.friends', 'FRIENDS') // I'm going to take all of his friends
->innerJoin( 'FRIENDS.eventNotified', 'EVENT' ) //but ONLY the ones that have notified Events ( array collection ov EVENT entity )
->leftJoin( 'EVENT.categories', 'c' ) //take events category in order to avoid doing any request when getting the name of the category
->leftJoin( 'EVENT.place', 'p' ) // same with the place where the event occured
->andWhere(
$qb->expr()->andX(
$qb->expr()->between('FRIENDS.latitude', ':minLat', ':maxLat'), //in a defined area
$qb->expr()->between('FRIENDS.longitude', ':minLng', ':maxLng'),
$qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id') //I want to select ONLY the friends who have notified they want to go to the same events than me (I have notified the same events as well)
)
)
->add( 'orderBy', $qb->expr()->sum( 'FRIENDS.latitude - :lat', 'FRIENDS.longitude - :lng' ) );
К сожалению для меня, это не то, что я собираюсь делать. И мне интересно, почему. Поэтому, когда я выбираю ДРУЗЬЯ, я в основном хочу выбирать ТОЛЬКО друзей, которые уведомили, что они хотят пойти на те же мероприятия, что и те, о которых я уведомил.
Итак, я делаю innerJoin, чтобы проверить, уведомили ли друзья (они также являются пользователями), что они хотят перейти на мероприятия. И затем среди этих друзей я хочу выбрать ТОЛЬКО тех, кто собирается на те же мероприятия, что и мой $qb->expr()->eq('FRIENDS.eventNotified.id', 'USER.eventNotified.id')
.
Я думаю, что это моя проблема ... поскольку eventNotified - это коллекция сущности EVENT, из которой я хочу выбрать ТОЛЬКО события, о которых мы оба уведомили, могу я просто избавиться от .id
? Кроме того, у меня есть ощущение, что это выбирает все события, когда я просто хочу получить уведомления о событиях, которые мы имеем в сообществе. Так что я считаю, что мне следует где-нибудь здесь сделать innerJoin, но я могу найти правильный синтаксис.
Любой совет ?
Спасибо
Бонус: следует ли мне также указать, что я хочу получить «c» и «p» в операторе SELECT?
РЕДАКТИРОВАТЬ:
Я попробовал решение, приведенное ниже, но получаю непонятную ошибку. Как я могу получить полное сообщение об ошибке? (некоторые детали отсутствуют!)
Код, который я пробовал:
// Мы хотим вернуть только тех пользователей поблизости, которые доступны ИЛИ тех, кто $ qb = $ this-> getEntityManager () -> createQueryBuilder ();
$qb->select( 'USER', 'FRIENDS' ) // Selecting Me, the user who is asking to retrieve the users matched, and the friends who fill the criterias below
->from( 'Entity\User', 'USER' ) // we start with the user
->where( 'USER = :user' ) // And I want the user the be me
->leftJoin('USER.friends', 'FRIENDS', 'WITH', 'USER.eventNotified = FRIENDS.eventNotified');
$array = array(
'user' => $user
);
$qb->setParameters( $array );
$usersMatched = $qb->getQuery()->getResult();
ошибка:
Неустранимая ошибка: неперехваченное исключение 'Doctrine \ ORM \ Query \ QueryException' с сообщением 'SELECT USER, FRIENDS FROM Entity \ User USER LEFT JOIN USER.friends FRIENDS WITH USER.eventNotified = FRIENDS.eventNotified WHERE USER =: user' в / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Query / QueryException.php: 39 Трассировка стека: # 0 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Query / Parser. php (429): Doctrine \ ORM \ Query \ QueryException :: dqlError ('SELECT USER, FR ...') # 1 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Query / Parser .php (686): Doctrine \ ORM \ Query \ Parser-> semanticalError ('Invalid PathExp ...', Array) # 2 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Query /. Parser.php (240): Doctrine \ ORM \ Query \ Parser -> _ processDeferredPathExpressions (Object (Doctrine \ ORM \ Query \ AST \ SelectStatement)) # 3 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Запрос / Парс er.php (304): Doctrine \ ORM \ Query \ Parser-> getAST () # 4 / Пользователи в /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php on line 49
Кажется, Doctrine2 почему-то не любит 'WITH', 'USER.eventNotified = FRIENDS.eventNotified'
. Я действительно не понимаю почему. без этого фрагмента кода код работает нормально, но это условие действительно не выполняется.
Большое спасибо за вашу помощь
РЕДАКТИРОВАТЬ2:
Попробовав то, что было в третьем комментарии ответа ниже, я все еще получаю аналогичное сообщение об ошибке:
Неустранимая ошибка: неперехваченное исключение «Doctrine \ ORM \ Query \ QueryException» с сообщением «ВЫБОР ПОЛЬЗОВАТЕЛЯ, ДРУЗЬЯ, СОБЫТИЕ, c, p FROM Entity \ User ПОЛЬЗОВАТЕЛЬ ВЛЕВО ПРИСОЕДИНЯЙТЕСЬ к USER.friends FRIENDS WHERE USER =: user AND USER.eventNotified = FRIENDS. eventNotified 'в /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php:39 Трассировка стека: # 0 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Query / Parser.php (429): Doctrine \ ORM \ Query \ QueryException :: dqlError ('SELECT USER, FR ...') # 1 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine /ORM/Query/Parser.php(528): Doctrine \ ORM \ Query \ Parser-> semanticalError ('' СОБЫТИЕ 'не ...', массив) # 2 / Users / YohannM / Sites / meetmyfriends-back / application /libraries/Doctrine/ORM/Query/Parser.php(233): Doctrine \ ORM \ Query \ Parser -> _ processDeferredIdentificationVariables () # 3 / Users / YohannM / Sites / meetmyfriends-back / application / libraries / Doctrine / ORM / Query /Parser.php(304): Доктрина \ OR M \ Query \ Parser-> getAST () # 4 / Users / YohannM / Sites / meetmyfrien в /Users/YohannM/Sites/meetmyfriends-back/application/libraries/Doctrine/ORM/Query/QueryException.php в строке 49
Я считаю, что мы не можем выполнять динамические условия. Я не знаю, есть ли способ сделать это с помощью доктрины, иначе мне, вероятно, придется сделать это с помощью PHP, я думаю ...
Вот структура моего события и пользовательского объекта:
Пользователь:
class User {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false, unique=true)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="fb_id", type="bigint", nullable=false, unique=true)
*/
private $fb_id;
/**
* @var string
*
* @ORM\Column(name="firstname", type="string", length=100, nullable=false, unique=false)
*/
private $first_name;
/**
* @var string
*
* @ORM\Column(name="lastname", type="string", length=100, nullable=true, unique=false)
*/
private $last_name;
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=255, nullable=true, unique=true)
*/
private $email;
/**
* @var integer
*
* @ORM\Column(name="notation", type="integer", nullable=true, unique=true)
*/
private $notation;
/**
* Bidirectional - Many users have Many favorite comments (OWNING SIDE)
*
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Entity\Category", inversedBy="userInterests")
*/
private $interests;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Entity\User", cascade={"persist"})
* @ORM\JoinTable(name="friends",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="friend_user_id", referencedColumnName="id")}
* )
**/
private $friends;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Entity\Request", mappedBy="user", cascade={"remove"}, orphanRemoval=true)
* @ORM\JoinColumn(nullable=true)
*/
private $requests;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Entity\Request", mappedBy="friend", cascade={"remove"}, orphanRemoval=true)
* @ORM\JoinColumn(nullable=true)
*/
private $notifications;
/**
* Bidirectional - Many users have notified they want to go to different events (OWNING SIDE)
*
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Entity\Event", inversedBy="userNotified", cascade={"persist"})
*/
private $eventNotified;
/**
* @var integer
*
* @ORM\Column(name="age", type="integer", length=3, nullable=true, unique=false)
*/
private $age;
/**
* @var string
*
* @ORM\Column(name="description", type="text", nullable=true, unique=false)
*/
private $description;
/**
* @var string
*
* @ORM\Column(name="picture", type="string", length=300, nullable=true, unique=false)
*/
private $picture;
/**
* @var string
*
* @ORM\Column(name="genre", type="string", length=10, nullable=true, unique=false)
*/
private $genre;
/**
* @var boolean
*
* @ORM\Column(name="isregistered", type="boolean", length=1, nullable=false, unique=false)
*/
private $registered;
/**
* @var string
*
* @ORM\Column(name="latitude", type="decimal", length=64, precision=25, scale=20, nullable=true, unique=false)
*/
private $latitude;
/**
* @var string
*
* @ORM\Column(name="longitude", type="decimal", length=64, precision=25, scale=20, nullable=true, unique=false)
*/
private $longitude;
/**
* @var \Entity\Security_Key
*
* @ORM\OneToOne(targetEntity="Entity\Security_Key", cascade={"persist","remove"}, orphanRemoval=true)
* @ORM\JoinColumns({
* @ORM\JoinColumn(name="private_key_id", referencedColumnName="id", unique=true, onDelete="SET NULL")
* })
*/
private $private_key;
/**
* @var boolean
*
* @ORM\Column(name="isavailable", type="boolean", length=1, nullable=false, unique=false)
*/
private $available = 0;
Сущность события:
class Event
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=200, precision=0, scale=0, nullable=false, unique=false)
*/
private $name;
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Entity\Category", inversedBy="events")
* @ORM\JoinTable(name="categories_events")
*/
private $categories;
/**
* @var \Entity\User
*
* @ORM\ManyToOne(targetEntity="Entity\User", inversedBy="events")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
**/
private $user;
/**
* @var \Entity\Admin
*
* @ORM\ManyToOne(targetEntity="Entity\Admin", inversedBy="events")
* @ORM\JoinColumn(name="admin_id", referencedColumnName="id")
**/
private $admin;
/**
* @var \Entity\Place
*
* @ORM\ManyToOne(targetEntity="Entity\Place", inversedBy="events", cascade={"persist"})
* @ORM\JoinColumn(nullable=false)
*/
private $place;
/**
* @var string
*
* @ORM\Column(name="description", type="text", precision=0, scale=0, nullable=true, unique=false)
*/
private $description;
/**
* @var string
*
* @ORM\Column(name="link", type="string", length=200, nullable=true, unique=false)
*/
private $link;
/**
* @var string
*
* @ORM\Column(name="picture", type="string", length=100, precision=0, scale=0, nullable=true, unique=false)
*/
private $picture;
/**
* @var \DateTime
*
* @ORM\Column(name="date_created", type="datetime", precision=0, scale=0, nullable=false, unique=false)
*/
private $dateCreated;
/**
* @var \DateTime
*
* @ORM\Column(name="date_start", type="datetime", precision=0, scale=0, nullable=true, unique=false)
*/
private $dateStart;
/**
* @var \DateTime
*
* @ORM\Column(name="date_end", type="datetime", precision=0, scale=0, nullable=true, unique=false)
*/
private $dateEnd;
/**
* @var boolean
*
* @ORM\Column(name="confirmed", type="boolean", length=1, nullable=false, unique=false)
*/
private $confirmed;
/**
* Bidirectional - One-To-Many (INVERSE SIDE)
*
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\OneToMany(targetEntity="Entity\Request", mappedBy="event")
*/
private $invitations;
/**
* Bidirectional - Many users are intending many events (INVERSE SIDE)
*
* @ORM\ManyToMany(targetEntity="User", mappedBy="eventNotified", cascade={"persist"})
*/
private $userNotified;
->leftJoin('USER.friends', 'FRIENDS')
на->innerJoin('USER.friends', 'FRIENDS')
? - person Gohn67   schedule 11.02.2014