How to get Array Results in findAll() - Doctrine? - symfony

I need to fetch all records in database as Array using findAll() in Doctrine, My Query is Something like this
$result = $this->getDoctrine()
->getRepository('CoreBundle:Categories')
->findAll(\Doctrine\ORM\Query::HYDRATE_ARRAY);
even if set Hydration Mode to HYDRATE_ARRAY, am getting results as objects
array:4 [▼
0 => Categories {#323 ▶}
1 => Categories {#326 ▶}
2 => Categories {#329 ▶}
3 => Categories {#332 ▶}
]
what mistake i made?

The findAll() method does not have any parameters. You can, for example, use the repository's createQueryBuilder() method to achieve what you want to do:
use Doctrine\ORM\Query;
// ...
$query = $this->getDoctrine()
->getRepository('CoreBundle:Categories')
->createQueryBuilder('c')
->getQuery();
$result = $query->getResult(Query::HYDRATE_ARRAY);

It's possible to use $query->getArrayResult()
as a shortcut to $query->getResult(Query::HYDRATE_ARRAY)
doctrine hydration modes

The format in which the result of a DQL SELECT query is returned can be influenced by a so-called hydration mode
so you couldn't use it for findAll().you may try this below:
$em = $this->getDoctrine()->getManager();
$result = $em->createQuery('select m from CoreBundle:Categories m')
->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);

Sorry, I wake up this old topic after years but I find the solution offered by JMS Serializer very elegant to convert arrays of Doctrine objects into associative arrays (e.g. JSON) without having to cutomize/rewrite your repositories findAll() methods.
I think it might help some people here since JMS is a lightweight framework that is really easy to configure.
The code snippet to use will look like this:
$serializer = SerializerBuilder::create()->build();
$employees = getEmployeeRepo->findAll();
$arrEmployees = $serializer->toArray($employees);

I have made this function:
https://gist.github.com/AndreiLN/3708ab829c26cee4711b1df551d1385f
/**
* Converte um objeto Doctrine para um array
* #param $dados
* #param $single define se é uma única execução (Sem recursividade)
* #return array
*/
public function doctrine_to_array($data, $single = false) {
if (is_object($data)) { // Verifica se é array ou objeto
$methods = get_class_methods($data);
$methods = array_filter($methods, function($val){ return preg_match('/^get/', $val); });
$return = [];
if(count($methods)){
foreach($methods as $method){
$prop = lcfirst(preg_replace('/^get/', "", $method));
$val = $data->$method();
if(!$single){
$return[$prop] = $this->doctrine_to_array($val, $single);
} else {
if(!is_array($val) && !is_object($val)){
$return[$prop] = $val;
}
}
}
}
return $return;
} else if(is_array($data)){
if(count($data)){
foreach($data as $idx => $val){
$data[$idx] = $this->doctrine_to_array($val, $single);
}
}
}
return $data; // Retorna o próprio valor se não for objeto
}
If you find some upgrade please let me know.
Explaining more of this function: it's get the doctrine object of array, if it's a object it's reads all get's methods to get all values, if this values is another doctrine object (And single option is not set) it's call the function recursively until it's done.
If the parameter is a array the function will go throught of it and call the method again for all it's values.
It's easy to use, but not tested in all situations.

Related

Doctrine 2 (Symfony) Result set mapping with custom field is always null

I'm performing the following native query in Symfony 2 repository:
$sql = "SELECT f.id, f.title, 'hi' AS custom_field FROM my_feed f";
$em = $this->getEntityManager();
$rsm = new \Doctrine\ORM\Query\ResultSetMapping($em);
$rsm->addEntityResult('MedicalCoreBundle:Feed', 'f');
$rsm->addFieldResult('f', 'id', 'id');
$rsm->addFieldResult('f', 'title', 'title');
$rsm->addFieldResult('f', 'custom_field', 'custom_field');
$query = $em->createNativeQuery($sql, $rsm);
$result = $query->getResult();
I have created the non-mapped property custom_field and its getter and setter getCustomField and setCustomField in the Feed entity.
Mapped fields are hydrated properly but when i add the custom_field RSM i get the following error: Notice: Undefined index: custom_field [...] in symfony\..\AbstractHydrator.php.
Entity code
// non mapped field
private $custom_field;
public function getCustomField()
{
return $this->custom_field;
}
public function setCustomField($number)
{
$this->custom_field = (int) $number;
return $this;
}
What am i doing wrong here ?
You should map custom_field or use addScalarResult instead of addFieldResult
...
$rsm->addScalarResult('custom_field', 'custom_field');
...
result will look like
[
[0=>entity, 'custom_field'=>custom_field value],
[0=>entity, 'custom_field'=>custom_field value],
...
]
Relatvie to your error, you seem to have a F instead of f in custom_Field somewhere.

Key "catTitle" for array with keys "0" does not exist in EagleShopBundle:global:product.html.twig

I'm trying to join two tables and print a value in twig template but I'm having this issue.
This is my Controller action.
/**
* #Route("products/display/{id}")
* #Template()
*/
public function displayAction($id) {
$em = $this->container->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('p', 'pc.catTitle')
->from('EagleShopBundle:Products', 'p')
->leftJoin('EagleShopBundle:ProductCategory', 'pc', \Doctrine\ORM\Query\Expr\Join::WITH, 'pc.id = p.category')
->where($qb->expr()->eq('p.id', '?5'))
->setParameter(5, $id);
$product = $qb->getQuery()->getResult();
return $this->render("EagleShopBundle:global:product.html.twig", array(
'product' => $product,
'image_path' => '/bundles/eagleshop/images/'
));
}
This is my twig file line related to the issue,
<small class="pr_type">{{product.catTitle}}</small>
But instead of printing 'catTitle' I'm having this issue,
Key "catTitle" for array with keys "0" does not exist in
EagleShopBundle:global:product.html.twig
It is simple: getResult() returns an array of objects, even if there is only one. If you are expecting that this query would return only one object use getOneOrNullResult(). But after that and before you are displaying results you need to check if smth is returned (for example: product instanceof Products) or null is returned.

Key "productTitle" for array with keys "0, catTitle" does not exist in EagleShopBundle:global:product.html.twig

I'm trying to join two tables and print a value in twig template but I'm having this issue.
This is my Controller action.
/**
* #Route("products/display/{id}")
* #Template()
*/
public function displayAction($id) {
$em = $this->container->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('p, pc.catTitle')
->from('EagleShopBundle:Products', 'p')
->leftJoin('EagleShopBundle:ProductCategory', 'pc', \Doctrine\ORM\Query\Expr\Join::WITH, 'pc.id = p.category')
->where($qb->expr()->eq('p.id', '?5'))
->setParameter(5, $id);
$product = $qb->getQuery()->getOneOrNullResult();
return $this->render("EagleShopBundle:global:product.html.twig", array(
'product' => $product,
'image_path' => '/bundles/eagleshop/images/'
));
}
This is my twig file line related to the issue,
<h1>{{product.productTitle}}</h1>
I guess issue is related to this line
$qb->select('p, pc.catTitle')
This is the error I get,
Key "productTitle" for array with keys "0, catTitle" does not exist in
EagleShopBundle:global:product.html.twig
You could try next query:
$qb->select('p, partial pc.{id, catTitle}')
// if you need full productCategory object then write just 'p, pc'
->from('EagleShopBundle:Products', 'p')
->leftJoin('p.category', 'pc')
//productCategory is the field
//in product entity which has relation to product category entity,
//paste your field (not column!) name here
//if it is not productCategory
->where('p.id = :productId')
->setParameter('productId', $id);
P.S.
It is better to move queries to entity repositories :)
P.P.S.
Doctrine partial objects
UPD
Fixed query - with right field name

symfony doctrine find User by Email

ok, with
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->find($user_id)
I get an User by the given Identifier (ID).
but how can I get him by given email?
$emailCheck = $em->createQueryBuilder('u')
->select('u, r')
->where('u.email = :email')
->setParameter('email','test#email.com')
->getQuery();
Whill it return an array or an object? Is this the right way to handle it?
This will return a User object.
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->findOneByEmail($email);
You can use either
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->findBy(array('email' => $email));
To load an array of User entities. (Will always be a list, even with 0 or 1 results.)
Or you can do:
$user = $this->getDoctrine()
->getRepository('UserBundle:User')
->findOneBy(array('email' => $email));
This will return the first found result as a User entity object.
You can use the getOneOrNullResult(), as well, it's the long variant. Note however that you should always use setMaxResults(1) with this, otherwise you'll get an exception if more than one result is found (SF 2.3.x).
Either you use the magic method of Doctrine findOneByyour_field or you can create your own method in your repo
public function findOneByEmailAndStoreId($email, $store_id)
{
$q = $this->createQueryBuilder('c')
->where('c.email = :email')
->andWhere('c.store_id = :store_id')
->setParameter('email', $email)
->setParameter('store_id', $store_id)
->getQuery();
return $q->getOneOrNullResult(); // will return only one result or null 'getResult' will return a collection
}

Use Limit and Offset in Doctrine2 query

I'm trying to do the pagination, but there is an error:
[Syntax Error] line 0, col 57: Error: Expected end of string, got 'limit'
I'm not quite sure if this is the right syntax (and logic) to make my query:
public function getFriendsFromTo ($user, $limit, $offset)
{
return $this->getEntityManager()
->createQuery('SELECT f FROM EMMyFriendsBundle:Friend f WHERE f.user='.$user.' limit '.$limit. 'offset' .$offset)
->getResult();
}
Friends and users are related manyToOne and oneToMany, so in the friends table there is a field - user_id.
This is in my controller:
$user = $this->get('security.context')->getToken()->getUser();
$id = $user->getId();
$friends = $user->getFriends();
$result = count($friends)
$FR_PER_PAGE = 7;
$pages = $result/$FR_PER_PAGE;
$em = $this->getDoctrine()->getEntityManager();
$friends = $em->getRepository('EMMyFriendsBundle:Friend')
->getFriendsFromTo($id, $FR_PER_PAGE, $page*$FR_PER_PAGE);
I know that it's stupid and even wrong (especially the third parameter to be $page*$FR_PER_PAGE), but I just wanted to try if the query works, and it didn't.
Nope. Use:
return $this->getEntityManager()
->createQuery('...')
->setMaxResults(5)
->setFirstResult(10)
->getResult();
$towary = $this->getDoctrine()
->getRepository('AcmeStoreBundle:Towar')
->findBy(array(),array(),10,($current-1)*$numItemsPerPage);
You can use findBy 3rd and 4th parameters of method of doctrine repository, which are limit and offset.
Here is the method definition:
findBy(
array $criteria,
array $orderBy = null,
integer|null $limit = null,
integer|null $offset = null
)
Source: http://www.doctrine-project.org/api/orm/2.2/class-Doctrine.ORM.EntityRepository.html
you can also use
$query->getSingleResult();
Doctrine2.6, stumbled upon this old post and tried the DQL way but it did not fit for purpose. So if you want to avoid using DQL because you already have Entities mapped and joined together, you can do paging using matching & Criteria
$criteria = Criteria::create()
->setMaxResults($limit ? $limit : null)
->setFirstResult($offset ? $offset : null)
$result = $em->getRepository('EMMyFriendsBundle:Friend')
->matching($criteria)->toArray();

Resources