Doctrine Paginator Iteration is an array of 1 object - symfony

I'm trying to use doctrines Paginate class to fetch some tasks.
$qb = $this->getEntityManager()
->createQueryBuilder()
->select('DISTINCT task, priority, company, invoice')
->addSelect('priority.id as priority_id')
->from('TekniqSD4Bundle:task', 'task')
->leftJoin('task.slips', 'slips')
->leftJoin('task.comments', 'comments')
->leftJoin('task.files', 'files')
->leftJoin('task.steps', 'steps')
->leftJoin('task.status', 'status')
->join('task.invoice', 'invoice')
->join('task.priority', 'priority')
->join('invoice.company', 'company');
$query = $qb->getQuery()
->setMaxResults(2)
->setFirstResult($offset);
$paginator = new Paginator($query, true);
foreach($paginator as $task){
var_dump($task); //this spits out an array containing 1 task
}
My question is, why is $task an array?

The selected priority.id in your DQL is causing this problem, since the ORM has to retrieve it as scalar result. Accessing $task[0] should give you fetch-joined task object, while $task['priority_id'] gives you the scalar representing priority.id.

Related

Symfony4 / Doctrine, how select 'distinct' objects ? getResult() return an array of string, not an array of object

From Symfony4/Doctrine, I need to select all "distinct" objects with a entity's repository custom method, below a simple example :
An minimal example table of an entity :
A simple $em->getRepository(MyEntity::class)->findAll(); return all data of my table in object structure.
I'm looking for a way to do the same query with a distinct in relation with the column name. With my example, this query must return the objects 1, 3 and 5.
I tried this entity's repository custom method :
public function getDistinct(){
$query = $this->createQueryBuilder('myentity');
$res = $query
->select("myentity.name")
->distinct(true)
->getQuery()
->getResult();
return $res;
}
But the $res var contains an array of string results, not a array of object (I want an array of entity Objects).
How can I do that ?
Try group by myentity.name instead of distinct.
$res = $query
->select("myentity")
->groupBy("myentity.name")
->getQuery()
->getResult();
This should do the job as expected.

Symfony2 simple query: can't fetch an object, only array

The following query in Symfony2.6 works with getArrayResult(); BUT doesn't work with getResult(); or getOneOrNullResult();. This means that I can't fetch an object but only an array.
If I use this query, all I get is a white/blank page (not even the symfony debug toolbar). Note that in my twig template I just do a {{ dump() }} of the query result.
The table structure is easy (it's a list of books read by the users):
id, user, book, status, vote, review
(user, book and status are foreign keys)
public function selectOneRecordBy2Ids($user_id, $book_id)
{
/* #var $qb QueryBuilder */
$qb = $this->createQueryBuilder('l');
$qb->select('l');
$qb = $qb->Where($qb->expr()->eq('l.user', ':first'));
$qb = $qb->andWhere($qb->expr()->eq('l.book', ':second'));
$qb = $qb->setParameters(array('first' => $user_id, 'second' => $book_id));
return $qb->getQuery()->getOneOrNullResult();
}
I've noticed a few bad practices here, so let me correct them:
public function selectOneRecordBy2Ids(User $user, Book $book)
{
/* #var $qb QueryBuilder */
$qb = $this->createQueryBuilder('l');
$qb
->andWhere($qb->expr()->eq('l.user', ':first'))
->andWhere($qb->expr()->eq('l.book', ':second'))
->setParameters(array('first' => $user, 'second' => $book));
return $qb->getQuery()->getResult();
}
Select is not necessary if you work only with one entity and you don't fetch any relations. QB returns $this so you can chain the method calls.
Try to use entities as parameters instead of primitive types (if it is possible). If not, then you have to use primitive types as primitives in QB. In this case you'll need a few joins:
->select('l')
->join('l.user', 'u')
->join('l.book', 'b')
->andWhere($qb->expr()->eq('u.id', ':first'))
->andWhere($qb->expr()->eq('b.id', ':second'))
->setParameters(array('first' => $user_id, 'second' => $book_id));
If you want to fetch only one record, then you may have to limit the results by setting the max results:
->setMaxResults(1)
I hope this helps and solves your original problem as well.
getOneOrNullResult() does not return the record, but tells you if any record in database is found, or not.
You might want to use getSingleResult()

doctrine query onetonmany / notIn with objects / symfony forms querybuilder

I am using symfony 2 and doctrine to prefilter a form field type 'entity' with the help of a querybuilder.
My querybuilder should return all products which the user has not already added to a list.
All relations are bidirectionnal.
I have products linked to userIngredients (oneToMany) each linked to one user (manyToOne)
I have come with this so far but it's not working, I get products not added by other users.
return $this
->createQueryBuilder('p')
->leftJoin('p.userIngredients', 'i')
->where('i.user <> ?1')
->setParameter(1,$user);
1; Any clue on how to correct this ?
Alternatively, I could select the products I don't want and then reselect those who don't match but using an expression and NotIn seems to only work for strings
$products = $this
->createQueryBuilder('p')
->leftJoin('p.userIngredients', 'i')
->where('i.user = ?1')
->setParameter(1,$user)
->getQuery()
->getResult();
return $this
->createQueryBuilder('p')
->where($this->createQueryBuilder('p')->expr()->notIn('p', $products));
2; how could we correct this to make it work with objects ?
3; alternatively : is there a way to pass not a querybuilder but an array of results to symfony form builders ?
I got thinks thanks to Javad:
(slight modification, I'm using an array result, not dql):
$qb = $this->_em->createQueryBuilder();
$ids = $qb
->select('p.id')
->from('AppBundle:MarketPlace\Product','p','p.id')
->leftJoin('p.userIngredients', 'i')
->where('i.user = ?1')
->setParameter(1,$user)
->getQuery()
->getResult();
//I don't know why I couldn't directly get an array of ids otherwise... if you know how to do better directly from the query, I'm interested (getScalarResult does not make it)
$ids=array_keys($ids);
$result = $this
->createQueryBuilder('p')
->where($this->createQueryBuilder('p')->expr()->notIn('p.id', $ids));
return $result;

Symfony2 Doctrine2 use of partials

From reading the documentation and another stackoverflow post, I thought that if I only want to return a couple of columns data, the correct method in doctrine was to use a partial. (This is a read only query).
However the below code returns all 100 columns instead of the 3 I identified. Can someone explain why?
Thanks,
Manisha
public function showAction(Request $request)
{
if ($request->getMethod() == 'GET') {
$id = $request->get('locationid');
$kfType = $request->get('type');
$em = $this->getDoctrine()
->getManager();
$data = $em->createQueryBuilder()
->select ( array( 'partial d.{id, locationid, kfFyp}' ))
->from('DashDataBundle:Data', 'd')
->where('d.locationid = :locationid')
->setParameter('locationid', $id)
->setMaxResults(100)
->getQuery()
->getResult();
}
This query will return doctrine entities which have many fields. But then you use partial keywords this fields would be empty. Only specified fields would be filled with data.
If you doesnt want to hydrate objects you can get data in simple array if you specify it
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY)

Query only works if I run a query before it

I want to get the schools the user is in, but for some reason I can only access it by running a query to the school table that is otherwise unrelated. Here is my code:
This doesn't work (within the controller):
$schoolsEnrolled = $this->getUser()->getSchools();
The result is an Array with a School object with all it's properties as null (other than id for some reason).
This does work (within the controller):
//unrelated query
$repository = $this->getDoctrine()->getRepository('AcmeMainBundle:School');
$query = $repository->createQueryBuilder('s')->getQuery();
$schools = $query->getResult();
//the query I care about
$schoolsEnrolled = $this->getUser()->getSchools();
The result is an array of schools as desired.
Here are the related methods:
In the School Class:
public function getSchools(){
$schools = array();
foreach ($this->schoolHasUsers as $key=>$schoolHasUser){
$schools[] = $schoolHasUser->getSchool();
}
return $schools;
}
In the SchoolHasUser Class:
public function getSchool()
{
return $this->school;
}
How can I get the query I care about to work without the unrelated query?
In doctrine object can be lazy-loaded. Then you call $schoolHasUser->getSchool(); you trully no query the database, only get proxy object. So try to get some property of it, example getName or getId. This action make a call to DB and fetch object.
One of the proper ways to do it is like this
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('YourBundle:YourEntity')->findAll();

Resources