How to order results using EntityManager from Controller in Symfony2 - php

I have this code:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$entities = $em
->getRepository('BreedrGeckoBundle:Weight')
->findBy(array('user' => $user), array());
return array(
'entities' => $entities,
);
}
Which is fine, gets all the weights in the database for the current user.
But how can I order the results so that all the weight entries for the same gecko id are together?
My table structure is as follows:

You need to query for your objects using Doctrine's QueryBuilder.
Something like this:
$repository = $this->getDoctrine()
->getRepository('BreedrGeckoBundle:Weight');
$query = $repository->createQueryBuilder('w')
->where('w.user = :user')
->orderBy('w.geckoId ASC')
->getQuery();
$query->setParameter(':user', $user);
$entities = $query->getResult();
If you want additional ordering, you can do something like:
->orderBy('w.geckoId ASC, w.weight ASC, w.id ASC')

You should create your own repository and use the addGroupBy function on the querybuilder. Example:
class WeightRepository extends EntityRepository
{
public function getGroupedByGeckoId(User $user)
{
$qb = $this->createQueryBuilder('weight');
$qb->select('whateverYouWant');
$qb->andWhere('weight.user = :user');
$qb->setParameter('user', $user);
$qb->addGroupBy('weight.geckoId');
return $qb->getQuery()->getResult();
}
}

You can also order by using the repository object itself like so:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$entities = $em
->getRepository('BreedrGeckoBundle:Weight')
->findBy(array('user' => $user), array('geckoId' => 'ASC'));
return array(
'entities' => $entities,
);
}

Related

Findby DateTime the recent uploaded articles Symfony

Hello im triying to get on my dashboard only the most recent articles
but isnt working i did this function
public function PostsRecientes(){
return $this->getEntityManager()
->createQuery('
SELECT post
FROM App:Posts post
WHERE post.fechaPublicacion > CURRENT_DATE()')
->getResult();
}
and this in my dashboardcontroller
/**
* #Route("/", name="dashboard")
*/
public function index(PaginatorInterface $paginator, Request $request): Response
{
$em = $this->getDoctrine()->getManager();
$posts = $em->getRepository(Posts::class)->PostsRecientes();
return $this->render('dashboard/index.html.twig', [
'posts' => $posts
]);
}
but when i do a var dump i doesnt bring any post.
You can use setFirstResult and setMaxResults, for example:
public function PostsRecientes()
{
$qb = $this->createQueryBuilder('p')
->orderBy('p.id', 'DESC')
->setFirstResult(0)
->setMaxResults(6);
return $qb->getQuery()->getResult();
}

Multiple criteria search Query builder [symfony2]

I have created a search form,i'm trying to fetch the following data from the database (airport,airport1,departuredate,price),i can only get [airport] but not the other entity.
This is my controller:
public function searchtabflightResultAction(Request $request)
{
$form = $this->createForm(new SearchflightType());
if ($this->get('request')->getMethod() == 'POST')
{
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('FLYBookingsBundle:Post')->searchflight($form['airport']->getData());
} else {
throw $this->createNotFoundException('The page you were looking for doesn\'t exist.');
}
return $this->render('FLYBookingsBundle:Post:searchtabflightResult.html.twig', array('entities' => $entities));
}
PostRepository.php
public function searchflight($entity)
{
$qb = $this->createQueryBuilder('u')
->select('u')
->where('u.airport like :entity')
->andWhere('u.airport1 like :entity')
->orderBy('u.id')
->setParameter('entity', '%'.$entity.'%');
return $qb->getQuery()->getResult();
}
Try something like :
In your controller:
$entities = $em->getRepository('FLYBookingsBundle:Post')->searchflight($form);
In your repo:
public function searchflight(FormInterface $form)
{
$qb = $this->createQueryBuilder('u');
if ($form->has('airport')) {
$qb->andWhere(
$qb->expr()->like('u.airport', ':airport')
)
->setParameter('airport', '%'. $form->get('airport')->getData().'%')
}
// ... complete like this with the other params

ZF2 How to add model class of sub items to main model

I've got a simple index action:
$reminders = $this->reminderTable->fetchAll();
foreach ($reminders as $reminder) {
$reminder->receivers = $this->reminderTable->getReceivers($reminder->id);
}
return new ViewModel(array(
'reminders' => $reminders
));
The get receivers (sub items of the main table) looks like this:
public function getReceivers($id)
{
$adapter = $this->tableGateway->getAdapter();
$receiversTable = new TableGateway('ga_reminders_receivers', $adapter);
$resultSet = $receiversTable->select(function (Select $select) use ($id) {
$select->join('ga_users', 'ga_reminders_receivers.receiver_uid = ga_users.uid', array('uid', 'firstname', 'lastname', 'email', 'telephone'), 'left');
$select->where('ga_reminders_receivers.rid = ' . $id);
});
return $resultSet;
}
This gives me the fancy error
This result is a forward only result set, calling rewind() after
moving forward is not supported.
So, I guess my question is this: When I do a fetch of a resultset it fils in the model class thanks to exchangearray(). But how am I suppose to fill a model property with a list of sub models?
In this case the model is Reminder:
class Reminder { // from the reminders table
public function exchangeArray($data)
{
$this->id = (!empty($data['rid'])) ? str_pad($data['rid'], 5, '0', STR_PAD_LEFT) : null;
$this->label = (!empty($data['label'])) ? $data['label'] : null;
// etc.
$this->receivers = array(
new Receiver(1),
new Receiver(2),
// list of objects from the reminders_receivers table
)
}
Second question: Is the separate getReceivers() method needed? Maybe it can be integrated in 1 query. As long as the model classes Reminder and Receiver are used it is OK.
In this cases you have to use buffer.
public function getReceivers($id)
{
$adapter = $this->tableGateway->getAdapter();
$receiversTable = new TableGateway('ga_reminders_receivers', $adapter);
$resultSet = $receiversTable->select(function (Select $select) use ($id) {
$select->join('ga_users', 'ga_reminders_receivers.receiver_uid = ga_users.uid', array('uid', 'firstname', 'lastname', 'email', 'telephone'), 'left');
$select->where('ga_reminders_receivers.rid = ' . $id);
});
$resultSet->buffer();
return $resultSet;
}

How to use KNPPaginatorBundle to paginate results using Doctrine Repository?

I'm working on a Symfony2 project and I decided to use KNPPaginatorBundle to build an easy pagination system. So I created a Product entity and I want to add the paginator to indexAction action (generated by CRUD command).
// Retrieving products.
$em = $this->getDoctrine()->getManager();
//$entities = $em->getRepository('LiveDataShopBundle:Product')->findAll();
$dql = "SELECT a FROM LiveDataShopBundle:Product a";
$entities = $em->createQuery($dql);
// Creating pagnination
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$entities,
$this->get('request')->query->get('page', 1),
20
);
It works fine but I want to use the Product's repository instead of creating the query directly in the controller. How can I do that ?
In fact, directly add the collection of results to the paginate object is just too slow because its load all products then paginate the ArrayCollection.
Thanks in advance.
K4
I suggest using QueryBuilder in your ProductRepository and then passing that to the paginator:
ProductRepository extends EntityRepository
{
// This will return a QueryBuilder instance
public function findAll()
{
return $this->createQueryBuilder("p");
}
}
In the controller:
$products = $productRepository->findAll();
// Creating pagnination
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$products,
$this->get('request')->query->get('page', 1),
20
);
I think in some cases we could use Closure and pass to it a QueryBuilder object.
In your ProductRepository you could do something like this:
ProductRepository extends EntityRepository
{
public function findAllPublished(callable $func = null)
{
$qb = $this->createQueryBuilder('p');
$qb->where('p.published = 1');
if (is_callable($func)) {
return $func($qb);
}
return $qb->getQuery()->getResult();
}
}
and then in ProductController:
public function indexAction(Request $request)
{
$em = $this->get('doctrine.orm.entity_manager');
$paginator = $this->get('knp_paginator');
$func = function (QueryBuilder $qb) use ($paginator, $request) {
return $paginator->paginate($qb, $request->query->getInt('page', 1), 10);
};
$pagination = $em->getRepository('AppBundle:Report')->findAllPublished($func);
// ...
}
I think it more flexible and you could use findAllPublished method to get both paginated or NOT paginated results if you need.
Also keep in mind that callable type hint work in PHP >=5.4! Please, check docs for more info.
In our project we want to avoid using Doctrine queries in controllers. We have also separate layers. Controllers must not access the database. So I included pagination in the Repository.
Here my code in controller:
public function indexAction(Request $request)
{
$userRepository = $this->get('user_repository');
$page = intval($request->query->get('page', 1));
$pages = 0;
$users = $userRepository->findAllPaginated($pages, $page - 1, 10);
return $this->render('User:index.html.twig', array(
'users' => $users,
'page' => $page,
'pages' => $pages,
));
}
And here is the important code in my repository:
use Doctrine\ORM\Tools\Pagination\Paginator;
class UserRepository extends EntityRepository
{
/**
* #return User[]
*/
public function findAllPaginated(&$pages, $startPage = 0, $resultsPerPage = 5)
{
$dql = 'SELECT u FROM CoreBundle:User u';
$query = $this->getEntityManager()->createQuery($dql)
->setFirstResult($startPage * $resultsPerPage)
->setMaxResults($resultsPerPage);
$paginator = new Paginator($query);
$count = $paginator->count();
$pages = floor($count/$resultsPerPage);
return $paginator; // on $paginator you can use "foreach", so we can say return value is an array of User
}
}

Symfony2, Doctrine2, findBy() order not working

I created a repository for my Articles entity and I'm trying to get all values ordered by ID DESC. But, I'll get everytime values ordered by id ASC. Here is my ArticleRepository.php:
<?php
namespace Acme\BlogBundle\Entity;
use Doctrine\ORM\EntityRepository;
class ArticleRepository extends EntityRepository
{
public function findAll()
{
return $this->findBy(array(), array('id' => 'DESC'));
}
public function findOneBySlug($slug)
{
$query = $this->getEntityManager()
->createQuery('
SELECT p FROM AcmePagesBundle:Article a
WHERE a.slug = :slug
')
->setParameter('slug', $slug);
try {
return $query->getSingleResult();
} catch (\Doctrine\ORM\NoResultException $e) {
return false;
}
}
}
Any ideas?
The Syntax looks good. This should provide a set of well ordered articles.
First, make sure the #Entity annotation is set with the right Repository class within the Article Entity,
/**
* #ORM\Entity(repositoryClass="...");
*/
class Article
{
// ...
}
Also, if you want to use native helpers, you've just to call findBy from the ArticleRepository within your controller,
$articles = $this->get('doctrine')
->getRepository('YourBundle:Article')
->findBy(array(), array('id' => 'DESC'));
You don't need to create a query in ArticleRepostory.php for that
In your controller you can just do:
$entities = $em->getRepository('YourBundle:Article')->findBy(array(), array( 'id' => 'DESC' ));
->findBy(array(), array( 'id' => 'DESC' )); // Order Works
->findAll(array(), array( 'id' => 'DESC' )); // Order doesn't work
This should be work:
public function findAll()
{
$em = $this->getEntityManager();
$query = $em->createQuery('
SELECT *
FROM AcmePagesBundle:Article a
ORDER BY a.id DESC
');
return $query->getResult();
}
I would tend to do this in my repository (to allow for using the same select DQL in different methods in the repository - especially when you have lots of fetch-joins to include):
class FooRepository extends EntityRepository
{
/**
* Get the DQL to select Foos with all joins
*
* #return string
*/
public function getSelectDql()
{
$dql = '
SELECT f
FROM Entity:Foo f
';
return $dql;
}
/**
* Fetch all foos, ordered
*
* #return array
*/
public function fetchAllOrdered()
{
$dql = sprintf(
'%s %s',
$this->getSelectDql(),
'ORDER BY f.id DESC'
);
return $this->getEntityManager()
->createQuery($dql)
->getResult();
}
}
This should make your repository quite flexible, allow different ordering in different methods (if you need to order them differently) and keep all DB-related code out of your controller.
Symfony 3.3 find by order working example.
From your controller:
public function indexAction(){
$entityManager = $this->getDoctrine()->getManager();
$categoryRepository = $entityManager->getRepository(ProductCategory::class);
$items = $categoryRepository->findBy(array(), array('id' => 'DESC'));
....
}

Categories