What I actually need: returning records from the last month with QueryBuilder in Symfony2
OR in other words: converting following MySQL query to Doctrine QueryBuilder
created_at >= DATE_FORMAT(NOW(), '%Y-%m-%d') - INTERVAL 1 MONTH
What i did:
$clicks = $clickRepo->createQueryBuilder('c')
->select('c.product, c.createdAt, c.title')
->addSelect('COUNT(c.product)')
->where('c.type = :pro')
->setParameter('pro', 'product')
->andWhere('c.createdAt >= DATE_DIFF(CURRENT_DATE(), :end)')
->setParameter('end', new \DateTime('-30 days'), \Doctrine\DBAL\Types\Type::DATETIME)
->andWhere('c.shop != :null')
->setParameter('null', '0')
->andWhere('c.visible = :one')
->setParameter('one', '1')
->groupBy('c.product')
->setMaxResults(2)
->getQuery()->getResult();
Result:
array(1) {
[0]=>
array(4) {
["product"]=>
int(3)
["createdAt"]=>
object(DateTime)#3211 (3) {
["date"]=>
string(26) "2016-02-19 13:27:45.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
["title"]=>
string(23) "Title BlaBla"
["clicks"]=>
string(1) "2"
}
}
It returns but only records at the beginning of the table.
DATE_DIFF() returns the time between two dates. I think you have to use the DATE_SUB() function.
->andWhere('c.createdAt >= DATE_SUB(CURRENT_DATE(), :end)')
you can directly use mysql ' INTERVAL 1 MONTH' to get last one month data:
$clicks = $clickRepo->createQueryBuilder('c')
->select('c.product, c.createdAt, c.title')
->addSelect('COUNT(c.product)')
->where('c.type = :pro')
->setParameter('pro', 'product')
->andWhere('c.createdAt >= (NOW() - INTERVAL 1 MONTH)')
->andWhere('c.shop != :null')
->setParameter('null', '0')
->andWhere('c.visible = :one')
->setParameter('one', '1')
->groupBy('c.product')
->setMaxResults(2)
->getQuery()->getResult();
Hope it helps....
I just registered my own DQL function .
DateAddFunction.php
# Bundle/ProductBundle/myDQL/DateAddFunction.php
<?php
namespace Bundle\ProductBundle\myDQL;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
/**
* DateAddFunction ::=
* "DATE_ADD" "(" ArithmeticPrimary ", INTERVAL" ArithmeticPrimary Identifier ")"
*/
class DateAddFunction extends FunctionNode
{
public $firstDateExpression = null;
public $intervalExpression = null;
public $unit = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->firstDateExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$parser->match(Lexer::T_IDENTIFIER);
$this->intervalExpression = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_IDENTIFIER);
/* @var $lexer Lexer */
$lexer = $parser->getLexer();
$this->unit = $lexer->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'DATE_ADD(' .
$this->firstDateExpression->dispatch($sqlWalker) . ', INTERVAL ' .
$this->intervalExpression->dispatch($sqlWalker) . ' ' . $this->unit .
')';
}
}
config.yml
# app/config/config.yml
doctrine:
orm:
auto_generate_proxy_classes: "%kernel.debug%"
auto_mapping: true
dql:
string_functions:
DATEADD: \Bundle\ProductBundle\myDQL\DateAddFunction
Query
$clicks = $clickRepo->createQueryBuilder('c')
->select('c.product, c.createdAt, c.title')
->addSelect('COUNT(c.product)')
->where('c.type = :pro')
->setParameter('pro', 'product')
->andWhere('c.createdAt >= DATEADD(CURRENT_DATE(), INTERVAL :minusOne MONTH)')
->setParameter('minusOne', '-1')
->andWhere('c.shop != :null')
->setParameter('null', '0')
->andWhere('c.visible = :one')
->setParameter('one', '1')
->groupBy('c.product')
->setMaxResults(2)
->getQuery()->getResult();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.