Doctrine error - expected end of string, got "ORDER" - symfony

Using Symfony 4 / Doctrine, I got an error with this query :
$this->createQueryBuilder('s')
->update()
->set('s.dateCreate', ':date_new')
->setParameter('date_new', date('Y-m-d H:i:s'))
->where('s.site = :site')
->setParameter('site', $site)
->orderBy('s.dateCreate', 'DESC')
->setMaxResults(1)
->getQuery()
->execute();
I got this error :
[Syntax Error] line 0, col 81: Error: Expected end of string, got 'ORDER'
If I remove the orderBy, query works but I need to only update last entry. Can't see what is wrong here..

You are make an update statement, where inside it you can't add an order by function in this case.
If you want to order your result you need to make a select instead of an update into another query, you can do both, or you need to make a subselect to update only 1 result for example

Related

Comparing current date with stored dated on doctrine querybuilder

I need to make a query to get the row where the active field is true or the current date is between two stored dates Itring with
$qb->andWhere('p.active = true')')
->orWhere($qb->expr()->andX(
$qb->expr()->lt('p.activationDate', 'now()'),
$qb->expr()->eq('p.deactivationDate', 'now()')
))
->setMaxResults(1);
But I get :
[Syntax Error] line 0, col 145: Error: Expected known function, got 'now'
the were can be like this:
->andWhere("CURRENT_TIMESTAMP() BETWEEN p.activationDate and p.deactivationDate")
like this:
$repo = $this->em->getRepository(YourRepo::class);
$result = $repo->createQueryBuilder("p")
->andWhere("CURRENT_TIMESTAMP() BETWEEN p.activationDate and p.deactivationDate")
->getQuery()
->getResult();

Symfony3.4 / Doctrine : subquery in FROM Clause : Error: Class 'SELECT' is not defined

I'm working on a Symfony 3.4 project and I'm trying to translate an sql query to DQL query but I get an Issue.
Mysql Query:
select sum(montant_paye)
from
(select montant_paye
from vente
where client_id = 1
and montant_paye > 0
order by date ASC
limit 2)
as T;
DQL Query (Error):
return $this->getEntityManager()
->createQuery('
SELECT SUM(montantPaye) as Total
FROM
SELECT v.montantPaye
FROM AppBundle:Vente v
where v.montantPaye > 0
AND v.client = '.$clientId.'
ORDER BY v.date ASC
limit 2
')
->getResult();
Error :
[Semantical Error] line 0, col 71 near 'SELECT v.montantPaye
': Error: Class 'SELECT' is not defined.
Is any one have a solution for a correct DQL query ?
Quoting from Christophe stoef Coevoet (Symfony Core Developer):
DQL is about querying objects. Supporting subselects in the FROM clause means that the DQL parser is not able to build the result set mapping anymore (as the fields returned by the subquery may not match the object anymore).
This is why it cannot be supported (supporting it only for the case you run the query without the hydration is a no-go IMO as it would mean that the query parsing needs to be dependant of the execution mode).
In your case, the best solution is probably to run a SQL query instead
(as you are getting a scalar, you don't need the ORM hydration anyway)
Details here.
add this function to your VenteRepository:
public function sumMontantPaye($clientId)
{
return $this->createQueryBuilder("v")
->select("sum(v.montantPaye) as sum")
->where("v.client = :id")
->andWhere("v.montantPaye > 0")
->setParameter("id", $clientId)
->setMaxResults(2)
->getQuery()->getSingleResult();
}
you can access the sum using $result["sum"] assuming $result is the variable assigned to this function in the controller

Symfony and Doctrine: order by time difference

I am trying to build a query that retrieves all the most recent and upcoming activities from database.
The entity activity has a field named date of type DateTime. So in my repository I was thinking of building something like this:
$query = $repository
->createQueryBuilder('a');
$query->orderBy( 'DATEDIFF( a.date, NOW())' , 'ASC');
$query->setMaxResults( 6 );
return $query;
Unfortunately I get the following error:
[Syntax Error] line 0, col 59: Error: Expected end of string, got '('
The Dql that is generated by my query:
SELECT a FROM MyBundle\Entity\Activity a ORDER BY DATEDIFF( a.date, NOW()) ASC
I also tried installing beberlei/DoctrineExtensions, but either it is not working or I was unable to configure it correctly.
Anyone has any suggestion?
Thanks in advance
date_diff si already implemented as Doctrine DQL statement as described here
for use as ordering statement I suggest you to use the HIDDEN select keyword as explained in this article
So your DQL is like this:
SELECT
a,
DATE_DIFF( a.date, CURRENT_TIMESTAMP() ) AS HIDDEN score
FROM MyBundle:Entity a
ORDER BY score
And add the max result on the query. Let me know if you need help to adapt as query builder statement
Hope this help
Why don't you just use
$query = $repository
->createQueryBuilder('a');
$query->orderBy( 'DATEDIFF( a.date, CURRENT_TIMESTAMP())' , 'ASC');
$query->setMaxResults( 6 );
return $query;
?

Symfony createQueryBuilder with many to many

In my system candidate and profession has many to many relationship. I need to implement following query in symfony.
SELECT c. *
FROM candidate AS c
LEFT JOIN candidate_profession AS cp ON cp.candidate_id=c.id
WHERE cp.profession_id = 2
So i wrote following code.
$matched = $em->getRepository('AppBundle:Candidate')
->createQueryBuilder('c')
->where('c.professions = :profession')
->setParameter('profession', $job->getProfession())
->getQuery()
->getResult();
$job->getProfession() is return profession object. But it show following error.
[Semantical Error] line 0, col 51 near 'professions =': Error: Invalid PathExpression. StateFieldPathExpression or SingleValuedAssociationField expected.
How i implement that query?
I think your query should look like this:
$em->getRepository('AppBundle:Candidate')
->createQueryBuilder('c')
->leftJoin('c.professions', 'p')
->where('p.id = :profession')
->setParameter('profession', $job->getProfession())
->getQuery()
->getResult();
More about join clauses: http://doctrine-dbal.readthedocs.org/en/latest/reference/query-builder.html#join-clauses
First of all, I don't know where you have placed that snippet of code but I strongly advice you to migrate it into a Repository if you don't have already done (but looking at code I'm not sure you have)
Second, you need to pass an ID as ->getProfession() (as you already noticed) will return the whole object and you don't need it
So your query should be like this
$matched = $em->getRepository('AppBundle:Candidate')
->createQueryBuilder('c')
->where('c.professions = :profession')
->setParameter('profession', $job->getProfession()->getId())
->getQuery()
->getResult();
Please pay attention
You didn't specify the cardinality of relationship between job and profession: if is a something-to-Many you can't simply use ->getId() as returned object is an ArrayCollection, so, in that case, you need to do a loop to extract all id(s) and then use something like "IN" clause

Select objects with doctrine

I am looking at three different models/entities. One is called Model:Idea, one is called Model:IdeaDetail and the other is called Model:IdeaDetailValue.
IdeaDetail has a few different columns, including Idea (which is idea_id in the database, but $idea object in my model class) and IdeaDetailValue (idea_detail_value_id in the database, but $ideaDetailValue as an object in the model).
So basically, what I'm trying to do is select out a list of Idea objects by querying IdeaDetail.
$queryBuilder
->select('id.idea')
->from('Model:IdeaDetail', 'id')
->where('IDENTITY(id.ideaDetailValue) IN (:ideaDetailValueIds)')
->setParameter('ideaDetailValueIds', $ideaDetailValueIds)
->getQuery()
->getResult();
This fails though, with this error:
[Semantical Error] line 0, col 10 near 'task FROM Model:IdeaDetail': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
Does anyone know the correct way to do this query?
Thanks
It is wrong to select id.idea (according to the error, in fact, you probably select id.task), and also you cannot use IDENTITY() in this case.
You should join your tables to achieve the desired effect. Something like this should work:
$queryBuilder
->select('idea')
->from('Model:IdeaDetail', 'id')
->leftJoin('Model:IdeaDetailValue', 'idea')
->where('idea.id IN (:ideaDetailValueIds)')
->setParameter('ideaDetailValueIds', $ideaDetailValueIds)
->getQuery()
->getResult();

Resources