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

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();

Related

Symfony 2 - fetch the last inserted row from table

How can I rewrite this code in order to get last inserted record from the table?
$repository = $entityManager->getRepository('AdminBundle:MyTable');
$product = $repository->find($id);
I tried something like
$repository->findBy(array('id','DESC')->setMaxResults(1);
But it did not work for me.
You could get the latest record by using findBy() with order by, limit and offset parameters
$results = $repository->findBy(array(),array('id'=>'DESC'),1,0);
First argument is for filter criteria
Second argument takes order by criteria
Third argument is for limit
Fourth argument sets offset
Note it will return you the results set as array of objects so you can get single object from result as $results[0]
FindBy() Examples
Instead of hacking code where you want to use it, you can also create a repository method and call it when necessary.
/**
* Repository method for finding the newest inserted
* entry inside the database. Will return the latest
* entry when one is existent, otherwise will return
* null.
*
* #return MyTable|null
*/
public function findLastInserted()
{
return $this
->createQueryBuilder("e")
->orderBy("id", "DESC")
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
}
References:
https://symfony.com/doc/current/doctrine.html#querying-for-objects-the-repository
After looking for one I decided to try it myself, I think it was much less verbose:
$myRepository->findOneBy([], ['id' => 'DESC']);
Please try the below one
$repository = $entityManager->getRepository('AdminBundle:MyTable');
$repository->setMaxResults(1)->orderBy('id', 'DESC');
$results = $repository->getQuery()->getSingleResult();
Reference:
https://undebugable.wordpress.com/2016/01/27/symfony2-querybuilder-find-first-and-find-last-record-in-table/
You can add these functions to your repository:
public function getLastRow(): ?YourEntity
{
return $this->findOneBy([], ['id' => 'DESC']);
}
public function getLastId(): int
{
$lastRow = $this->getLastRow();
return $lastRow ? $lastRow->getId() : 0;
}
You can be collected by getting the id of the inserted object
$em->persist($entity);
$em->flush();
$entity->getId();
OR
$entitymanager->getRepository("entity")->findBy([],["id"=>desc])->getId();

Get all entities ordered with Doctrine query builder

I'm getting a little crazy with this. I have a PhoneCodes entity and I simply want to retrieve all entities ordered by a field so no where condition but I tried to achieve this by many ways and not working. Currently I have this:
$phonecodes = $this->getDoctrine()
->getRepository('AcmeDemoBundle:PhoneCodes')
->createQueryBuilder('p')
->orderBy('p.length', 'ASC')
->getQuery()
->getResult();
What's the way to do this? Thanks.
Your code should be something like this:
$phonecodes = $this->getEntityManager()
->createQueryBuilder()
->select("p")
->from("AcmeDemoBundle:PhoneCodes", "p")
->orderBy("p.length", "ASC")
->getQuery()
->getResult()
If you're in a controller just do this:
$phonecodes = $em->getRepository('AcmeDemoBundle:PhoneCodes')->findBy(
array(),//conditions, none in this case
array(//orderBy, multiple possible
"length"=>"asc"
)
);
This way you don't need to write a custom repository function.
If you wan't to create it as a repository function (e.g. in PhoneCodesRepository.php) do it that way:
/**
* Returns all phoneCodes hydrated to objects ordered by length
* #param string $order - ASC | DESC
* #return \Doctrine\Common\Collections\Collection
*/
function findAllOrderedByLength($order="ASC")
{
$qb = $this->createQueryBuilder("p");
$qb->orderBy("p.length", $order);
return $qb->getQuery()->getResult();
}
http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes

How can I query raw via Eloquent?

I am trying to do a query in my Laravel app and I want to use a normal structure for my query. This class either does use Eloquent so I need to find something to do a query totally raw.
Might be something like Model::query($query);. Only that doesn't work.
You may try this:
// query can't be select * from table where
Model::select(DB::raw('query'))->get();
An Example:
Model::select(DB::raw('query'))
->whereNull('deleted_at')
->orderBy('id')
->get();
Also, you may use something like this (Using Query Builder):
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
Also, you may try something like this (Using Query Builder):
$users = DB::select('select * from users where id = ?', array(1));
$users = DB::select( DB::raw("select * from users where username = :username"), array('username' => Input::get("username")));
Check more about Raw-Expressions on Laravel website.
You can use hydrate() function to convert your array to the Eloquent models, which Laravel itself internally uses to convert the query results to the models. It's not mentioned in the docs as far as I know.
Below code is equviolent to $userModels = User::where('id', '>', $userId)->get();:
$userData = DB::select('SELECT * FROM users WHERE id > ?', [$userId]);
$userModels = User::hydrate($userData);
hydrate() function is defined in \Illuminate\Database\Eloquent\Builder as:
/**
* Create a collection of models from plain arrays.
*
* #param array $items
* #return \Illuminate\Database\Eloquent\Collection
*/
public function hydrate(array $items) {}
use DB::statement('your raw query here'). Hope this helps.
I don't think you can by default. I've extended Eloquent and added the following method.
/**
* Creates models from the raw results (it does not check the fillable attributes and so on)
* #param array $rawResult
* #return Collection
*/
public static function modelsFromRawResults($rawResult = [])
{
$objects = [];
foreach($rawResult as $result)
{
$object = new static();
$object->setRawAttributes((array)$result, true);
$objects[] = $object;
}
return new Collection($objects);
}
You can then do something like this:
class User extends Elegant { // Elegant is my extension of Eloquent
public static function getWithSuperFancyQuery()
{
$result = DB::raw('super fancy query here, make sure you have the correct columns');
return static::modelsFromRawResults($result);
}
}
Old question, already answered, I know.
However, nobody seems to mention the Expression class.
Granted, this might not fix your problem because your question leaves it ambiguous as to where in the SQL the Raw condition needs to be included (is it in the SELECT statement or in the WHERE statement?). However, this piece of information you might find useful regardless.
Include the following class in your Model file:
use Illuminate\Database\Query\Expression;
Then inside the Model class define a new variable
protected $select_cols = [
'id', 'name', 'foo', 'bar',
Expression ('(select count(1) from sub_table where sub_table.x = top_table.x) as my_raw_col'), 'blah'
]
And add a scope:
public function scopeMyFind ($builder, $id) {
return parent::find ($id, $this->select_cols);
}
Then from your controller or logic-file, you simply call:
$rec = MyModel::myFind(1);
dd ($rec->id, $rec->blah, $rec->my_raw_col);
Happy days.
(Works in Laravel framework 5.5)
use Eloquent Model related to the query you're working on.
and do something like this:
$contactus = ContactUS::select('*')
->whereRaw('id IN (SELECT min(id) FROM users GROUP BY email)')
->orderByDesc('created_at')
->get();
You could shorten your result handling by writing
$objects = new Collection(array_map(function($entry) {
return (new static())->setRawAttributes((array) $entry, true);
}, $result));
if you want to select info it is DB::select(Statement goes here) just remember that some queries wont work unless you go to Config/Database.php and set connections = mysql make sure 'strict' = false
Just know that it can cause some security concerns
if ever you might also need this.
orderByRaw() function for your order by.
Like
WodSection::orderBy('score_type')
->orderByRaw('FIELD(score_type,"score_type") DESC')
->get();

How to use a findBy method with comparative criteria

I'd need to use a "magic finder" findBy method using comparative criteria (not only exact criteria). In other words, I need to do something like this:
$result = $purchases_repository->findBy(array("prize" => ">200"));
so that I'd get all purchases where the prize is above 200.
The class Doctrine\ORM\EntityRepository implements Doctrine\Common\Collections\Selectable API.
The Selectable interface is very flexible and quite new, but it will allow you to handle comparisons and more complex criteria easily on both repositories and single collections of items, regardless if in ORM or ODM or completely separate problems.
This would be a comparison criteria as you just requested as in Doctrine ORM 2.3.2:
$criteria = new \Doctrine\Common\Collections\Criteria();
$criteria->where(\Doctrine\Common\Collections\Criteria::expr()->gt('prize', 200));
$result = $entityRepository->matching($criteria);
The major advantage in this API is that you are implementing some sort of strategy pattern here, and it works with repositories, collections, lazy collections and everywhere the Selectable API is implemented.
This allows you to get rid of dozens of special methods you wrote for your repositories (like findOneBySomethingWithParticularRule), and instead focus on writing your own criteria classes, each representing one of these particular filters.
This is an example using the Expr() Class - I needed this too some days ago and it took me some time to find out what is the exact syntax and way of usage:
/**
* fetches Products that are more expansive than the given price
*
* #param int $price
* #return array
*/
public function findProductsExpensiveThan($price)
{
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder();
$q = $qb->select(array('p'))
->from('YourProductBundle:Product', 'p')
->where(
$qb->expr()->gt('p.price', $price)
)
->orderBy('p.price', 'DESC')
->getQuery();
return $q->getResult();
}
You have to use either DQL or the QueryBuilder. E.g. in your Purchase-EntityRepository you could do something like this:
$q = $this->createQueryBuilder('p')
->where('p.prize > :purchasePrize')
->setParameter('purchasePrize', 200)
->getQuery();
$q->getResult();
For even more complex scenarios take a look at the Expr() class.
$criteria = new \Doctrine\Common\Collections\Criteria();
$criteria->where($criteria->expr()->gt('id', 'id'))
->setMaxResults(1)
->orderBy(array("id" => $criteria::DESC));
$results = $articlesRepo->matching($criteria);
The Symfony documentation now explicitly shows how to do this:
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT p
FROM AppBundle:Product p
WHERE p.price > :price
ORDER BY p.price ASC'
)->setParameter('price', '19.99');
$products = $query->getResult();
From http://symfony.com/doc/2.8/book/doctrine.html#querying-for-objects-with-dql
I like to use such static methods:
$result = $purchases_repository->matching(
Criteria::create()->where(
Criteria::expr()->gt('prize', 200)
)
);
Of course, you can push logic when it is 1 condition, but when you have more conditions it is better to divide it into fragments, configure and pass it to the method:
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->where($expr->gt('prize', 200));
$criteria->orderBy(['prize' => Criteria::DESC]);
$result = $purchases_repository->matching($criteria);
Copying the findBy query and modifying it to return your expected result is a good approach.

How to fetch class instead of array in Doctrine 2

I am able to fetch my data from database by using this structure:
$user = $this->getDoctrine()
->getRepository('AcmeDemoBundle:Emails')
->find(8081);
When I do that, I am able to get my data like this:
$user->getColumnNameHere();
Basically I am able to use Entity Class.
But if I want to use QueryBuilder instead of find I am only getting associative arrays.
$product->createQueryBuilder('p')
->setMaxResults(1)
->where('p.idx = :idx')
->select('p.columnNameHere')
->setParameter('idx', 8081)
->orderBy('p.idx', 'DESC')
->getQuery();
$product = $query->getResult();
$product returnds as array. Is it possible to fetch it withj Entity Managaer Class? If yes, how?
I digg the documentation but it seems not possible or not exist in the doc or I'm just blind :)
Yes you can, usually using:
$repository
->createQueryBuilder('p')
->getQuery()
->execute()
;
This should return you an array of entities.
If you want to get a single entity result, use either getSingleResult or getOneOrNullResult:
$repository
->createQueryBuilder('p')
->getQuery()
->getOneOrNullResult()
;
Warning: These method can potentially throw NonUniqueResultException.
Edit: Ok, so the question was about partial objects: http://docs.doctrine-project.org/en/latest/reference/partial-objects.html
you can get an object instead of array by using "Partial Objects".
here is a tested example with DoctrineORM 2.2.2:
// create query builder
// $em is the EntityManager
$qb = $em->createQueryBuilder();
// specify the fields to fetch (unselected fields will have a null value)
$qb->select ('partial p.{id,pubDate,title,summary}')
->from ('Project\Entity\Post', 'p')
->where ('p.isActive = 1')
->orderBy ('p.pubDate', 'desc');
$q = $qb->getQuery();
$result = $q->getResult();
var_dump($result); // => object
If you wish to return an object from your original query:
$product->createQueryBuilder('p')
->setMaxResults(1)
->where('p.idx = :idx')
->select('p.columnNameHere')
->setParameter('idx', 8081)
->orderBy('p.idx', 'DESC')
->getQuery();
$product = $query->getResult();
Remove this line
->select('p.columnNameHere')
As soon as you use select, it will return an array...
getResult() method returns a collection (an array) of entities. Use getSingleResult() if you're going to fetch only one object.
EDIT:
Oh, I just noticed that you want to fetch a single field of a single object. Use getSingleScalarResult() as #Florian suggests.

Categories