Я пытаюсь сделать запрос с подзапросом с Doctrine. Сейчас это дает мне ошибку. Моя функция в репозитории:
public function getRecentPlaylists($count = 3) { $q = $this->_em->createQuery(" SELECT p.id, p.featuredImage, p.title, p.slug, a.firstName, a.lastName, a.slug as authorSlug, (SELECT updated FROM \Entities\Articles ORDER BY updated DESC LIMIT 1) as updated FROM \Entities\Playlist p JOIN \Entities\Account a ON p.account_id = a.id ") ->setMaxResults($count); try{ return $q->getResult(); }catch(Exception $e){ echo $e->message(); } }
Это дает мне эту ошибку:
[Semantical Error] line 0, col 210 near 'LIMIT 1) as updated FROM': Error: Class 'LIMIT' is not defined.
Я почти отказываюсь от Doctrine, мне не удалось выяснить, как делать запросы с подзапросами или объединениями с подзапросами. Любая помощь с этой функцией? Благодаря!
Вам нужно вытащить внутренний запрос и сделать DQL отдельно для него, а затем использовать сгенерированный DQL внутри
$inner_q = $this->_em ->createQuery("SELECT AR.updated FROM \Entities\Articles AR ORDER BY AR.updated DESC") ->setMaxResults(1) ->getDQL(); $q = $this->_em->createQuery("SELECT p.id, p.featuredImage, p.title, p.slug, a.firstName, a.lastName, a.slug as authorSlug, (".$inner_q.") AS updated FROM \Entities\Playlist p JOIN \Entities\Account a ON p.account_id = a.id ") ->setMaxResults($count); try{ return $q->getResult(); } catch(Exception $e){ echo $e->message(); }
Вы можете легко добавить свой собственный синтаксис в Doctrine, например, добавить LIMIT 1
в подзапросы, как объяснил Колин О'Делл в своем блоге .
// AppBundle\DBAL\FirstFunction <?php use Doctrine\ORM\Query\AST\Functions\FunctionNode; use Doctrine\ORM\Query\AST\Subselect; use Doctrine\ORM\Query\Lexer; use Doctrine\ORM\Query\Parser; use Doctrine\ORM\Query\SqlWalker; /** * FirstFunction ::= * "FIRST" "(" Subselect ")" */ class FirstFunction extends FunctionNode { /** * @var Subselect */ private $subselect; /** * {@inheritdoc} */ public function parse(Parser $parser) { $parser->match(Lexer::T_IDENTIFIER); $parser->match(Lexer::T_OPEN_PARENTHESIS); $this->subselect = $parser->Subselect(); $parser->match(Lexer::T_CLOSE_PARENTHESIS); } /** * {@inheritdoc} */ public function getSql(SqlWalker $sqlWalker) { return '(' . $this->subselect->dispatch($sqlWalker) . ' LIMIT 1)'; } }
# app/config/config.yml doctrine: # ... orm: # ... dql: string_functions: FIRST: AppBundle\DBAL\FirstFunction
Используйте следующее:
$dqb->from('MyAppBundle:Foo', 'foo') ->leftJoin('foo.bar', 'bar', 'WITH', 'bar = FIRST(SELECT b FROM MyAppBundle:Bar b WHERE b.foo = foo AND b.published_date >= :now ORDER BY t.startDate)');
В этом случае вы можете использовать суммарное выражение MAX для Doctrine, чтобы получить самую последнюю дату:
SELECT MAX(a.updated) FROM AppBundle:Article a
Вам не нужно использовать LIMIT.