Get all entities ordered with Doctrine query builder - php

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

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

Symfony2 - Searching for objects by user input

I'm trying to search for objects based on words the user types in, but the search results always come up blank. I know the query is right because if I hard-code in a value for $botanicalname, it works. Also, I know the URL is getting the data because here's the URL when I search for "Abies concolor":
"http://localhost:8000/searchresults?appbundle_shrubs[botanicalname]=Abies+concolor&appbundle_shrubs[commonname]=&appbundle_shrubs[phpreference]=&appbundle_shrubs[save]=&appbundle_shrubs[token]=SkM70kmkbx-50P-K5d_FUOnxhaZ4rsfrCnu-nb5WdQ"
I've also tried the post method ("$botanicalname = $request->request->get('botanicalname')").
Here's my controller:
/**
* Lists all search results.
*
* #Route("/searchresults", name="shrubs_search_results")
* #Method({"GET", "POST"})
*/
public function SearchResultsAction(Request $request)
{
$botanicalname = $request->query->get('botanicalname');
$repository = $this->getDoctrine()->getRepository('AppBundle:Shrubs');
$query = $repository->createQueryBuilder('p')
->where('p.botanicalname = :botanicalname')
->setParameter('botanicalname', '%'.$botanicalname.'%')
->orderBy('p.commonname', 'ASC')
->getQuery();
$shrubs = $query->getResult();
return $this->render('shrubs/searchresults.html.twig', array(
'shrubs' => $shrubs,
));
}
May be you need to convert your query like below:
$query = $repository->createQueryBuilder('p');
$shrubs = $query->where($query->expr()->like('p.botanicalname',':botanicalname'))
->setParameter('botanicalname', '%'.$botanicalname.'%')
->orderBy('p.commonname', 'ASC')
->getQuery()
->getResult();
The problem was with my html.twig page. It doesn't work with twig syntax, {{form_widget(form.botanicalname)}}
It only works with standard HTML <input type="text" name="botanicalname">

Symfony Order entities by field OneToMany

Who knows how to solved this simple question?
I have entity project with field likedUsers and in twig count up this field but I want order projects by this count up (DESC) - first who have more likedUsers. How to do it? In query builder or in twig create filter?Help with doctrine I know count
"likes_user" => count($this->getLikedUsers()->getValues())
how to sort my all projects from this field?
or how its solved with query builder?
something like that, but this is not work:
public function getProjects()
{
$qb = $this->getEntityManager()->createQueryBuilder('d');
$qb
->select('d')
->from('AppBundle:Project', 'd')
->where('d.confirm = :identifier')
->setParameter('identifier', 'approved')
->orderBy('COUNT(d.likedUsers)', 'DESC')
->getQuery()
->getResult()
;
$query = $qb->getQuery();
$results = $query->getResult();
return $results;
}
entity:
/**
* Project
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\ProjectRepository")
*/
class Project implements \JsonSerializable
{
/**
* #var Collection
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\User", mappedBy="likedProjects")
*/
private $likedUsers;
{% for project in projects %}
<div>LIked: <span>{{ project.likedUsers|length|number_format(0, '.', ' ') }}</span></div>
{% endfor %}
I think maybe like that:
{% for project in projects.likedUsers|length|sort %}
but not effect
maybe who knows? How array projects sort by count of field LikedUser. I don’t know how do this. Query builder or twig extension or usort..
IMHO, this seems like a job for PHP instead of Doctrine. Not sure if t could be achieved by Doctrine and, if possible, what would be an impact.
One way to do this is usort().
$projects = ...;
usort($projects, function($p1, $p2){
// Both $p1 and $p2 are instance of Project
// Assuming that `getLikedUsers()` return Doctrine `Collection`...
return count($p1->getLikedUsers()) > count($p2->getLikedUsers());
});
usort takes an array and in each pass offers two items (two projects in your case) for you to decide which one is "greater". In your case, the project with more likes is definitely "greater", right?
Hope this helps...
I solved with query builder. And I add only project who have like user - user live in some city no all city
public function getProject()
{
$qb = $this->getEntityManager()->createQueryBuilder('d');
$qb
->select('d')
->from('AppBundle:Project', 'd')
->addSelect('COUNT(m.id) as nMethods')
->join('d.likedUsers', 'm')
->join('m.location', 'l')
->where('l.city = :identifier')
->setParameter('identifier', 'someCity')
->groupBy('d.id')
->orderBy("nMethods", 'DESC')
->getQuery()
->getResult()
;
$query = $qb->getQuery();
$results = $query->getResult();
return $results;
}

Order attribute of an object in Symfony

I would like to reorder the attribute (COMMENTS) of my object (instance of ARTICLE) after I retrieve it from the DBB. Is this possible?
My object is ARTICLE and it is linked to COMMENTS (which is defined as a collection in entity article)
I know I can order through the repository but the order of my comments depend on many conditions, some not available through the DB.
Condition exemple:
I want at the top the comment whose attribute show_first are set to true whatever their score, and then the other comments ordered depending of their score.
You could add a hidden field to you query that sorting things in the order that you wanted so that you don't need to process the complete ArrayCollection to sort.
public function findByArticleInOrderOfState()
{
return $this->createQueryBuilder('c')
->select('c')
->addSelect('
CASE
WHEN c.state = :state_new THEN 1
WHEN c.state = :state_viewed THEN 2
WHEN c.state = :state_deleted THEN 3
ELSE 4
END AS HIDDEN order_by
')
->setParameter('state_new', 'new')
->setParameter('state_viewed', 'viewed')
->setParameter('state_deleted', 'deleted')
->orderBy('order_by', 'ASC')
->addOrderBy('c.createdAt', 'ASC')
->getQuery()
->getResults();
}
This would create a hidden field order_by and set that depending on the current state of that object, then it would order by that hidden field and then createdAt.
It doesn't really make sense to order comments like that but it does show how you could do it. With a little more info on the actual use case I would (hopefully) be able to make work a bit closer to your specific needs.
Update
In your case when you have show_first == 'yes'|'no' you could do the following..
public function findByArticleInOrderOfState()
{
return $this->createQueryBuilder('c')
->select('c')
->addSelect('
CASE
WHEN c.show_first = :show_first THEN 1
ELSE 2
END AS HIDDEN order_by
')
->setParameter('show_first', 'yes')
->orderBy('order_by', 'ASC')
->addOrderBy('c.createdAt', 'ASC')
->getQuery()
->getResults();
}
Set the getter of comments (getComments()) in your Article entity to get the comments in the order you want.
public function getComments(){
$iterator = $comments->getIterator();
$iterator->uasort(function ($a, $b) {
// change getProperty() with the field you want to order on
return ($a->getProperty() < $b->getProperty()) ? -1 : 1;
});
$comments= new ArrayCollection(iterator_to_array($iterator));
return $comments;
}
For more Infos visit this post "usort" a Doctrine\Common\Collections\ArrayCollection?
For simple ordering of associations, you can use Doctrine annotations.
/**
* #ORM\OneToMany(targetEntity="Comment", mappedBy="article")
* #ORM\OrderBy({"show_first" = "ASC", "score" = "DESC"})
*/
private $comments;
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/ordered-associations.html
The following possible within an entity object
public function getCommentsActiveLast3()
{
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('status', Comment::STATUS_PUBLISHED));
$criteria->setMaxResults(3);
if ($this->comments) {
return $this->comments->matching($criteria);
}
}

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