Symfony2 flash messages from Entity Repository - symfony

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));
}
// ...
}

Related

return random data form database in random order and with limit

I'm new with symfony and I'm trying to view data from one of my tables with random order and a limit of 4. I tried doing it in the repository but RAND() is not working so I'm trying in the controller.
The error is the following one:
"Warning: array_rand() expects parameter 1 to be array, object given"
And I don't understand why, when in the $response I set the data into an array.
This is my actual code:
/**
* #Route("/ws/random/superviviente", name="ws_random_survi")
*/
public function randomSurvi(Request $request): Response
{
$data = $request->request->all();
$entityManager = $this->getDoctrine()->getManager();
$randomPerks = $entityManager->getRepository(Perks::class)
->getRandomPerks();
$response = new JsonResponse();
$response -> setStatusCode(200);
$response -> setData(array('random perk' => $randomPerks));
$resultRandom = array_rand($response);
return $resultRandom;
}
You are trying to use array_rand on a doctrine array collection.
You could either convert it as array and back to a doctrine array :
use Doctrine\Common\Collections\ArrayCollection;
public function randomSurvi(Request $request): Response
{
$data = $request->request->all();
$entityManager = $this->getDoctrine()->getManager();
$randomPerks = $entityManager->getRepository(Perks::class)
->getRandomPerks();
$resultRandom = new ArrayCollection(array_rand($randomPerks->toArray()));
return new JsonResponse($resultRandom);
}
Otherwise it would work with shuffle :
$randomPerks = $entityManager->getRepository(Perks::class)->getRandomPerks();
$randomPerks = shuffle($randomPerks);
Or get random perks directly through your method in your repository.
See example from #Krzysztof Trzos:
public function getRandomProducts($amount = 7)
{
return $this->getRandomProductsNativeQuery($amount)->getResult();
}
/**
* #param int $amount
* #return ORM\NativeQuery
*/
public function getRandomProductsNativeQuery($amount = 7)
{
# set entity name
$table = $this->getClassMetadata()
->getTableName();
# create rsm object
$rsm = new ORM\Query\ResultSetMapping();
$rsm->addEntityResult($this->getEntityName(), 'p');
$rsm->addFieldResult('p', 'id', 'id');
# make query
return $this->getEntityManager()->createNativeQuery("
SELECT p.id FROM {$table} p ORDER BY RAND() LIMIT 0, {$amount}
", $rsm);
}
You could write your own query to achieve this, so create a new method inside the repository like so:
public function getRandomPerks(int $limit): array
{
$queryBuilder = $this->createQueryBuilder('p');
return $queryBuilder
->setMaxResults($limit)
->orderBy('RAND()')
->getQuery()
->getResult();
}
Then in your controller all you would to do is call the method and pass a limit:
$randomPerks = $entityManager->getRepository(Perks::class)
->getRandomPerks(4);

Code Style: Doctrine2 queries from entity repository?

As I understand the best code style is to put the complex SQL/DQL queries to the entity repositories.
For example there is an entity named "News". It has an own entity repository named "NewsRepository".
In the controller there is this code:
/**
* #Route("/news", name="news")
*/
public function indexAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$news = $paginator->paginate(
$em->createQuery('SELECT n FROM AppBundle:News n'),
$request->query->getInt('page', 1),
10
);
return $this->render('app/news/list.html.twig', array(
'news' => $news,
));
}
Now I like to add further features (filtering, order by, ..). That because I think the query should be moved to any service or the entity repository. But how and what is the best coding style?
(And does anybody have nice generic ideas how to easily add filtering, order by ... ?)
Sure,
Every request should be in the repository if you want use it again. Not only complexiest.
I'll try to answer your first question and after give you a tip that could help you with your "generic filtering"
If you want to put your request in the repo just make in your NewsRepository :
public function findAllOrderedByDate() {
$qb = $this->createQueryBuilder('n');
$qb->orderBy('creationDate');
return $qb->getQuery()->getResult();
}
And in your controller :
public function indexAction(Request $request)
{
$newsRepo = $this->get('doctrine')->getRepository('AppBundle:News');
$em = $this->getDoctrine()->getManager();
$paginator = $this->get('knp_paginator');
$news = $newsRepo->findAllOrderedByDate();
$pagination = $paginator->paginate(
$news,
$request->query->getInt('page', 1),
10
);
return $this->render('app/news/list.html.twig', array(
'news' => $pagination,
));
}
For the filtering, you have a trick in your repor that consist by returning the qb and not directly results.
As well, you can make a function that add you orderBy with a given parameter (using addOrderBy() or andWhere) and which return the queryBuilder. After all of that you can process.
EDIT :
The solution i read on this thread :
public function findAllOrderedByDate(callable $func = null) {
$qb = $this->createQueryBuilder('n');
$qb->orderBy('creationDate');
if (is_callable($func)) {
return $func($qb);
}
return $qb->getQuery()->getResult();
}
and in your controller :
$func = function (QueryBuilder $qb) use ($paginator, $request) {
return $paginator->paginate($qb, $request->query->getInt('page', 1), 10);
};
$pagination = $em->getRepository('AppBundle:News')->findAllOrderedByDate($func);
Model part must be in model part. Move queries to repo's.
And what do you mean, saying this: "nice generic ideas how to easily add filtering, order by"?
OrderBy
Where - same link

Doctrine replace associations with their ids

I'm building an API using FOSRestBundle in Symfony2 and I'm trying to remove the entity associations from an entity with no luck, to minimize the JSON data sent in the API response.
public function helperRemoveAssociations($entities) {
$em = $this->getEntityManager();
$data = array();
/** #var WBEntity $entity */
foreach ($entities as $entity) {
$entityAssociations = $entity->getAssociationNames($em); // ex: array('category', 'comments')
foreach ($entityAssociations as $associationName) {
$associationGetter = 'get' . ucfirst($associationName);
$associationSetter = 'set' . ucfirst($associationName);
/** #var WBEntity $associationObject */
$associationObject = $entity->$associationGetter();
$associationId = $associationObject->getEntityId($em); // ex: 51
$entity->$associationSetter($associationId); // I am not allowed to write an integer
}
$data[] = $entity;
}
return $data;
}
How can I accomplish this, replacing the associated entities with their respective ids.

Symfony2.6 - Service

I have learnt Symfony2 since several months.
I have created a service. When I use it in a simple controller, I have no problem. When I use it in my controller that manages my entity, I have a problem.
My service is:
<?php
namespace Cours\BlogBundle\Services;
class Service1
{
public function creerSlug($texte)
{
$texte = transliterator_transliterate("Latin-ASCII; [:Punctuation:] Remove; Lower();", $texte);
$texte = preg_replace('/[-\s]+/', '-', $texte);
$texte = trim($texte, '-');
return $texte;
}
}
My simple controller is:
<?php
namespace Cours\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Cours\BlogBundle\Services\Service1;
class TestController extends Controller
{
public function indexAction()
{
$texte = "Le test du slug";
$service1 = $this->container->get('service1');
$texte = $service1->creerSlug($texte);
return $this->render('CoursBlogBundle:Test:index.html.twig', array('texte' => $texte));
}
}
The action of my controller that manages my entity is:
public function ajouterAction(Request $request)
{
$rubrique = new Rubrique();
$form = $this->createForm(new RubriqueType(), $rubrique);
if ($request->isMethod('POST'))
{
$form->handleRequest($request);
if ($form->isValid())
{
$manager = $this->getDoctrine()->getManager();
$rubrique = $form->getData();
$texte = $rubrique->getTexte();
$service1 = $this->container->get('service1');
$slug = $serviceSlug->creerSlug($texte);
$slug = $rubrique->setSlug($slug);
$manager->persist($rubrique);
$manager->flush();
return $this->redirect($this->generateUrl('cours_blog_accueil'));
}
}
return $this->render('CoursBlogBundle:Rubrique:ajouter.html.twig', array('form' => $form->createView()));
}
My view tells me that my slug can’t be empty.
I think there is a mistake in my action but I can’t find it.
Does anyone help me?
KISSES AND THANK YOU VERY MUCH
change
$service1 = $this->container->get('service1');
$slug = $serviceSlug->creerSlug($texte);
to
$serviceSlug = $this->container->get('service1');
$slug = $serviceSlug->creerSlug($texte);
I suggest to comment/remove $rubrique = $form->getData(); $texte = $rubrique->getTexte(); from ajouterAction and set the text manually (just for testing purpose):
if ($form->isValid())
{
$manager = $this->getDoctrine()->getManager();
// $rubrique = $form->getData();
// $texte = $rubrique->getTexte();
$rubrique->setTexte('Some text');
$service1 = $this->get('service1');
$slug = $service1->creerSlug($rubrique->getTexte());
...
if it works, you can set some validations to the texte field in your form type which prevents entering an invalid value.
Also I suggest to use some libraries (Cocur/Slugify can be a good option) instead of handling the process by yourself.

symfony2 get field from controller without getting whole entities

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

Resources