Order By with DAY(), MONTH() is not working in doctrine2 - symfony

I am trying to order results of my query by day and month, here is my code
public function getUserBirthday($idList)
{
$queryBuilder = $this->_em->createQueryBuilder();
$queryBuilder->select('fb')
->from('Wishwish\ApplicationBundle\Entity\FbUser', 'fb')
->where(' Week(fb.birthday)<= Week(:now)+2')
->andWhere('Week(fb.birthday)> Week(:now)')
->andWhere('fb.id IN (:idList)')
->orderBy('DAY(fb.birthday)')
->addOrderBy('MONTH(fb.birthday)');
$queryBuilder->setParameter('now', new \DateTime());
$queryBuilder->setParameter('idList',$idList);
return $queryBuilder->getQuery()->getResult();
}
this id the error displayed :
[Syntax Error] line 0, col 170: Error: Expected end of string, got '('
500 Internal Server Error - QueryException
1 linked Exception: QueryException »
update =>solution :
the trick was to use createNativeQuery
public function getUserBirthday($idList)
{
$rsm = new ResultSetMapping();
$rsm->addEntityResult('Wishwish\ApplicationBundle\Entity\FbUser', 'fb');
$rsm->addFieldResult('fb', 'birthday', 'birthday');
$rsm->addFieldResult('fb', 'picture', 'picture');
$rsm->addFieldResult('fb', 'name', 'name');
$rsm->addFieldResult('fb', 'id', 'id');
$sql ='select * from fb_user
where (Week(birthday)<= Week(:now)+2) and (Week(birthday)> Week(:now))
and (id IN (:idList)) ORDER By DAY (birthday),MONTH (birthday)';
$query = $this->_em->createNativeQuery($sql, $rsm);
$query->setParameter('now', new \DateTime());
$query->setParameter('idList',$idList);
return $query->getResult();
}

Try to use createNativeQuery() method for more complex query:
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping();
$query = $this->_em->createNativeQuery('
SELECT fb
FROM WishwishApplicationBundle:FbUser fb
WHERE Week(fb.birthday) <= Week(:now)+2
AND Week(fb.birthday) > Week(:now)
AND fb.id IN (:idList)
ORDER BY DAY(fb.birthday) ASC, MONTH(fb.birthday) ASC
', $rsm)
->setParameter('now', new \DateTime())
->setParameter('idList',$idList);
$result = $query->getResult();

Related

how to make a dql request with table database are not an entity

I would like to understand why my DQL request doesn't work. I've to entity : books(ouvrages) and authors(auteurs), there is many to many relation, so in my database a join table is create books_authors (ouvrages_auteurs) with reference "id" of each other. I would like to use this join table for have all informations of my two entity books and authors.
I've make many request in my BooksRepository but it's doesn't work :
public function getOuvrageTradeByAuteur(array $autor){
$query = $this->getEntityManager()->createQuery("SELECT o,a FROM SBMainBundle:Ouvrages o JOIN ouvrages_auteurs oa JOIN SBMainBundle:Auteurs a WHERE o.is_trade = true AND o.id = oa.ouvrages_id AND oa.auteurs_id = a.id AND a.nom_auteur = :autor")
->setParameter('autor',$autor);
return $query->getResult();
}
public function getBooksTradeByAutor(array $autor){
//requete DQL pour un many to many
$query = $this->createQueryBuilder('o');
$query->join('o.auteur','auteurs')
->where($query->expr()->in('auteurs.nomAuteur',$autor))
->andWhere('o.isTrade = true')
->orderBy('o.id','desc')
->addSelect('o,auteurs');
return $query->getQuery()->getResult();
}
public function getBooksSellByAutor(array $autor){
//requete DQL pour un many to many
$query = $this->createQueryBuilder('o');
$query->join('o.auteur','auteurs')
->where($query->expr()->in('auteurs.nomAuteur',$autor))
->andWhere('o.isSell = true')
->orderBy('o.id','desc')
->addSelect('o,auteurs');
return $query->getQuery()->getResult();
}
public function getOuvragesEchangesByAutor($auteurs){
//requete en DQL 2eme partie
$query = $this->createQueryBuilder('o')->where('o.auteur = :autor')
->andWhere('o.isTrade = true')
->join('o.auteur','a')
->setParameter('autor',$auteurs)
->orderBy('o.id','desc')
->addSelect('a');
return $query->getQuery()->getResult();
}
public function getOuvragesVentesByAutor($auteurs){
//requete en DQL 2eme partie
$query = $this->createQueryBuilder('o')->where('o.auteur = :autor')
->andWhere('o.isSell = true')
->join('o.auteur','a')
->setParameter('autor',$auteurs)
->orderBy('o.id','desc')
->addSelect('a');
return $query->getQuery()->getResult();
}
Edit for error message :
[Semantical Error] line 0, col 45 near 'ouvrages_auteurs': Error: Class 'ouvrages_auteurs' is not defined.
500 Internal Server Error - QueryException
1 linked Exception:
QueryException »
[2/2] QueryException: [Semantical Error] line 0, col 45 near 'ouvrages_auteurs': Error: Class 'ouvrages_auteurs' is not defined.
[1/2] QueryException: SELECT o,a FROM SBMainBundle:Ouvrages o JOIN ouvrages_auteurs oa JOIN SBMainBundle:Auteurs a WHERE o.is_trade = true AND o.id = oa.ouvrages_id AND oa.auteurs_id = a.id AND a.nom_auteur = :autor
Edit for the Nnew issue :
[Semantical Error] line 0, col 79 near 'auteur = :autor': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.
500 Internal Server Error - QueryException
1 linked Exception:
QueryException »
[2/2] QueryException: [Semantical Error] line 0, col 79 near 'auteur = :autor': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.
[1/2] QueryException: SELECT o, a FROM SB\MainBundle\Entity\Ouvrages o INNER JOIN o.auteur a WHERE o.auteur = :autor AND o.isSell = true ORDER BY o.id desc
I've use this request :
public function getOuvragesEchangesByAutor($auteurs){
//requete en DQL 2eme partie
$query = $this->createQueryBuilder('o')->where('o.auteur = :autor')
->andWhere('o.isTrade = true')
->join('o.auteur','a')
->setParameter('autor',$auteurs)
->orderBy('o.id','desc')
->addSelect('a');
return $query->getQuery()->getResult();
}
Thanks for your help ! :D
That error informs that the problem probably is in your entity definition. ouvrages_auteurs must exist like an association property in your Ouvrages entity, but it is more simple call it as auteurs like this:
// Ouvrage Entity definitions...
/**
* #ORM\ManyToMany(targetEntity="Auteurs", inversedBy="ouvrages")
* #ORM\JoinTable(name="ouvrages_auteurs",
* joinColumns={#ORM\JoinColumn(name="ouvrage_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="auteur_id", referencedColumnName="id")}
* )
*/
private $auteurs;
/*
* Constructor
*/
public function __construct()
{
$this->auteurs = new \Doctrine\Common\Collections\ArrayCollection();
}
Later in your query you should create dql JOIN clauses like this type:
SELECT o, a
FROM SBMainBundle:Ouvrages o
JOIN o.auteurs a
WHERE o.is_trade = true
all related auteurs with selected ouvrages will be returned in result, clause: o.id = oa.ouvrages_id is not necessary.
More info about Doctrine mapping here: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#many-to-many-unidirectional
EDIT for new issue:
I think problem is that if autors info are in auteurs then:
$query = $this->createQueryBuilder('o')->where('a.id = :autor')
->andWhere('o.isTrade = true')
->join('o.auteur','a')
->setParameter('autor',$auteurs)
->orderBy('o.id','desc')
->addSelect('a');

How to make a Doctrine subquery?

I have two mysql tables and corresponding entities:
Question
--------
id
text
level
Asked
--------
* #ORM\ManyToOne(targetEntity="QuestionEntity")
* #ORM\JoinColumn(name="question", referencedColumnName="id")
question
user
I want to query for all questions that has a specific level and the question haven't been asked from a given user. How can I do this with an entity manager query builder?
With MySQL syntax the query would be:
SELECT
*
FROM
Question
WHERE
Question.level = 1
AND Question.id NOT IN( SELECT Asked.question FROM Asked WHERE Asked.user = 23)
I tried multiple things like Tomasz Madeyski commented, but I still got 500 Internal Server Error. This is my code: (I tested the subquery and it was fine when it is stand alone)
$em = $this->getDoctrine()->getManager();
$fbUser = $em->getRepository(FbUserEntity::class)->findOneBy(['fbId' => $session->get('fb_user_id')]);
$qb = $em->createQueryBuilder();
$qb2 = $qb;
$questions = $qb->select('q')
->from('MyBundle:QuestionEntity', 'q')
->where('q.level = :level')
->setParameter('level', $level)
->andWhere($qb->expr()->notIn(
'q.id',
$qb2->select('a.question')
->from('LMyBundle:AskedEntity', 'a')
->where('a.user = :userid')
->setParameter('userid', $fbUser->getId())
->getDQL()
))
->getQuery()
->getResult();
Try something like this:
$qb = $em->createQueryBuilder();
$subQuery = $qb->select('a.question')
->from('YourBundle:Asked', 'a')
->andWhere('a.user = 23')
$query = $qb->select('q')
->from('YourBundle:Question', 'q')
->andWhere('q.level = 1')
->andWhere($qb->expr()->notIn('q.id', $subQuery->getDQL())
->getQuery()
->getResult()
The key here is $qb->expr()->notIn() part
Investigating the logs I figured out that instead of
$qb = $em->createQueryBuilder();
$qb2 = $qb;
I should create a new queryBuilder for qb2:
$qb = $em->createQueryBuilder();
$qb2 = $em->createQueryBuilder();
But this still gives me an error. After some experimentingI figured out that if the subquery is executed, it gives something like this format:
array (size=2)
0 =>
array (size=1)
'question' => int 1
1 =>
array (size=1)
'question' => int 2
So I run through the subquery result like this:
$alreadyAsked = [];
foreach($asked as $q){
$alreadyAsked[] = $q['question'];
}
And pass the $alreadyAsked array to the main query like this, then it works:
->andWhere($qb->expr()->notIn('q.id', $alreadyAsked))

Symfony2 Error: Object of class Doctrine\ORM\EntityManager could not be converted to string

I have 2 non related entities: External and Internal. I need to union select all results from entities. I am using ResultSetMapping and Native SQL to do this:
$em = $this->getDoctrine()
->getManager()->getConnection();
$rsm = new \Doctrine\ORM\Query\ResultSetMapping();
$rsm->addEntityResult('ExternalBundle:External', 'e');
$rsm->addFieldResult('e', 'id', 'id');
$rsm->addFieldResult('e', 'status', 'status');
$rsm->addFieldResult('e', 'name', 'name');
$rsm->addEntityResult('InternalBundle:Internal', 'i');
$rsm->addFieldResult('i', 'id', 'id');
$rsm->addFieldResult('i', 'status', 'status');
$rsm->addFieldResult('i', 'name', 'name');
$sql = "SELECT e.*
FROM external_print e
UNION
SELECT i.*
FROM internal_print i";
$objects = $this->$em->createNativeQuery($sql, $rsm)->getResult();
I keep getting this error: Catchable Fatal Error: Object of class Doctrine\ORM\EntityManager could not be converted to string.
What needs to be fixed?
You have a code error instead of
$objects = $this->$em->createNativeQuery($sql, $rsm)->getResult();
use just
$objects = $em->createNativeQuery($sql, $rsm)->getResult();

QueryBuilder on a non object

I want create a multilingual web site, and for that I use Symfony with the PrezentBundle and A2lixBundle. I would get the list of my data by locale with entity repo.
I have this error :
FatalErrorException: Error: __clone method called on non-object in /project/vendor/doctrine/orm/lib/Doctrine/ORM/QueryBuilder.php line 238
Here is my repo :
$qb = $this->createQueryBuilder('c')
->leftJoin('c.criteres', 'crit')
->leftjoin('c.translations', 'ct', 'WITH', 'ct.locale = :locale')
->setParameters('locale', 'fr');
var_dump($qb->getDql() );
return $qb->getQuery()
->getResult();
The var_dump give me that :
SELECT c FROM NS\MyBundle\Entity\CritereCateg c LEFT JOIN c.criteres crit LEFT JOIN c.translations ct WITH ct.locale = :locale
Your issue is probably because of misuse of the setParameters() mehtod. There is two simmilar methods for the doctrine query builder:
1) setParameter() which sets only one parameter per method usage. The syntax is:
// for numeric parameters
$qb->leftjoin('c.translations', 'ct', 'WITH', 'ct.locale = ?1')
->setParameter(1, 'fr');
// for string parameters
$qb->leftjoin('c.translations', 'ct', 'WITH', 'ct.locale = :locale')
->setParameter('locale', 'fr');
2) setParameters() which sets multiple parameters:
// String params
$qb->where('u.id = :uid')
->leftjoin('c.translations', 'ct', 'WITH', 'ct.locale = :locale')
->setParameters(array('locale' => 'fr', 'uid' => $userId));
// Numeric parameters are also available here
$qb->where('u.id = ?1')
->leftjoin('c.translations', 'ct', 'WITH', 'ct.locale = ?2')
->setParameters(array(2 => 'fr', 1 => $userId));
So you probably wanted to use setParameter() instead of setParameters() in your query builder.

query with dateformat in where clause in symfony2

when I run a query with date in where clause, following error is showed...
[Syntax Error] line 0, col 129: Error: Expected known function, got 'DATE_FORMAT'
the query is given below
$query = $this->getEntityManager()->createQuery(
"SELECT a.id, a.amont, a.paymentDescrip, a.paymentType, a.paymentDate
FROM RegalSmsBundle:DailyTransaction a
WHERE DATE_FORMAT(a.paymentDate,'%Y-%m-%d') = :paymentDate
and a.students = :studentId"
)->setParameter('studentId', $studentId)
->setParameter('paymentDate','2013-03-11');
return $query->getResult();
Doctrine doesn't have DATE_FORMAT function defined by default. It's possible to Register Custom DQL Function.
But you can compare date easily (assuming a.paymentDate is of type date):
$query = $this->getEntityManager()->createQuery("
SELECT a.id, a.amont, a.paymentDescrip, a.paymentType, a.paymentDate
FROM RegalSmsBundle:DailyTransaction a
WHERE a.paymentDate = :paymentDate AND a.students = :studentId
")
->setParameter('studentId', $studentId)
->setParameter('paymentDate', new \DateTime('2013-03-11'))
;
return $query->getResult();
Edit: I prefer using querybuider to writing DQL. It would look like this:
$qb = $this->getEntityManager()->getRepository('RegalSmsBundle:DailyTransaction')->createQueryBuilder('a');
$qb
->select('a') // select whole entity
->where($qb->expr()->andX(
$qb->expr()->eq('a.paymentDate', ':paymentDate')
$qb->expr()->eq('a.students', ':studentId')
))
->setParameter('studentId', $studentId)
->setParameter('paymentDate', new \DateTime('2013-03-11'))
;
return $qb->getQuery()->getResult();

Resources