Doctrine ResultSetMapping(Builder) is not showing any results - php

My normal query was looking like this.
$qb = $placeRepository->createQueryBuilder('p');
var_dump($qb->getQuery()->getResult());
I'll get few results as objects.
So this is the normal behaviour.
Then I want to add a custom field with ResultSetMapping.
$qb = $placeRepository->createQueryBuilder('p');
$qb->addSelect('123 as distance');
$rsm = new ResultSetMapping;
$rsm->addEntityResult(Place::class, 'p');
$rsm->addFieldResult('p', 'id', 'id');
$rsm->addScalarResult('distance', 'distance');
var_dump($qb->getQuery()->setResultSetMapping($rsm)->getResult());
With a ResultSetMappingBuilder its also not working.
$qb = $placeRepository->createQueryBuilder('p');
$qb->addSelect('123 as distance');
$rsm = $placeRepository->createResultSetMappingBuilder('p');
var_dump($qb->getQuery()->setResultSetMapping($rsm)->getResult());
Not working means: Array with zero items in it.

Ok found it.
But not working like I want 😢
/** #var \Doctrine\ORM\EntityManager $em */
$em = $this->getDoctrine()->getManager();
// Working but bad because defining all by yourself
$rsm = new ResultSetMapping();
$rsm->addEntityResult(Place::class, 'p');
$rsm->addFieldResult('p','p_id','id');
// Good
$rsmB = new ResultSetMappingBuilder($em);
$rsmB->addRootEntityFromClassMetadata(Place::class, 'p');
// Not working because separate field
//$rsmB->addScalarResult('distance', 'distance');
// Not working because not found ... (not a #ORM\Column)
$rsmB->addFieldResult('p', 'distance', 'distance');
I added comments why its not working.
Now I'm going to loop 😅

Related

How to get data from a column with this annotation #ORM\index

Good afternoon, please tell me how to get the column data:
{#ORM\Index(name="localities_names_idx", columns={"name_ru", "name_cn", "name_en"})
I tried using queryBuilder :
$qb
->select('a')
->from(Locality::class, 'a')
->where('a.name_ru = :name_ru')
->andWhere('a.area is null')
->setParameter('name', 'Moscow');
$query = $qb->getQuery();
Without success
I need it for:
$em = $this->entityManager;
$qb = $em->createQueryBuilder();
$qb
->select('a')
->from(Locality::class, 'a')
->where('a.name_ru = :name_ru')
->andWhere('a.area is null')
->setParameter('name', 'Москва');
$query = $qb->getQuery();
$result = $query->getResult(Query::HYDRATE_SCALAR);
$location = new Location();
$location->setLocality($result[0]['a_id']);
$location->setAddress($address);
$em->persist($location);
$em->flush();
return $location->getId();
Edit: This turned into a review, but might as well keep it here
You're using index wrong.
I'm guessing you're using it incorrectly. I'm assuming you want an index for faster search. However, the way you do now you've created a combined index. Example:
{#ORM\Index(name="thing_colour_idx", columns={"thing", "colour"})
Thing | Colour
--------------
Car Blue
Car Red
Bike Green
Bike Yellow
If you always (or at least most of the time) select by both columns, eg you always search for a BLUE+CAR, or a GREEN+BIKE, than this is the way to go.
However, if you to select all Thing=Car, without colour, then this index does nothing. You want this:
indexes={
#ORM\Index(name="thing_idx", columns={"thing"}),
#ORM\Index(name="colour_idx", columns={"colour"})
}
You're not using getResult as intended
You do ->getResult(Query::HYDRATE_SCALAR), but then follow it up with a ->setLocality($result[0]['a_id']). Unless you have performace issues, you dont work with IDs, thats a problem for Doctrine, not you. You should only care about objects:
$locality = $em
->createQueryBuilder()
->from(Locality::class, 'a')
->where('a.name_ru = :name_ru')
->andWhere('a.area is null')
->setParameter('name', 'Москва') // <- btw, this should be 'name_ru', same as two lines heigher
->getQuery()
->getSingleResult();
$location = new Location();
$location->setLocality($locality);
Dont use the querybuilder like that, use a repository
You're now placing service logic and query logic in one code. That is incorrect. An example of the way Symfony is intented:
class LocalityRepository extends ServiceEntityRepository{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Locality::class);
}
public function getLocalityByRuName(string $name): Locality
{
return $this->createQueryBuilder('a')
->where('a.name_ru = :name_ru')
->andWhere('a.area is null')
->setParameter('name_ru', $name);
->getQuery();
->getSingleResult();
}
}
class YourService
{
public function __construct(
private LocalityRepository $localityRepository
){}
public function somethingSomething()
{
$locality = $this->localityRepository->getLocalityByRuName('Москва');
$location = new Location();
$location->setLocality($locality);
}
}
Final note: Try not to use a ->flush() in a service. The job of a service is to do work, not to decide what to do it. A controller decides when something is done. Suppose you have another service which in which you alter things, but DONT want to flush them. You can now no longer use any service method that flushes.
The error was that there were no name properties Ru

How to execute DQL query in Symfony2?

I am trying to get objects from DQL query.
Here is my code :
$em = $this->getDoctrine()->getRepository(Item::class);
$items = $em->createQuery($getQuery);
$items = $query->getResult();
$getQuery = DQL query string : SELECT from Entity WHERE ...
I am receiving error : Undefined method 'createQuery'. The method name must start with either findBy or findOneBy!
I don't understand it, bcz this example is copied from official documentation.
How I can execute DQL query in queryBuilder/createQuery?
Entity manager has a createQuery method.
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery($getQuery);
$items = $query->getResult();
Repository has a createQueryBuilder method.
$em = $this->getDoctrine()->getManager();
$qb = $em->getRepository(Item::class)->createQueryBuilder();
$query = qb->select('[columns]')->from('Entity')->where('[condition]')->getQuery();
$items = $query->getResult();

Building a query to search for multiple attributes

I am very new to coding, especially with Symfony. But now my teacher has given me a task to create a query to search within 2 attributes. I have started writing the query, but there is still a lot lacking. I am wondering if someone can help, or send a link to help me finish it.
I need to make a search option which looks up into Artikelnummer and Omschrijving.
/**
* #Route("/artikel/zoek", name="zoekartikel")
*/
Public function zoek(Request $request){
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT a
FROM AppBundle:Artikel a
WHERE a.artikelnummer = input AND a.omschrijving LIKE input2'
);
$artikelen = $query->getResult();
return new Response($this->render('search.html.twig',
array('artikelen' => $artikelen)));
}
You need first to instantiate Result Mapping
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping();
Then
$query = $em-> createNativeQuery(
'SELECT a
FROM AppBundle:Artikel a
WHERE a.artikelnummer = ? AND a.omschrijving LIKE ?',
$rsm
);
$query->setParameter(1, 'input1'); // or var
$query->setParameter(2, 'input2'); // or var
$artikelen = $query->getResult();
return new Response($this->render('search.html.twig',
array('artikelen' => $artikelen)));
More docs here http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html

Doctrine- setting query parameters conditionally

I building application in Symfony 2.
I have to filter users basing on data passed in form.
I wrote something like this in my controller:
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$qb->addSelect('user');
$qb->from('Application\Sonata\UserBundle\Entity\User', 'user');
if(($filter['freelancer'])){
$qb->setParameters(array('freelancer' => $filter['freelancer']))
->andWhere('user.firstname = :freelancer');
}
if(($filter['category'])){
$qb->innerJoin('Flexihub\MainBundle\Entity\Category', 'category', 'WITH', 'user.category = category.id')
->setParameters(array('category' => $filter['category']))
->andWhere('user.category = :category');
}
$query = $qb->getQuery();
$result = $query->getResult();
dump($result);
Im stuck with error when im trying to pass both parameters.
Invalid parameter number: number of bound variables does not match number of tokens
What am I doing wrong?
Is there better solution to solve my problem?
It's logical to write it like this, so, first add criteria then provide arguments:
if(($filter['freelancer'])){
$qb
->andWhere('user.firstname = :freelancer')
->setParameter('freelancer', $filter['freelancer']);
}
if(($filter['category'])){
$qb
->innerJoin('Flexihub\MainBundle\Entity\Category', 'category', 'WITH', 'user.category = category')
->andWhere('user.category = :category')
->setParameter('category', $filter['category']);
}

Symfony2: How to convert 'Doctrine->getRepository->find' from Entity to Array?

I want to return an \Symfony\Component\HttpFoundation\JsonResponse with the record information, but I need to pass it as array.
Currently I do:
$repository = $this->getDoctrine()->getRepository('XxxYyyZzzBundle:Products');
$product = $repositorio->findOneByBarCode($value);
But now $product is an Entity containing all what I want, but as Objects. How could I convert them to arrays?
I read somewhere that I need to use "Doctrine\ORM\Query::HYDRATE_ARRAY" but seems 'findOneBy' magic filter does not accept such parameter.
*
* #return object|null The entity instance or NULL if the entity can not be found.
*/
public function findOneBy(array $criteria, array $orderBy = null)
Well thanks to dbrumann I got it working, just want to add it the full working example.
Also seems that ->from() requires 2 parameters.
$em = $this->getDoctrine()->getManager();
$query = $em->createQueryBuilder()
->select('p')
->from('XxxYyyZzzBundle:Products','p')
->where('p.BarCode = :barcode')
->setParameter('barcode', $value)
->getQuery()
;
$data = $query->getSingleResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
When you want to change the hydration-mode I recommend using QueryBuilder:
$query = $em->createQueryBuilder()
->select('p')
->from('Products', 'p')
->where('p.BarCode = :barcode')
->setParameter('barcode', $valur)
->getQuery()
;
$data = $query->getSingleResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
But what would probably be better, is adding a toArray()- or toJson()-method to your model/entity. This way you don't need additional code for retrieving your entities and you can change your model's data before passing it as JSON, e.g. formatting dates or omitting unnecessary properties.
Have done this two ways if you are working with a single entity:
$hydrator = new \DoctrineModule\Stdlib\Hydrator\DoctrineObject($entityManager);
$entityArray = $hydrator->extract($entity);
Last resort, you can just cast to an array like any other PHP object via:
$array = (array) $entity
NB: This may have unexpected results as you are may be working with doctrine proxy classes, which may also change in later Doctrine versions..
Can also be used:
$query = $em->createQueryBuilder()
->select('p')
->from('Products', 'p')
->where('p.BarCode = :barcode')
->setParameter('barcode', $valur)
->getQuery()
;
$data = $query->getArrayResult();

Categories