Create a select distinct request with symfony 5 - symfony

In symfony 5, with doctrine I want to create a request to select distinct type.
So, I have made the following code:
/**
* #Route("/hometest", name="hometest")
*/
public function index2()
{
$lesservices = $this->getDoctrine()->getRepository(Services::class)->findAll();
$em = $this->getdoctrine()->getManager();
$query = $em->createQuery('SELECT distinct serv.souscategorie FROM App\Entity\Services serv');
$services = $query->getResult();
return $this->render('home/indextest.html.twig', array ('servicesliste' => $lesservices, 'distinctscat' => $query));
}
But, I am getting this error :
[Semantical Error] line 0, col 21 near 'souscategorie': Error: Invalid PathExpression. Must be a StateFieldPathExpression.
In fact, souscategorie is a relation field and if I put a string field at his place everything goes right.
Do I have to make a join request to have my souscategorie results ?
Thanks for your answers.

You are selecting a relation field, this might be your problem.
By searching your error i found out this answer which could help you solve your query without having to join:
SELECT DISTINCT IDENTITY(serv.souscategorie) ...

Related

How to build this query on Symfony with QueryBuilder?

Please I am a beginner on symfony and I have 2 entities: category and professionnal with ORM many to many. And 'City' is an entity with ORM oneToMany with 'professionnal'.
In professionnel I have a property city. I want to show professionnal grouped by categories who have a special cityId putted on parameter in the url.
I put this query on sql
(for example city_id= 10873)
, it gives me the results.
SELECT * FROM sub_category AS a LEFT JOIN professionnel ON professionnel.city_id = 10873
but I don't know how to write with querybuilder.
I put this solution but I have errors:
$city = $paramFetcher->get('city');
$queryBuilder = $em->getRepository(SubCategory::class)
->createQueryBuilder('a')
->leftJoin('App\Entity\Professionnel','p')
->where('p.city = :city')
->setParameter('city', $city);
return $queryBuilder->getQuery()->getResult();
in log:
request.CRITICAL: Uncaught PHP Exception Doctrine\DBAL\Exception\SyntaxErrorException: "An exception occurred while executing 'SELECT c0_.id AS id_0, c0_.name AS name_1 FROM category c0_ LEFT JOIN professionnel p1_ WHERE p1_.city_id = ?' with params ["10873"]: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE p1_.city_id = '10873'' at line 1"
I search on forums too and I found that I can replaced the 'ON' of leftJoin as following, but shows me all professionnals:
$city = $paramFetcher->get('city');
$queryBuilder = $em->getRepository(SubCategory::class)
->createQueryBuilder('a')
->leftJoin('App\Entity\Professionnel','p','WITH','p.city = :city')
->setParameter('city', $city);
return $queryBuilder->getQuery()->getResult();
For the mapping, I put it like this:
class Category
{
/**
* Many professionnels have Many categories.
* #ORM\ManyToMany(targetEntity="App\Entity\Professionnel", mappedBy="Categories")
* #ORM\JoinTable(name="professionnel_category")
*/
private $professionnels;
}
class Professionnel extends User
{
/**
* Many professionel have Many categories.
* #ORM\ManyToMany(targetEntity="App\Entity\Category", inversedBy="professionnels")
* #Groups({"Default", "professionnel", "user"})
*/
private $categories;
}
Thank you so much for your help.
So, assuming that you have your entity relation set up correctly (please update your question with those), I see one mistake above.
If you look at the official Doctrine Query Builder documentation, the leftJoin method's third argument is either WITH or ON constant and not join predicate. That one comes as a 4th argument. But, even then, that join predicate is only used is a very specific use-case, where you want to further define your join relation. By looking at your example, I doubt that is your case.
With that being said, I think your code should look like this:
$city = $paramFetcher->get('city');
$queryBuilder = $em->getRepository(Category::class)
->createQueryBuilder('a');
->leftJoin('App\Entity\Professionnel','p')
->where('p.city_id = :city')
->setParameter('city', $city);
return $queryBuilder->getQuery()->getResult();
Now the question: is that really just a city_id (plain integer) or is that relation to some entity named City?
Please update your question with those details and I will update the answer, if necessary...
Hope this helps...
Firstly, you need describe relations in entities. Read more about this here
Secondary, you must call in join field (read as property), not a Entity.
inside CategoryRepository:
/** #return ArrayCollection|Category[] */
public function getByCityId(int $cityId): ArrayCollection
{
$qb = $this->createQueryBuilder('category');
$qb->leftJoin('category.professional', 'professional')
->leftJoin('category.city', 'city')
->where($qb->expr()->eq('city.id', $cityId));
return $qb->getQuery()->getResult();
}
Inside SomeController:someAction()
$cityId = $paramFetcher->get('city');
$categoriesList = $this->get('doctrine.orm.entity_manager')
->getRepository(Category::class)
->getByCityId($cityId);
As result you'll be have list of category, with joined professional and city.
I suggest to read this article on symfony docs

How to set parameters in nested query in DQL

Hi,
I'd like to get number of created articles by a user, the query used to work until I added some parameters filtering the query by "fromDate" and "toDate" dates, here's my query :
// query String
$dql = 'SELECT u.idUser,
u.lastName,
u.email,
u.mobile,
(SELECT AVG(n.note)
FROM MyBundle:Note n
WHERE n.noteFor = u.idUser) AS note,
(SELECT COUNT(a)
FROM MyBundle:Article a
WHERE (a.createdBy = u.idUser) AND (a.createdAt BETWEEN :fromDate AND :toDate)) AS articles
FROM MyBundle:User u';
// create the actual query
$users= $em->createQuery($dql);
// set filter date parameter
$users->setParameter('fromDate', $fromDate.'00:00:00');
$users->setParameter('toDate', $toDate.'23:59:59');
I keep getting this error : Invalid parameter number: number of bound variables does not match number of tokens.
I tried searching in the doctrine documentation for how to set parameters in nested queries without finding anything. first I need to know if it's possible to do that then find where the error come from, Please Help !
Use setParameters() instead of setParameter()
$users->setParameters(array('fromDate'=> $fromDate.'00:00:00','toDate'=> $toDate.'23:59:59'))
So after performing some tests, I found out that the query worked well the way it was and the problem wasn't there.
I'm using KnpPaginatorBundle to paginate my queries, it seems that the problem was that it couldn't paginate complex queries like passing multiple parameters in the nested query. so I found a solution. So this is the old code :
// Pagination
$paginator = $this->get('knp_paginator');
$users = $paginator->paginate($users, 1, 10);
And this is the new code :
// Pagination
$paginator = $this->get('knp_paginator');
$users = $paginator->paginate($users, 1, 10, array('wrap-queries' => true) );
Thanks to Nisam and Matteo for their time, hope this helps someone

Query Builder or Closure or DQL, which is the right one for get ride of this complex SQL query with ManyToMany relationship?

So I've this two entities:
class TipoRegistro
{
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\TipoTramite", inversedBy="tipoRegistros", cascade={"persist"})
* #ORM\JoinTable(name="nomencladores.tipo_registro_tipo_tramite", schema="nomencladores",
* joinColumns={#ORM\JoinColumn(name="tipo_registro_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="tipo_tramite_id", referencedColumnName="id")}
* )
*/
protected $tipoTramites;
}
class TipoTramite
{
/**
* #ORM\ManyToMany(targetEntity="AppBundle\Entity\TipoRegistro", mappedBy="tipoTramites", cascade={"persist"})
*/
protected $tipoRegistros;
}
I need to get all the TipoRegistro associated to TipoTramite trhough ManyToMany relationship as show before as the SQL below shows:
SELECT tr.*
FROM
nomencladores.tipo_registro tr
LEFT JOIN
nomencladores.tipo_registro_tipo_tramite AS trtt
ON (trtt.tipo_registro_id = tr."id")
WHERE
tr.activo = true
AND
trtt.tipo_tramite_id = 1;
I don't know if I can use a custom repository here so my only solution is to use query_builder parameter at form level and this is what I'm doing:
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('tr')
->where('tr.activo = :activo')
->leftJoin('tr.tipoTramites', 'ttr')
->andWhere("ttr.tipo_tramite_id = :tramite")
->setParameter("tramite", 1)
->setParameter('activo', true);
}
But that solution cause this error:
[Semantical Error] line 0, col 121 near 'tipo_tramite_id': Error:
Class AppBundle\Entity\TipoTramite has no field or
association named tipo_tramite_id
I tried this one also (as suggested per user here):
->andWhere("ttr.tipoTramites = :tramite")
But the errors turns into this one:
[Semantical Error] line 0, col 120 near 'tipoTramites': Error: Invalid
PathExpression. StateFieldPathExpression or
SingleValuedAssociationField expected
Also I've tried this other solution:
->andWhere("tr.id = :tramite")
But this one doesn't return the right values. I read something about Closures on the entity field type but has no idea in how to implement on this scenario. The other idea comes to me is use a DQL and a preparement statement but I thin this can't be used at form level, so I'm out of ideas, then how I can get those values? How I should establish the relation between this ManyToMany entities?
When you create a ManyToMany relationship in your entity, Doctrine will generate the third table as mediator between those two entities (named in #ORM\JoinTable) with two fields (defined in joinColumns). You do not have direct access to the fields or columns in the third table but they all will be handled by Doctrine in your DQL.
This means in your DQL you need to just set the joint table id in your where clause not the real field name and Doctrine will produce the proper SQL:
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('tr')
->where('tr.activo = :activo')
->leftJoin('tr.tipoTramites', 'ttr')
->andWhere("ttr.id = :tramite")
->setParameter("tramite", 1)
->setParameter('activo', true);
}
This will produce the proper SQL.
The only tip is you do not have access to the generated fields of third table in you DQL, but it will be handled by Doctrine and you can use the join table id instead

Delete function using join in DQL

I'm trying to use the Doctrine QueryBuilder to perform the Delete function using query
I need to delete a record that is present in 2 tables ,
in TcTracks table the id is "id" and in TcWall teh id is "related_id"
my controller
public function deleteAction(Request $request){
$deleteQuery = $this->getDoctrine()
->getManager()
->createQueryBuilder('d')
->delete('TcPlayerBundle:TcTracks', 'd')
->innerJoin('TcprofileBundle:TcWall', 't', 'ON', 'd.id = t.related_id')
->where('d.id = :dId')
->setParameter('wId', $request->get('related_id'))
->setParameter('dId', $request->get('id'))
->getQuery();
$deleted = $deleteQuery->getResult();
$deleted->flush();
return $this->render('TcPlayerBundle:Default:all.html.twig',array(
'tracks' => $tracks
));
}
i need to delete same record in two tables , but its not performing for both tables, kindly help me
i'm getting error as
Invalid parameter number: number of bound variables does not match number of tokens
Remove the line below:
->setParameter('wId', $request->get('related_id'))
There is only :dId but no :wId.
Actually you did inner join by 'd.id = t.related_id', so related_id is not necessary to set any more.
You don't have wID parameter anywhere in query. In the same time you're using ->setParameter('wId', $request->get('related_id')) which is obsolete in this case. Try to remove this row and it should be fine.
Is one-to-many realation with your entities
TcPlayerBundle:TcTracks
and
TcprofileBundle:TcWall
if like that,you can do some like:
oneToMany:
cascade: [remove]
in your config 'yourentity.orm.yml' file..
hope hlep you!

Doctrine: Invalid parameter number: number of bound variables does not match number of tokens

I have a Subscribers table which consists of emails (not unique) and a category for each email.
I am trying to find the emails for each category using the following function but get the error:
Invalid parameter number: number of bound variables does not match number of tokens
This is my function:
public function findEmailsByCategory($category)
{
$result = $this->getEntityManager()
->createQuery(
'SELECT s.email FROM NEWSBlogBundle:Subscribers s WHERE s.category =:category'
)->getResult();
return $result;
}
Can anyone tell me where I'm going wrong?
You didn't specified "category" parameter value. Please see Doctrine DQL usage.
ex.
$query = $em->createQuery('SELECT u FROM ForumUser u WHERE u.username = :name');
$query->setParameter('name', 'Bob'); // you didn't add required parameter.
$users = $query->getResult();

Resources