2015-02-23 5 views
4

просто так у меня есть запись, уже принятая. У меня есть поле даты «создано», и теперь я хочу получить следующую и предыдущую запись по дате.doctrine - получить следующую и предыдущую запись

Понял работает по:

$qb = $this->createQueryBuilder('a'); 

    $next = $qb->expr()->gt('a.created', ':date'); 
    $prev = $qb->expr()->lt('a.created', ':date'); 

    $prev = $qb->select('partial a.{id,title,created}') 
     ->where($prev) 
     ->setParameter('date', $date) 
     ->orderBy('a.created', 'DESC') 
     ->setMaxResults(1) 
     ->getQuery() 
     ->getArrayResult(); 

    $next = $qb->select('partial a.{id,title,created}') 
     ->where($next) 
     ->setParameter('date', $date) 
     ->orderBy('a.created', 'DESC') 
     ->setMaxResults(1) 
     ->getQuery() 
     ->getArrayResult(); 

она работает очень хорошо. Но это 2 вопроса к базе данных. Мне это нужно. Я могу сделать это, просто присоединившись и т. Д., Но когда нет следующего или нет, я получил только пустой массив.

любая идея?

ответ

5

ответ Александровского близок , Когда вы запрашиваете id < 2 LIMIT 1, он вернет 1, но если вы запросите id < 5 LIMIT 1, это также вернет 1. Это потому, что он возвращает 1, 2, 3, 4 и принимает первый элемент, который равен 1, а не необходимый 4.

Просто добавьте ORDER BY id DESC, чтобы получить предыдущий элемент. Это вернет 4, 3, 2, 1, а LIMIT 1 вернет 4 или предыдущий элемент.

$query = $em->createNativeQuery('SELECT id FROM users WHERE 
     id = (SELECT id FROM users WHERE id > 2 LIMIT 1) 
     OR 
     id = (SELECT id FROM users WHERE id < 2 ORDER BY id DESC LIMIT 1)', $rsm); 
+0

Ааа .. да .. вы право :) Я забыл о заказе :) –

2

Вы можете сделать это с носителями запросов:

/** @var EntityManager $em */ 
$em = $this->getDoctrine()->getManager(); 
$rsm = new ResultSetMapping(); 
$rsm->addScalarResult('id', 'id'); 

$query = $em->createNativeQuery('SELECT id FROM users WHERE 
     id = (SELECT id FROM users WHERE id > 2 LIMIT 1) 
    OR 
     id = (SELECT id FROM users WHERE id < 2 LIMIT 1)', $rsm); 
$users = $query->execute(); 

в $ пользователей переменных вы будете иметь следующий массив:

[ 
    ['id' => 1] 
    ['id' => 3] 
] 

Подробнее здесь http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html

0

Альтернативный подход к родному SQL при использовании репозитория объектов ORM.

namespace EntityNamespace; 

use Doctrine\ORM\EntityRepository; 

class MyEntityRepository extends EntityRepository 
{ 

    /** 
    * @param int $id 
    * @return array|int[] 
    */ 
    public function filterNextPrevious($id) 
    { 
     $expr = $this->_em->getExpressionBuilder(); 
     $qbNext = $this->createQueryBuilder('a') 
      ->select(['MIN(a.id)']) 
      ->where($expr->gt('a.id', ':id')); 
     $qbPrevious = $this->createQueryBuilder('b') 
      ->select(['MAX(b.id)']) 
      ->where($expr->lt('b.id', ':id')); 
     $query = $this->createQueryBuilder('m') 
      ->select(['m.id']) 
      ->where($expr->orX(
       $expr->eq('m.id', '(' . $qbNext->getDQL() . ')'), 
       $expr->eq('m.id', '(' . $qbPrevious->getDQL() . ')') 
      )) 
      ->setParameter('id', $id) 
      ->addOrderBy('m.id', 'ASC') 
      ->getQuery(); 
     //optionally enable caching 
     //$query->useQueryCache(true)->useResultCache(true, 3600);  

     return $query->getScalarResult(); 
    } 
} 

Результирующая DQL:

SELECT m.id 
FROM EntityNamespace\Entity m 
WHERE m.id = (
    SELECT MIN(a.id) 
    FROM EntityNamespace\Entity a 
    WHERE a.id > :id 
) 
OR m.id = (
    SELECT MAX(b.id) 
    FROM EntityNamespace\Entity b 
    WHERE b.id < :id 
) 
ORDER BY m.id ASC 

(необязательно использовать вместо QueryBuilder через $this->_em->createQuery($DQL))

Результирующая Dataset:

array(2) { 
    [0]=> 
    array(1) { 
    ["id"]=> 
    string(4) "5869" 
    } 
    [1]=> 
    array(1) { 
    ["id"]=> 
    string(4) "5871" 
    } 
} 
Смежные вопросы