I'm using symfony 2.2.3 and sonata admin in dev-master.
I would like a custom field to show users from a specific group.
I've not found how to make the relation with Sonata User entity and Sonata Group entity.
The doctrine schema create 3 tables : fos_user_user, fos_user_group and the relation table fos_user_user_group.
I've a form with a field like that in my Admin class :
->add('coach', 'entity', array(
'class' => 'ApplicationSonataUserBundle:User',
'empty_value' => 'Choisissez un coach',
'property' => 'username',
'query_builder' => function(\Application\Sonata\UserBundle\Entity\UserRepository $er) {
return $er->getCoachs();
},
))
And my function getCoachs() in UserRepository:
public function getCoachs()
{
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder(array('u', 'g'))
->select('u.username, g.id')
->from('ApplicationSonataUserBundle:User', 'u')
->innerJoin('ApplicationSonataUserBundle:Group', 'g', 'WITH','g.id = u.group_id')
->where('g.id = :id')
->setParameter('id', 1);
return $qb;
}
I know that the query doesn't work because the innerJoin isn't correct.
My user entity and group entity just extends BaseUser and GroupUser with an id.
Someone know the right query ?
Thank you.
EDIT :
Ok i've found the solution for the query :
public function getCoachs()
{
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder('u')
->select('u.username')
->from('ApplicationSonataUserBundle:User', 'u')
->innerJoin('u.groups', 'g')
->where('g = :id')
->setParameter('id', 1);
return $qb;
}
However, i've this error :
Expected argument of type "object or array", "string" given
I don't understand because I return my function getCoachs() which return a query builder...
No idea ?
Ok I've found the solution !
My query is :
public function getCoachs()
{
$em = $this->getEntityManager();
$qb = $em->createQueryBuilder('u')
->select('u') // and not u.username
->from('ApplicationSonataUserBundle:User', 'u')
->innerJoin('u.groups', 'g')
->where('g = :id')
->setParameter('id', 1);
return $qb;
}
In fact, I returned values of a specific column (username) but you have to return the object User.
Related
I'm coding in Symfony a search bar working with a query builder for an entity named "Structure" which is related to an entity "Partenaire" (OneToMany), it's working great but the problem is that it shows all the structures and I need to display only the structures related to the Partenaire. If someone can help me to solve this issue, thank you.
PartenaireController.php:
#[Route('/{id}', name: 'app_partenaire_show', methods: ['GET', 'POST'])]
public function show(Partenaire $partenaire, EntityManagerInterface $entityManager, PartenaireRepository $partenaireRepository,Request $request, PartenairePermissionRepository $partenairePermissionRepository, StructureRepository $structureRepository): Response
{
$getEmail = $this->getUser()->getEmail();
$partenaireId = $entityManager->getRepository(Partenaire::class)->findOneBy([
'id' => $request->get('id')
]);
$search2 = $structureRepository->findOneBySomeField2(
$request->query->get('q')
);
return $this->render('partenaire/show.html.twig', [
'partenaire' => $partenaire,
'permission'=>$partenairePermissionRepository->findBy(
['partenaire' => $partenaireId],
),
'structures'=>$search2, // show all the structures
/* 'structures'=>$structureRepository->findBy( // show the structure linked to the partenaire but doesn't work with the search
['partenaire' => $partenaireId],
[],
),*/
'email'=>$getEmail,
]);
}
StructureRepository.php :
public function findOneBySomeField2(string $search2 = null): array
{
$queryBuilder = $this->createQueryBuilder('q')
->orderBy('q.id' , 'ASC');
if ($search2) {
$queryBuilder->andWhere('q.Adresse LIKE :search')
->setParameter('search', '%'.$search2.'%');
}
return $queryBuilder->getQuery()
->getResult()
;
}
as it's a One To Many relation, you should join the right table and add a where statement in your structure query like :
public function findByPartenaireWithFilter(Partenaire $partenaire, string $search2 = null): array
{
$queryBuilder = $this->createQueryBuilder('q')
->leftJoin('q.partenaire','p')
->where('p.partenaire.id = :partenaireId')
->setParameter('partenaireId', $partenaire->getId())
->orderBy('q.id' , 'ASC');
if (null !== $search2) {
$queryBuilder->andWhere('q.Adresse LIKE :search')
->setParameter('search', '%'.$search2.'%');
}
return $queryBuilder
->getQuery()
->getResult();
}
You need to limit your results to the desired Partenaire by adding a condition. You can achieve this by simply passing another argument to the repository function.
I've removed the commented code in the controller and the loading of the Partenaire entity, as it should be already loaded thanks to the magic of param converters.
#[Route('/{id}', name: 'app_partenaire_show', methods: ['GET', 'POST'])]
public function show(Partenaire $partenaire, EntityManagerInterface $entityManager, Request $request, PartenairePermissionRepository $partenairePermissionRepository, StructureRepository $structureRepository): Response
{
$getEmail = $this->getUser()->getEmail();
// The Partenaire should already be loaded
$result = $structureRepository->findByPartenaireWithFilter(
$partenaire,
$request->query->get('q')
);
return $this->render('partenaire/show.html.twig', [
'partenaire' => $partenaire,
'permission' => $partenairePermissionRepository->findBy(
['partenaire' => $partenaireId],
),
'structures' => $search2, // show all the structures
'email' => $getEmail,
]);
}
As for the repository, it's pretty straightforward: pass the loaded partenaire and add a where clause.
public function findByPartenaireWithFilter(Partenaire $partenaire, string $search2 = null): array
{
$queryBuilder = $this->createQueryBuilder('q')
->where('q.partenaire = :partenaire')
->setParameter('partenaire', $partenaire)
->orderBy('q.id' , 'ASC');
if (null !== $search2) {
$queryBuilder->andWhere('q.Adresse LIKE :search')
->setParameter('search', '%'.$search2.'%');
}
return $queryBuilder
->getQuery()
->getResult();
}
As for the permissions key in the controller, I think what you are trying to do, I'd recommend looking into security voters.
I have an one to one relation in my sonata admin bundle.
Person <-> Player.
If i go to my Person admin i can choose the player from the choice list.
If i go to another Person object the player (which is now already assigned) is shown again ... if i choose it, there occurs an error ...
The error is
Failed to update object: AppBundle\Entity\Person
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '18' for key 'UNIQ_9A5FDF45F6B75B26'
Can i change the behaviour that already assigned values do not appear in other objects?
I cant find a option for doing this in sonata admin
You can generate a custom choice list for every Person.
Add method to PlayerRepository:
class PlayerRepository extends EntityRepository
{
public function getNotAssociatedPlayers($person)
{
$qb = $this->createQueryBuilder('p')
->leftJoin('p.person', 'prsn')
->where('prsn.id is null');
if($person !== null)
{
$qb->orWhere('prsn.id = :person')
->setParameter('person', $person);
}
return $qb->getQuery()
->getResult();
}
}
And use it in PersonAdmin:
protected function configureFormFields(FormMapper $formMapper)
{
$person = ($this->getSubject()->getPlayer() !== null)
? $this->getSubject()->getId()
: null;
$em = $this->getConfigurationPool()->getContainer()->get('doctrine.orm.entity_manager');
$choices = $em->getRepository('YourBundle:Player')->getNotAssociatedPlayers($person);
$formMapper
->add('player', null, array(
'choices' => $choices,
));
Please, let me know if something went wrong with that.
EDIT:
Documented solution is a query_builder option for the field:
$formMapper
->add('player', null, array(
'query_builder' => function(EntityRepository $er)
{
$qb = $er->createQueryBuilder('p')
->leftJoin('p.person', 'prsn')
->where('prsn.id is null');
if($this->getSubject()->getPlayer() !== null)
{
$qb->orWhere('prsn.id = :person')
->setParameter('person', $this->getSubject()->getId());
}
return $qb;
}
));
I would need a little help. I'm trying to implement a search bar with symfony, this search bar in the database. What I can do but the problem is that I absolutely have to put the full name to find the person (s) corresponds to that name. Except that I would like to be able to retrieve all the people starting with the beginning of the name I entered. For example :
I type "dub" and I find: "Dubois", "Dubost", "Dubububu", ....
public function searchAction (Request $request)
{
$defaultData = array('search' => 'Type your search here');
$form = $this->createFormBuilder()
->add('search', TextType::class, array('label'=>'Surname ?','required'=>true))
->add('send', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$repository = $this
->getDoctrine()
->getManager()
->getRepository('PegasusWebBundle:Clients')
;
//$clients = $repository->findBySurname($form->get('search')->getData()); // Method 1
$clients = $repository->myFindname($form->get('search')->getData()); // Method 2 with Repository
return $this->render('PegasusWebBundle:Default:searchresult.html.twig',array(
'clients'=> $clients ));
}
else
return $this->render('PegasusWebBundle:Default:search.html.twig', array(
'form' => $form->createView(),
));
}
The repository for the method 2
`class ClientsRepository extends \Doctrine\ORM\EntityRepository
{
public function myFindname($name)
{
// Method 2
$qb = $this->createQueryBuilder('a');
$qb->where(
$qb->expr()->like('a.surname' ,':surname'))
->setParameter('surname', $name);
return $qb
->getQuery()
->getResult();
}
}`
Try adding the wildchar eg:
$query = $repo->createQueryBuilder('a')
->where('a.surname LIKE :surname')
->setParameter('surname', '%'.$name.'%')
->getQuery();
Try adding a SQL wildcard character (%) after the surname value.
Also See this as reference.
I'm using Sonata to make a backoffice and at configureFormFields, I want do a query to return some values. The query is well done and returns values when I use var_dump, but at the form I always get "Class does not exist". Can you help me?
Here is the code:
protected function configureFormFields(FormMapper $formMapper)
{
/* #var $queryBuilder \Doctrine\ORM\QueryBuilder */
$queryBuilder = $this->getModelManager()
->getEntityManager('EBCoreKernelBundle:Campaign\Campaign')
->createQueryBuilder();
$queryBuilder->select('cmp.id, cmp.name')
->from('EBCoreKernelBundle:Campaign\Campaign', 'cmp');
/* #var $templateList Template[] */
$templateList = $queryBuilder->getQuery()->execute();
var_dump($templateList);
$formMapper
->add('name','sonata_type_model', array('required' => true, 'query' => $queryBuilder));
}
$entity = new \Nnx\AbpBundle\Entity\Truc();
$query = $this->modelManager->getEntityManager($entity)->createQuery('SELECT t FROM Nnx\AbpBundle\Entity\Truc t ORDER BY t.lib ASC')->execute();
As documentation:
https://sonata-project.org/bundles/admin/master/doc/reference/form_types.html
query defaults to null. You can set this to a QueryBuilder instance in
order to define a custom query for retrieving the available options.
So, let's give it a query builder:
$queryBuilder = $this->getModelManager()
->getEntityManager(Category::class)
->createQueryBuilder('c')
->select('c')
->from('AppBundle:Category', 'c')
->orderBy('c.title', 'ASC')
;
$formMapper->add('toto', ModelType::class, array(
'query' => $queryBuilder
))
Hi
I've got the following query but it doesn't seem to work.
$q = $this->em->createQueryBuilder()
->update('models\User', 'u')
->set('u.username', $username)
->set('u.email', $email)
->where('u.id = ?1')
->setParameter(1, $editId)
->getQuery();
$p = $q->execute();
This returns the following error message:
Fatal error: Uncaught exception
'Doctrine\ORM\Query\QueryException'
with message '[Semantical Error] line
0, col 38 near 'testusername WHERE':
Error: 'testusername' is not defined.'
in ...
I would be glad of any help
I think you need to use ->set() It's much safer to make all your values parameters:
$queryBuilder = $this->em->createQueryBuilder();
$query = $queryBuilder->update('models\User', 'u')
->set('u.username', ':userName')
->set('u.email', ':email')
->where('u.id = :editId')
->setParameter('userName', $userName)
->setParameter('email', $email)
->setParameter('editId', $editId)
->getQuery();
$result = $query->execute();
Let's say there is an administrator dashboard where users are listed with their id printed as a data attribute so it can be retrieved at some point via JavaScript.
An update could be executed this way …
class UserRepository extends \Doctrine\ORM\EntityRepository
{
public function updateUserStatus($userId, $newStatus)
{
return $this->createQueryBuilder('u')
->update()
->set('u.isActive', '?1')
->setParameter(1, $qb->expr()->literal($newStatus))
->where('u.id = ?2')
->setParameter(2, $qb->expr()->literal($userId))
->getQuery()
->getSingleScalarResult()
;
}
AJAX action handling:
# Post datas may be:
# handled with a specific custom formType — OR — retrieved from request object
$userId = (int)$request->request->get('userId');
$newStatus = (int)$request->request->get('newStatus');
$em = $this->getDoctrine()->getManager();
$r = $em->getRepository('NAMESPACE\User')
->updateUserStatus($userId, $newStatus);
if ( !empty($r) ){
# Row updated
}
Working example using Doctrine 2.5 (on top of Symfony3).
With a small change, it worked fine for me
$qb=$this->dm->createQueryBuilder('AppBundle:CSSDInstrument')
->update()
->field('status')->set($status)
->field('id')->equals($instrumentId)
->getQuery()
->execute();