2015-10-26 4 views
1

Есть 2 таблицы: Провайдеры и Объявления. У Провайдера есть реклама.Получить все записи, если нет записей в связанной таблице с условием (Doctrine2, Symfony2)

Первая таблица "Поставщик":

  • ID
  • ...

Вторая таблица "Сейчас":

  • ID
  • Begin (DateTime)
  • End (DateTime)
  • ...

отношений:

/** 
* @ORM\OneToMany(targetEntity="Advert", mappedBy="provider", cascade={"persist"}) 
*/ 
private $adverts; 

Я хочу:

Все провайдеры, которые не имеют каких-либо объявления, которые в данный момент активны (= в настоящее время между «Begin «и« Конец ») И НЕ имеют рекламы, которая запланирована на будущее (=« Начать »и« Конец »в будущем).

Другими словами:

Я хочу, чтобы все провайдеры, которые не имеют каких-либо текущих или предстоящих рекламных объявлений.

Мой вопрос:

Я не знаю, и найти какую-либо информацию, как это сделать.


Я использую Doctrine2 с Symfony 2.8/3.0.

+0

Вы можете добавить как провайдер Относящиеся к Реклама? Какая сторона является собственником в вашем сопоставлении и т. Д. – stevenll

+0

Я добавил информацию об отношении. – JHGitty

ответ

0

Этот код работает отлично, но, возможно, он не полностью оптимизирована.

Предупреждение. Вам следует создать репозиторий для объекта-поставщика. Следующий код работает, если у вас есть $em как Doctrine EntityManager.

$qb = $em->createQueryBuilder(); 
    $qb = $qb->select('IDENTITY(advert.provider)') 
     ->from('AppBundle:Advert', 'advert') 
     ->where("advert.begin <= :now AND advert.end > :now") 
     ->andWhere('advert.active = true') 
     ->setParameter(':now', new \DateTime(), Type::DATETIME) 

    $nots = $qb->getQuery()->getArrayResult(); 

    $qb = $em->createQueryBuilder(); 
    $qb = $qb->select('p') 
     ->from('AppBundle:Provider', 'provider') 
     ->leftJoin('provider.adverts', 'advert'); 
    if (isset($nots[0])) { 
     $qb->where($qb->expr()->notIn('provider.id', $nots[0])); 
    } 

    $providers = $qb->getQuery()->getArrayResult(); 

Может быть «не существует» было бы лучше: NOT IN vs NOT EXISTS

1

Обратите внимание: некоторые функции MySQL не поддерживаются по умолчанию в Doctrine. Для этого вы можете установить расширение. Я собираюсь предложить способ без расширений. (Но вы должны отказаться для Bundle на свое собственное суждение)

В вашем Provider хранилища, вы можете сделать что-то вроде этого:

public function getProvidersWithoutAdverts() 
{ 
    $now = date("Y-m-d H:i:s"); 
    $qb = $this->createQueryBuilder('provider'); 

    $qb->leftJoin('provider.adverts', 'advert', Join::WITH) 
     ->where("advert.end < {$now}") //Advert has ended 
     ->andWhere("advert.begin < {$now}") //Advert is not scheduled 
     ; 

    return $qb->getQuery()->getResult(); 

} 
+0

В левом соединении возвращаются даже провайдеры, у которых нет рекламы вообще – stevenll

+0

Во-первых, вы в основном хотите всех Провайдеров, которые могут быть заинтересованы в объявлении. 'leftJoin' заверяет вас в том, что вы получили Провайдеров, у которых никогда не было рекламы.Кроме того, для того, чтобы объявление не было активным, это означает, что это конец в прошлом (он закончился) и для него не быть запланированным, его запуск не должен быть в будущем. Итак, у вас есть все провайдеры, у которых была история рекламы, но нет активных или запланированных. Это то, чего вы не хотели? – stevenll

+0

Я не хочу провайдера, если он в настоящее время рекламирует. Я не хочу, чтобы провайдер получал рекламу в будущем (запланированные рекламные объявления). Я ТОЛЬКО хочу, чтобы поставщики, у которых нет текущих или предстоящих рекламных объявлений. Я также хочу, чтобы у провайдера никогда не было рекламы. – JHGitty