symfony2 get field from controller without getting whole entities - symfony

I am having an issue. Am new to symfony2 and I am trying to get a field of a repository in my controller without getting all of it. I tried with the findAll() and it works 'except that am getting all the fields'.
Here is my controller:
<?php
namespace Extranet\RepportsBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UtilisateurController extends Controller
{
/**
* Retrieves utilisateurs name(called entite)
*
* #Route("/utilisateur", name="extranet_repports_utilisateur")
* #Template("ExtranetRepportsBundle:Utilisateur:index.html.twig")
*/
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
// $entity = $em->getRepository("ExtranetUtilisateurBundle:Utilisateur")->findAll(array());
$entity = $em->getRepository("ExtranetUtilisateurBundle:Utilisateur")
->createQueryBuilder(
'SELECT u.name FROM ExtranetUtilisateurBundle:Utilisateur u ORDER BY u.name ASC'
)
->getResult();
;
var_dump($entity);die();
return array('entity' => $entity);
}
}
// $em = $this->getDoctrine()->getManager();
// $query = $em->createQuery(
// 'SELECT p
// FROM AcmeStoreBundle:Product p
// WHERE p.price > :price
// ORDER BY p.price ASC'
// )->setParameter('price', '19.99');
// $products = $query->getResult();
I am trying to get only the username from the repository and the commented code below is the example from the symfony book
Thanks for your help

You can specify your properties in select() method of query builder which you want to select
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository("ExtranetUtilisateurBundle:Utilisateur");
$result= $entity->createQueryBuilder('u')
->select('u.name')
->orderBy('u.name')
->getQuery()
->getArrayResult();

Related

Empty array from query native builder symfony6

I'm new on symfony 6.1 and i would like to understand what wrong with my custom sql request.
I try many things but with no success can you help me ?
This is my Accueil Controller where i want to get back the sql result from my repository :
<?php
namespace App\Controller;
use App\Entity\Mission;
use App\Entity\Tag;
use App\Entity\User;
use App\Form\AddMissionFormType;
use App\Form\RegistrationFormType;
use App\Repository\MissionRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class AccueilProspectorController extends AbstractController
{
#[Route('/accueil/prospector', name: 'app_accueil_prospector')]
public function index(Request $request,ManagerRegistry $doctrine,Security $security): Response
{
$mission = new Mission();
//Récupération de toutes les missions.
$allmission = $doctrine->getManager()->getRepository(Mission::class)->selectmissionswithtags();
//Création du formulaire pour ajouter une mission
$mission->setIduser($security->getUser());
$form = $this->createForm(AddMissionFormType::class, $mission)->handleRequest($request);
if($form->isSubmitted() && $form->isValid()){
$entityManager = $doctrine->getManager();
$entityManager->persist($mission);
$entityManager->flush();
return $this->redirectToRoute('app_accueil_prospector');
}
return $this->render('accueil_prospector/index.html.twig', [
'controller_name' => 'AccueilProspectorController',
'addmissionForm' => $form->createView(),
'missionsvalues' => $allmission,
]);
}
}
This is my repository where is the request :
<?php
namespace App\Repository;
use App\Entity\Mission;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\Query\ResultSetMapping;
use Doctrine\Persistence\ManagerRegistry;
/**
* #extends ServiceEntityRepository<Mission>
*
* #method Mission|null find($id, $lockMode = null, $lockVersion = null)
* #method Mission|null findOneBy(array $criteria, array $orderBy = null)
* #method Mission[] findAll()
* #method Mission[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class MissionRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Mission::class);
}
public function save(Mission $entity, bool $flush = false): void
{
$this->getEntityManager()->persist($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
public function remove(Mission $entity, bool $flush = false): void
{
$this->getEntityManager()->remove($entity);
if ($flush) {
$this->getEntityManager()->flush();
}
}
public function selectmissionswithtags(){
$sql = "SELECT descriptionmission,onsetdate,deadline,prioritymission,remote, GROUP_CONCAT(tg.nomtag SEPARATOR ',') as tag From mission m
left join mission_tag mt on m.id = mt.mission_id
left join tag tg on mt.tag_id = tg.id
GROUP BY descriptionmission;";
$rsm = new ResultSetMapping();
$rsm->addEntityResult(Mission::class, 'mission');
$em = $this->getEntityManager();
return $result = $em->createNativeQuery($sql,$rsm)->getArrayResult();
}
This is my selectmissionwithtags witch return empty array.
enter image description here
Querybuilder -> i don't have GROUP_CONCAT so i can't use this kind of query builder.
NativeQuery -> i use this method for the moment.
The last thing that i can do is to create entity for an database view and create the entity related to. But i would like to understand the querynative method for the moment.
Many thanks ;)
The ResultSetMapping needs to be really explicit to work, you'd have to do something like
$rsm->addEntityResult(Mission::class, 'mission');
$rsm->addFieldResult('mission', 'id', "id");
//same for all fields
$rsm->addJoinedEntityResult(MissionTag::class, 'mt', 'mission', 'mission_tag');
$rsm->addFieldResult('mt', 'id', 'id);
//same for all fields of related entities
But there is ResultSetMappingBuilder to the rescue
$rsmb->addRootEntityFromClassMetadata(Mission::class);
That's all you should have to do, with doctrine handling the relation and hydration. It will try to hydrate from your SELECT tho, so you need all fields used in the hydrator in the SELECT from your query.
You can specify the joined relation with:
$rsm->addJoinedEntityFromClassMetadata(MissionTag::class, 'mt', 'mission', 'relationName', array('id' => "tag_id"));
But then you need the join in the query (it will look for the relation in the select) and you need to be careful to when to use the doctrine name (relationName) and when to use the database name (tag_id)
You could also archived your ends by adding GROUP_CONCAT to doctrine, by leveraging Doctrine's User Defined Functions
I've found a snippet doing exactly that, it's not mine and I have not tested it.

Symfony doctrine ManyToMany unidirectional mapping

Well, back again, i'll try to simplify my question as much as i can.
First of all, i have 2 Entities
Post
PostRating
I've created unidirectional ManyToMany relation between them, because I only need ratings to be added to each Post, if I try to map Post to PostRating too, I get Circular Reference error.
Post Entity, it creates 3rd table post_has_rating, no mapping inside PostRating Entity, It workes like expected, rating collection is added to each post, but if i want to find one rating, and edit it if needed, then it comes to be bigger headache than expected.
/**
* Post have many PostRating
* #ORM\ManyToMany(targetEntity="PostRating")
* #ORM\JoinTable(name="post_has_rating",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="postrating_id", referencedColumnName="id", unique=true)}
* )
*/
protected $ratings;
PostController thumbAction, simple word "ratingAction"
/**
* Search related videos from youtube
* #Route("/post/thumb", name="post_thumb")
* #param Request $request
* #return string
*/
public function thumbAction (Request $request) {
$content = json_decode($request->getContent());
$serializer = $this->get('serializer');
$em = $this->getDoctrine()->getManager();
$postRatingRepo = $this->getDoctrine()->getRepository(PostRating::class);
$postRepo = $this->getDoctrine()->getRepository(Post::class);
$me = $this->getUser()->getId();
/** #var PostRating $rating */
$rating = $postRatingRepo->findOneBy(['userId' => $me]);
/** #var Post $post */
$post = $postRepo->find($content->id);
if ($post->getRatings()->contains($rating)) {
$post->removeRating($rating);
$em->remove($rating);
}
$rating = new PostRating();
$rating->setUserId($me);
switch ($content->action) {
//NVM about those hardcoded words, they are about to be removed
case 'up':
$rating->setRating(1);
break;
case 'down':
$rating->setRating(0);
break;
}
$post->addRating($rating);
$em->persist($rating);
$em->persist($post);
$em->flush();
return new JsonResponse( $serializer->normalize( ['success' => 'Post thumbs up created'] ) );
}
Problems: $rating = $postRatingRepo->findOneBy(['userId' => $me]); this row needs to have postId too for $post->getRatings()->contains($rating), right now im getting all the raitings, that I have ever created, but it Throws error if i add it, Unknown column
Should i create custom repository, so i can create something like "findRating" with DQL?
OR
Can i make Post and PostRating Entities mapped to each other more simple way, i don't really want many-to-many relation, because I don't see point of using it
Considering you want to keep OneToMany unidirectional here is my suggestion
create a custom repository for your Post Entity
namespace AppBundle\Repository;
use Doctrine\ORM\EntityRepository;
class PostRepository extends EntityRepository
{
public function findOneRatingByUser($post, $user)
{
$query = $this->createQueryBuilder('p')
->select('r')
->innerJoin('p.ratings', 'r')
->where('p.id = :post')
->andWhere('r.user = :user')
->setParameter('post', $post)
->setParameter('user', $user)
->getQuery()
;
return $query->getOneOrNullResult();
}
}
Then in your controller:
public function thumbAction (Request $request)
{
$content = json_decode($request->getContent());
$serializer = $this->get('serializer');
$em = $this->getDoctrine()->getManager();
$postRepo = $this->getDoctrine()->getRepository(Post::class);
$me = $this->getUser()->getId();
/** #var Post $post */
$post = $postRepo->find($content->id);
$rating = $postRepo->findOneRatingByUser($post->getId(), $me);
if (null === $rating) {
$rating = new PostRating();
$rating->setUserId($me);
}
switch ($content->action) {
//NVM about those hardcoded words, they are about to be removed
case 'up':
$rating->setRating(1);
break;
case 'down':
$rating->setRating(0);
break;
}
$post->addRating($rating);
$em->persist($rating);
$em->persist($post);
$em->flush();
return new JsonResponse( $serializer->normalize( ['success' => 'Post thumbs up created'] ) );
}
If you want your custom repository to work dont forget to declare it in your entity
/**
* #ORM\Entity(repositoryClass="AppBundle\Repository\PostRepository")
*/
class Post

Error to call a method in Doctrine, Symfony2

I don't understand why I get the following error in my Symfony2 project:
Error: Call to a member function getQueryId() on a non-object
Here are my codes:
Bibliorepository:
<?php
namespace Xxxx\XxxxxBundle\Repository;
use Doctrine\ORM\EntityRepository;
/**
* BiblioRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class BiblioRepository extends EntityRepository
{
public function wantAuthor($author)
{
$query = $this->_em->createQuery('SELECT b FROM XxxxBundle:Biblio b WHERE b.author = :author');
$query->setParameter('author', $author);
$result_author = $query->getResult();
return $result_author;
}
}
The getter:
/**
* Get queryId
*
* #return integer
*/
public function getQueryId()
{
return $this->queryId;
}
}
And the controller:
$author = $this->getUser()->getId();
$repository = $this
->getDoctrine()
->getManager()
->getRepository('XxxxBundle:Biblio');
$resultBiblio = $repository->wantAuthor($author);
$resultBiblio->getQueryId();
foreach ($resultBiblio as $id_query) {
$repository = $this
->getDoctrine()
->getManager()
->getRepository('XxXxBundle:Query');
$resultQuery = $repository->wantQuery($id_query);
$titles = $resultQuery->getQuery();
}
return $this->redirect($this->generateUrl("fos_user_profile_show"));
Thank you very much for your help ;)
$resultBiblio is an array with object. You invoke a method on array and this causes error.
You can invoke this method in foreach like
foreach ($resultBilbo as $singleResult){
$singleResult->getQueryId();
}
Var dump results wantAuthor($author) method and make sure you're getting the Author object in return. I bet you're not getting one.

How to execute a doctrine query inside a DataFixture class?

How can I access the EntityManager or a repository class inside a DataFixture in order to create a query?
If your fixture implements ContainerAwareInterface you have full access to the container and can obtain one of your entity-managers from there.
once you have the entity-manager you can get the repository or create a query using DQL or the querybuilder.
namespace Vendor\YourBundleBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\FixtureInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class LoadCharacterData implements FixtureInterface, ContainerAwareInterface
{
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
public function load()
{
$em = $this->container->get('doctrine')->getEntityManager('default');
// example using DQL
$query = $em->createQuery('SELECT u FROM YourBundle\Entity\User u WHERE u.name = your_name');
$users = $query->getResult();
// example query using repository
$repository = $em->getRepository('YourBundle:User');
$entities = $repository->findBy(array('name' => 'your_name'));
// example using queryBuilder
$qb = $repository->createQueryBuilder('u');
$qb
->where('u.name = :name')
->setParameter('name', 'your_name')
->orderBy('u.name');
$users = $qb->getQuery()->getResult();
// ...
}

Symfony2 flash messages from Entity Repository

Is there a way to write flash messages from entity repository. I have a Tag and Category entity.
I am adding tags via Category form, where i added a custom input field that receives tags separated with ", ". Every time i submit a form i check if the tags in the input already exist, if not i add them to the database and then i add them to the Category entity.
Here is my tag repository where im trying to write the flashmessage:
namespace Kpr\CentarZdravljaBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Kpr\CentarZdravljaBundle\Entity\Tags;
use Symfony\Component\HttpFoundation\Request;
class TagsRepository extends EntityRepository
{
public function findByTagInput($arg)
{
$request = Request::createFromGlobals();
$args = explode(", ", $arg);
$em = $this->getEntityManager();
$tagArray = array();
$addaedTags = "";
foreach($args as $name){
$tag = $this->findByName($name);
if(!$tag){
$addaedTags .= $name.", ";
$newTag = new Tags();
$newTag->setName($name);
$newTag->setApproved(1);
$em->persist($newTag);
$tagArray[] = $newTag;
}
}
if($addaedTags!="") $request->get('session')->getFlashBag()->add('info', substr($addaedTags,0,strlen($addaedTags)-2));
$qb = $em->createQueryBuilder();
$qb->add('select', 'tag')
->add('from', 'KprCentarZdravljaBundle:Tags tag')
->add('where', $qb->expr()->in('tag.name', $args));
// $qb instanceof QueryBuilder
$query = $qb->getQuery();
// Set additional Query options
$query->useResultCache('my_cache_id');
$results = $query->getResult();
/*
$sql = "SELECT * FROM categories WHERE $whereS";
$stmt = $this->getEntityManager()->getConnection()->prepare($sql);
$results = $stmt->execute();
*/
$totalResults = array_merge($tagArray, $results);
$tags = new ArrayCollection($totalResults);
return $tags;
}
public function findByName($name)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->add('select', 'tag')
->add('from', 'KprCentarZdravljaBundle:Tags tag')
->add('where', 'tag.name = :namearg')
->setParameter('namearg', $name);
// $qb instanceof QueryBuilder
$query = $qb->getQuery();
$result = $query->getResult();
return $result;
}
}
The error i get:
FatalErrorException: Error: Call to a member function getFlashBag()
on a non-object in /home/kprhr/public_html/CZ_Symfony/src/Kpr/CentarZdravljaBundle/Entity/TagsRepository.php line 31
I don't think you should handle the request from the EntityManager ; their purposes are different. The EntityManager manages the communication between the DB and your application, it's not its purpose to handle session management, neither is it to add flashes messages.
This job should go to a dedicated service, which will handle that.
Now, your error comes from the way you get your request. You are actually creating a brand new object, which is not properly instanciated, by using the static method createFromGlobals. Instead, you should handle the flash messages in your controller.
This would translate as something like that:
//Controller
public function mypageAction()
{
// Your logic
if (count($args) > 0) {
$this->getRequest()->get('session')->getFlashBag()->add('info', implode(',', $args));
}
// ...
}

Resources