ZF2 and Doctrine 2 convert resultset to Array - php

I use Zend Framework 2 with Doctrine 2. Here is my problem
The following returns Array of Objects
$results = $em->getRepository('MyProject\Domain\User')->find($id);
Returns:
array (size=4)
0 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
1 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
3 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
4 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
I want to convert it to Array of Arrays like so:
array (size=4)
0 =>
array (size=3)
['id'] => int 1
['firstName'] => string 'joe' (length=3)
['lastName'] => string 'smith' (length=5)
1 =>
array (size=3)
['id'] => int 1
['firstName'] => string 'joe' (length=3)
['lastName'] => string 'smith' (length=5)
2 =>
array (size=3)
['id'] => int 1
['firstName'] => string 'joe' (length=3)
['lastName'] => string 'smith' (length=5)
3 =>
array (size=3)
['id'] => int 1
['firstName'] => string 'joe' (length=3)
['lastName'] => string 'smith' (length=5)
I have tried the following:
$resultsArray = new \Doctrine\Common\Collections\ArrayCollection($results);
$resultsArray->toArray();
$resultsArray = new \Zend\Stdlib\ArrayObject($results);
$resultsArray->getArrayCopy();
Both return this:
array (size=4)
0 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
1 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
3 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
4 =>
object(My\Entity\User)[3]
private 'id' => int 1
private 'firstName' => string 'joe' (length=3)
private 'lastName' => string 'smith' (length=5)
How can I accomplish this? What is the recommended way of doing it?

In its simplest form, the following does what you want
$qb = $em->getRepository('My\Entity\User')->createQueryBuilder('User');
$result = $qb->getQuery()->getArrayResult();
Normally you'd use a custom repository and add your DQL queries as methods as describe here in the docs
http://docs.doctrine-project.org/en/2.0.x/tutorials/getting-started-xml-edition.html#entity-repositories

Yet another way to code it, which I use:
//at the top of custom repository class
use Doctrine\Orm\Query;
//in the method
$dql = "SELECT u FROM MyProject\Domain\User u WHERE u.id = $id"
$query = $entityManager->createQuery($dql);
$users = $query->getResult(Query::HYDRATE_ARRAY);
//knowing the code you provided, this should give you an array of four arrays

Traditionally, I write a custom repository class and call a getArrayResult() inside of it
$dql = 'MYDQLHERE';
$query = $this->getEntityManager()->createQuery($dql);
$query->execute();
$result = $query->getArrayResult();
I believe your other option is custom hydration modes, although I don't have experience with them. http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#custom-hydration-modes

Related

php pdo PDO::FETCH_LAZY Keeping track of db cursor/pointer

What am I doing wrong? How do I track the db cursor if the primary key is not consecutive?
MySQL driver.
$sql = "SELECT * FROM employees";
$stmt = $db->query($sql);
$result = $stmt->fetch(PDO::FETCH_LAZY);
var_dump($result);
output:
object(PDORow)[3]
public 'queryString' => string 'SELECT * FROM employees' (length=23)
public 'employeeNumber' => string '1002' (length=4)
public 'lastName' => string 'Murphy' (length=6)
public 'firstName' => string 'Diane' (length=5)
public 'extension' => string 'x5800' (length=5)
public 'email' => string 'dmurphy#classicmodelcars.com' (length=28)
public 'officeCode' => string '1' (length=1)
public 'reportsTo' => null
public 'jobTitle' => string 'President' (length=9)
$result = $stmt->fetch(PDO::FETCH_ORI_FIRST);
var_dump($result);
output:
array (size=8)
'employeeNumber' => string '1056' (length=4)
'lastName' => string 'Patterson' (length=9)
'firstName' => string 'Mary' (length=4)
'extension' => string 'x4611' (length=5)
'email' => string 'mpatterso#classicmodelcars.com' (length=30)
'officeCode' => string '1' (length=1)
'reportsTo' => string '1002' (length=4)
'jobTitle' => string 'VP Sales' (length=8)
$result = $stmt->fetch(PDO::FETCH_ORI_NEXT);
var_dump($result);
output:
array (size=16)
'employeeNumber' => string '1076' (length=4)
0 => string '1076' (length=4)
'lastName' => string 'Firrelli' (length=8)
1 => string 'Firrelli' (length=8)
'firstName' => string 'Jeff' (length=4)
2 => string 'Jeff' (length=4)
'extension' => string 'x9273' (length=5)
3 => string 'x9273' (length=5)
'email' => string 'jfirrelli#classicmodelcars.com' (length=30)
4 => string 'jfirrelli#classicmodelcars.com' (length=30)
'officeCode' => string '1' (length=1)
5 => string '1' (length=1)
'reportsTo' => string '1002' (length=4)
6 => string '1002' (length=4)
'jobTitle' => string 'VP Marketing' (length=12)
7 => string 'VP Marketing' (length=12)
$result = $stmt->fetch(PDO::FETCH_ORI_LAST);
var_dump($result);
output:
array (size=8)
0 => string '1088' (length=4)
1 => string 'Patterson' (length=9)
2 => string 'William' (length=7)
3 => string 'x4871' (length=5)
4 => string 'wpatterson#classicmodelcars.com' (length=31)
5 => string '6' (length=1)
6 => string '1056' (length=4)
7 => string 'Sales Manager (APAC)' (length=20)

Can't access elements of merged arrays

So I had 2 objects that need to work together, one idea that was given to me was to merge them. Did that, using array_merge
But now I can't access the second object from the merged one and I'm stuck. The keys that appear after merge look a little weird, have I used it wrongly?
$merged=array_merge_recursive((array)$post,(array)$image);
And the var_dump for $merged shows me this:
array (size=10)
0 =>
object(Models\Post)[7]
protected 'id' => string '17' (length=2)
protected 'title' => string 'qwq' (length=3)
protected 'body' => string 'wqwq' (length=4)
protected 'views' => string '22' (length=2)
protected 'imgId' => string '17' (length=2)
protected '_attr_accessible' =>
array (size=3)
0 => string 'title' (length=5)
1 => string 'body' (length=4)
2 => string 'views' (length=5)
protected '_validators' =>
array (size=0)
empty
protected '_errors' =>
array (size=0)
empty
protected '_valid' => boolean true
'�*�id' => string '17' (length=2)
'�*�path' => string '/media/' (length=7)
'�*�name' => string 'col_right_callout.jpg' (length=21)
'�*�idPost' => string '0' (length=1)
'�*�description' => string 'wqeqw' (length=5)
'�*�_attr_accessible' =>
array (size=3)
0 => string 'name' (length=4)
1 => string 'path' (length=4)
2 => string 'description' (length=11)
'�*�_validators' =>
array (size=0)
empty
'�*�_errors' =>
array (size=0)
empty
'�*�_valid' => boolean true
How do I access the path or any field from the second part of the array?
Content of $post
array (size=1) 0 =>
object(Models\Post)[7]
protected 'id' => string '17' (length=2)
protected 'title' => string 'qwq' (length=3)
protected 'body' => string 'wqwq' (length=4)
protected 'views' => string '23' (length=2)
protected 'imgId' => string '17' (length=2)
protected '_attr_accessible' =>
array (size=3)
0 => string 'title' (length=5)
1 => string 'body' (length=4)
2 => string 'views' (length=5)
protected '_validators' =>
array (size=0)
empty
protected '_errors' =>
array (size=0)
empty
protected '_valid' => boolean true
Content of $image
object(Models\Image)[9]
protected 'id' => string '17' (length=2)
protected 'path' => string '/media/' (length=7)
protected 'name' => string 'col_right_callout.jpg' (length=21)
protected 'idPost' => string '0' (length=1)
protected 'description' => string 'wqeqw' (length=5)
protected '_attr_accessible' =>
array (size=3)
0 => string 'name' (length=4)
1 => string 'path' (length=4)
2 => string 'description' (length=11)
protected '_validators' =>
array (size=0)
empty
protected '_errors' =>
array (size=0)
empty
protected '_valid' => boolean true
Because image is object, protected and private properties have special character prepended when you cast object to array.
With post you are casting array to array. If you do something like (array)$post[0] you will get same issue with both objects.
Take a look how to get array out of it: How to convert (cast) Object to Array without Class Name prefix in PHP?

Symfony2 Doctrine Array of joined objects

I have the following repository:
class CustomerRepository extends EntityRepository
{
public function searchCustomer($criteria)
{
$q = $this->createQueryBuilder('c');
$q->join('TeamERPCustomerBundle:Company', 'o',
'WITH', 'c.company = o.id');
if (isset($criteria) and $criteria!=""){
$q->orWhere(sprintf("c.customer_name like '%s'", '%'.$criteria.'%'));
(...)
}
$q = $q->getQuery()->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
return $q;
}
}
I call it from the controller as follows:
$result = $this->getDoctrine()->getManager()
->getRepository('TeamERPCustomerBundle:Customer')
->searchCustomer($customerInfo);
It returns an array of elements as follows:
array (size=20)
0 =>
array (size=9)
'id' => int 1
'customer_name' => string 'Abel' (length=4)
'address' => string 'Calle 52 # 60, % 3era y G. Quezada, Nuevo Sosa' (length=46)
'postal_address' => string '75100' (length=5)
'city_town_village' => string 'Las Tunas' (length=9)
'e_mail' => string 'abel#ltu.sld.cu' (length=15)
'land_line' => string '346386' (length=6)
'cell_phone' => null
'fax' => null
1 =>
array (size=2)
'id' => int 1
'company_name' => string 'Debswana' (length=8)
2 =>
array (size=9)
'id' => int 2
'customer_name' => string 'Kay' (length=3)
'address' => null
'postal_address' => null
'city_town_village' => null
'e_mail' => null
'land_line' => null
'cell_phone' => null
'fax' => null
3 =>
array (size=2)
'id' => int 3
'company_name' => string 'DTC' (length=3)
(...)
It gives one element of the array per object, but what I want it the classic mysql join; as result an array of elements of the same type. Something like mergin elements 1 and 2 together.
The other problem with this query is that is does not work like that classic join ether, it gives all the customers, but only the companies that are not repeated.
Can anyone help me to get a uniform array of elements?
Edit: I managed to find a solution:
$em = $this->getEntityManager();
$query = $em->createQuery('
SELECT c, i
FROM TeamERPCustomerBundle:Customer c
JOIN c.company i');
//$query->setParameter('id', '1'); With this is can add as many parameter as I need
return $query->getResult(\Doctrine\ORM\AbstractQuery::HYDRATE_ARRAY);
This returned something like this:
array (size=11)
0 =>
array (size=10)
'id' => int 1
'customer_name' => string 'Abel' (length=4)
'address' => string 'Calle 52 # 60, % 3era y G. Quezada, Nuevo Sosa' (length=46)
'postal_address' => string '75100' (length=5)
'city_town_village' => string 'Las Tunas' (length=9)
'e_mail' => string 'abel#ltu.sld.cu' (length=15)
'land_line' => string '346386' (length=6)
'cell_phone' => null
'fax' => null
'company' =>
array (size=2)
'id' => int 1
'company_name' => string 'Debswana' (length=8)
As you might have already appreciated this array is different from what I was getting before. so now I just have to go through the array and change it to what ever I want. for instance:
foreach ($result as $key => $value){
$result[$key]['company'] = $value['company']['company_name'];
}
Now we are talking. This Is kind of what I wanted:
array (size=11)
0 =>
array (size=10)
'id' => int 1
'customer_name' => string 'Abel' (length=4)
'address' => string 'Calle 52 # 60, % 3era y G. Quezada, Nuevo Sosa' (length=46)
'postal_address' => string '75100' (length=5)
'city_town_village' => string 'Las Tunas' (length=9)
'e_mail' => string 'abel#ltu.sld.cu' (length=15)
'land_line' => string '346386' (length=6)
'cell_phone' => null
'fax' => null
'company' => string 'Debswana' (length=8)

Removing an item from a multidimensional array in php by value

I have a multidimensional array $array that looks like this:
array (size=3)
0 =>
array (size=1)
0 =>
object(stdClass)[500]
public 'id' => int 2
public 'first_name' => string 'Mary' (length=4)
public 'last_name' => string 'Sweet' (length=5)
1 =>
array (size=1)
0 =>
object(stdClass)[501]
public 'id' => int 9
public 'first_name' => string 'Joe' (length=3)
public 'last_name' => string 'Bob' (length=3)
2 =>
array (size=1)
0 =>
object(stdClass)[502]
public 'id' => int 1
public 'first_name' => string 'Shag' (length=4)
public 'last_name' => string 'Well' (length=4)
I would like to be able to remove one of the items in the array by searching for values (not indexes).
So, I would like to remove the item in the array that has the first_name property of 'Joe'.
So if I removed it, the array would look like this:
array (size=2)
0 =>
array (size=1)
0 =>
object(stdClass)[500]
public 'id' => int 2
public 'first_name' => string 'Mary' (length=4)
public 'last_name' => string 'Sweet' (length=5)
1 =>
array (size=1)
0 =>
object(stdClass)[502]
public 'id' => int 1
public 'first_name' => string 'Shag' (length=4)
public 'last_name' => string 'Well' (length=4)
How would I be able to do this? Thanks.
Yes you could just use a foreach in this case. It will work just fine. Just use your search string needle and add an if inside the loop comparing the objects property firstname and the needle:
$first_name_search = 'Joe';
foreach ($array as $key => $value) {
$value = reset($value); // get that index 0 which is nested
if($value->first_name == $first_name_search) {
unset($array[$key]);
}
}

How to take two random entries from a multidimensional array in PHP

I am looking for a way to take a multidimensional array and choose 2 random entries from the top level to create a new multidimensional array.
For example, if I have an array $data that looks like the below:
array (size=3)
0 =>
array (size=1)
0 =>
object(stdClass)[500]
public 'id' => int 2
public 'first_name' => string 'Mary' (length=4)
public 'last_name' => string 'Sweet' (length=5)
1 =>
array (size=1)
0 =>
object(stdClass)[501]
public 'id' => int 9
public 'first_name' => string 'Joe' (length=3)
public 'last_name' => string 'Bob' (length=3)
2 =>
array (size=1)
0 =>
object(stdClass)[502]
public 'id' => int 1
public 'first_name' => string 'Shag' (length=4)
public 'last_name' => string 'Well' (length=4)
How do I cut it up so that I take two of the three random entries, to get something like $data2:
array (size=2)
0 =>
array (size=1)
0 =>
object(stdClass)[500]
public 'id' => int 2
public 'first_name' => string 'Mary' (length=4)
public 'last_name' => string 'Sweet' (length=5)
1 =>
array (size=1)
0 =>
object(stdClass)[502]
public 'id' => int 1
public 'first_name' => string 'Shag' (length=4)
public 'last_name' => string 'Well' (length=4)
Use array_rand(). You could get more sophisticated depending on what you are doing, but here is the basic idea:
$randkeys = array_rand($data, 2);
$data2 = array($data[$randkeys[0]], $data[$randkeys[1]]);
See demo

Categories