How can I use 'order by rand' in Symfony doctrine? - symfony

I am trying to use the possibilities of Doctrine in Symfony. How can I do an 'orderBy rand' following this logic:
findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
Here's what I have so far (but it doesn't work):
$this->entityManager->getRepository(people::class)->findBy([ 'visible' => true ], [ 'name' => 'rand()' ], 8);
I already have the extension 'beberlei/doctrineextensions'
thank you in advance for your help

You cannot use findBy with a custom dql method since it only expect an array with key (property name) and value (ASC or DESC).
So you have to create a custom method in your PeopleRepository to do it.
For example:
function findRandom($isVisible = true)
{
return $this->createQueryBuilder('p')
->andWhere('p.visible = :visible')
->setParameter('visible', $isVisible)
->orderBy('RAND()')
->getQuery()
->getResult()
;
}

Related

Symfony: Get parent object within child from formevent

I have a form that contains 3 fields (date, typeEvent, seller) where Seller is a choiceType that depends on date and typeEvent, and to do that i followed the symfony documentation for dynamics forms.
but the exemple in the doc its about a field that depends on only one other field.
what i did so far :
$formModifier = function (FormInterface $form,DateTime $date = null, TypeEvent $type = null) {
if (($date === null) || ($type === null)) {$sellers = [];return;}
$repo = $this->entityManager->getRepository(User::class);
$start = $date->format("Y-m-d H:i:s");
$end = new DateTime($date->format("Y-m-d H:i:s"));
$end = date_add($end,date_interval_create_from_date_string("60 minutes"))->format('Y-m-d H:i:s');
$organisation = $this->security->getUser()->getOrganisation();
$sellers = $repo->findSellers($organisation,$start,$end);
$form->add('seller', EntityType::class, [
'class' => User::class,
'placeholder' => '',
'choices' => $sellers,
'choice_label' => 'pseudo',
'attr' => ['class'=>'seller-select'],
'required'=>false,
'expanded' =>false,
]);
};
$builder->get('start')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$start = $event->getForm()->getData();
$type = $event->getForm()->getParent()->getData()->getTypeEvent();
$formModifier($event->getForm()->getParent(), $start, $type);
}
);
$builder->get('typeEvent')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
$type = $event->getForm()->getData();
$start = $event->getForm()->getParent()->getData()->getStart();
$formModifier($event->getForm()->getParent(), $start, $type);
}
);
the problem here is that, for exemple when i try to add a listener to 'start' field inside of it, i don't have access to the other fields, the typeEvent field specifically, i tried $event->getForm()->getParent()->getData()->getTypeEvent() but it returns null, and that's $event->getForm()
dumped.
As you can see the $event->getForm()->getParent()->getData() it's like a new Event() with all attribute on null.
So my question is: There is any way to get the typeEvent there ? or should i proceed differently?
Thank you.
I am not completely sure if this is what you want, but you should take a look at this answer:
https://stackoverflow.com/a/25890150/17089665
$form->all(); <- Will get you all fields
$child->getName(); <- Will get you the name of every child, if you iterate the $form variable.

Gedmo and parent select in Symfony2

I've implemented Gedmo nested trees in my Symfony2 project and I'm trying to build a parent select. I read the doc https://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/tree.md
but it's very short note about this kind of issues.
I can't get an array of nodes with a identation based on node levels.
$repo = $em->getRepository('SymdruMenuBundle:MenuLink');
$options = array(
'decorate' => true,
'nodeDecorator' => function($node) {
return str_repeat(' ', $node['lvl']).'-'.$node['title'].'</a>';
},
'html' => false,
);
$htmlTree = $repo->childrenHierarchy(
null, /* starting from root nodes */
false, /* true: load all children, false: only direct */
$options
);
var_dump($htmlTree);
$form->add('parent', 'choice', array('choices' => $htmlTree));
It gives me a string instead of an array.
I can do it like this
$em = $this->getDoctrine()->getManager();
$links = $em->getRepository('SymdruMenuBundle:MenuLink')->findAll();
$choices = array();
foreach ($links as $link) {
$choices[$link->getId()] = str_repeat('--', $link->getLvl()).$link->getTitle();
}
but is this the best way?
The second issue here is how to get a parent object when I save the children to the database?

Symfony form query_buider and entity repository

I'm trying to create a form with data in collection type depending on the user being logged. I'm following this chapter of the Symfony cookbook.
Everything works fine when the query_builder option is a closure where I get my data from DQL. As the data need to be fetched from different location in code, I would prefer to define the query in the Repository class.
Here is the function in my repository :
public function findOwnedBy($user) {
$query = $this->getEntityManager()->createQuery("SELECT l FROM MyBundle:Article a JOIN a.owndBy u WHERE u.id = :userId");
$query->setParameters(array("userId"=>$user->getId()));
return $query->getResult();
}
This function works when called in a Controller and return an array of Article. Here is a snippet of the symfony doc :
$formOptions = array(
'class' => 'Acme\DemoBundle\Entity\User',
'multiple' => false,
'expanded' => false,
'property' => 'fullName',
'query_builder' => function(EntityRepository $er) use ($user) {
// build a custom query, or call a method on your repository (even better!)
},
);
When I put a call to my Repository function in the query_builder, I get an error : Expected argument of type "Doctrine\ORM\QueryBuilder", "array" given, which I can understand because my Repository returns an array of Entity, not a QueryBuilder.
I don't want to duplicate code and create a new QueryBuilder in the Form. What is the best practice to use the query from the Repository ? I was thinking of having two function in the repository, one returning an array and the other returning the QueryBuilder, but the comment in Symfony doc "or call a method on your repository (even better!)" let me think there's better way for this case.
It should be easy. Do the following:
public function queryOwnedBy($user) {
$query = $this->createQueryBuilder('a')
->from('MyBundle:Article', 'a')
->innerJoin('a.owndBy', 'u')
->where('u.id = :id')
->setParameter('id', $user->getId());
return $query;
}
public function findOwnedBy($user) {
return $this->queryOwnedBy($user)
->getQuery()
->getResult();
}
Then in the form builder:
$formOptions = array(
'class' => 'Acme\DemoBundle\Entity\User',
'multiple' => false,
'expanded' => false,
'property' => 'fullName',
'query_builder' => function(EntityRepository $er) use ($user) {
return $er->queryOwnedBy($user);
},
);
EDIT
Thank's for ncatnow and unagi I've changed the previous functions to return the querybuilder
I just did a little fix of saamorim answer. The working code would be something like this:
public function queryOwnedBy($user) {
$query = $this->createQueryBuilder("u")
->where('u.id = :id')
->setParameter('id', $user->getId());
return $query;
}
public function findOwnedBy($user) {
return $this->queryOwnedBy($user)
->getQuery()
->getResult();
}

How to use Repository custom functions in a FormType

The problem I'm facing is I have to create a selectbox in a form that holds all the parent entities (Category Entity). Now i managed to do this with:
$builder->add('parent', 'entity', array(
'class' => 'KprCentarZdravljaBundle:Category',
'query_builder' => function($repository) use ($param, $catID) {
return $repository->createQueryBuilder('p')
->where('p.id != :id AND p.parent = :parent')
->setParameters(array('id' => $param, 'parent' => $catID));},
'property' => 'name',
'required' => false,
'attr' => array('data-placeholder' => '--Izaberite Opciju--'),
));
As u can see i pass 2 arguments first is the current category.id(a category cant be its own parent) and a second which is a parent id, because i want all the children from that parent. This works nice but it doesn't give me the parents children's children.
I created a CategoryRepository with a recursive function that returns all the children:
<?php
namespace Kpr\CentarZdravljaBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Kpr\CentarZdravljaBundle\Entity\Category;
class CategoryRepository extends EntityRepository
{
public function findByParenting($parent)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->add('select', 'cat')
->add('from', 'KprCentarZdravljaBundle:Category cat')
->add('where', 'cat.parent = :parent')
->setParameter('parent', $parent);
// $qb instanceof QueryBuilder
$query = $qb->getQuery();
$results = $query->getResult();
foreach($results as $result){
if($result->getParent()){
$newResult = $this->findByParenting($result->getId());
$results = array_merge($results, $newResult);
}
}
return $results;
}
}
How can I use the findByParenting($parent) function in a entity field?
I posted the answer: Symfony2 choice field not working. Thanks redbirdo.
You are having this error because you have to return the QueryBuilder object on your findByParenting($parent) function
public function findByAllocation($alloc)
{
return $qb = $this->createQueryBuilder('r')
->select('r')
->where('r.showRangeStart < :alloc', 'r.showRangeStop >= :alloc')
->setParameter('alloc', $alloc)
;
}

Use of entity_extract_ids($entity_type, $entity)

I am trying to use entity_extract_ids($entity_type, $entity) where:
$entity_type = The entity type; e.g. 'node' or 'user'.
$entity = The entity from which to extract values.
I have never used this function and don't understand what the second parameter (i.e. $entity) is supposed to be.
I would love to see an example code with this function being used. Thank you.
This function return array($id, $vid, $bundle);
Example:
// Define $entity_type.
// Could be 'node', 'user', 'file', 'taxonomy_term' etc.
$entity_type = 'node';
// Get $entity object, in our case $node with nid = 1
$entity = node_load(1);
// print_r will give us something like:
// Array
// (
// [0] => 1
// [1] => 4
// [2] => page
// )
// Where [0] is nid, [1] is vid and [2] is bundle name of a node with nid = 1
print_r(entity_extract_ids($entity_type, $entity));
It's better to use function like that:
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

Resources