Symfony2 - Generate CRUD - symfony

I am trying to generate CRUD of the entities but i have a few questions, i don't know if it's a normal comportment or an error.
I apply the command :
I am adding the route in routing.yml like asking.
Now, when i am testing this crud , just create party work.
Update doesn't working, it's updateAction :
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('IFppoGestionPersonnelBundle:TableTest')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find TableTest entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('tabletest_edit', array('id' => $id)));
}
return $this->render('IFppoGestionPersonnelBundle:TableTest:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
I don't know why it doesn't add "em->persist($entity)", but if i add this line , it does not update ...
I have same errors with deleteAction.
And when i am creating a new tuple, and back to list , the last tuple is not displaying.
It's maybe an error to the class :
IFppo\GestionPersonnelBundle\Entity\TableTest:
type: entity
table: tabletest
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
nom:
type: string
length: 255
column: nom
prenom:
type: string
length: 255
column: prenom
lifecycleCallbacks: { }
In log, i don't have any trace of update ...
[EDIT] When writing to the log for any errors, return an empty array with $editForm->getErrors() and with $editForm->getErrorsAsString() return :
nom: No errors prenom: No errors submit: No errors [] []
Thanks a lot.

Related

Symfony 3 update Action

In my project, foreign key should hidden in the form type and have default value so the first id in the table refernced.
In the New Action all good but is in the update action that I block.
I've tried like tkis to give default value for my foreign key in update but It don't works, I have an error: Expected argument of type "AppBundle\Entity\Cursus", "string" given
public function editAction(Request $request, Etudiant $etud)
{
$deleteForm = $this->createDeleteForm($etud);
$editForm = $this->createForm('AppBundle\Form\EtudiantType', $etud);
$editForm->handleRequest($request);
$first = $this->getDoctrine()->getRepository(Cursus::class)->findOneBy([]);
$etud->setIdcursus($first);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('etudiant_edit');
}
return $this->render('etudiant/edit.html.twig', array(
'etudiant' => $etud,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
EDIT
Symfony 3.3.10
form Type
$builder->add('nom')
->add('prenom')
->add('adresse')
->add('matricule')
->add('domaine')
->add('idcursus', HiddenType::class);
The problem
The wrong is in my idcursus whom should hidden and have default value(the first id in cursus entity).

Why my action is not loaded when I click on a button?

I wanted to create a button that delete a pupil. But I have a problem, my button doesn't launch the deleteAction in my controller.
My controller :
public function deleteAction(Eleve $id, $schoolId)
{
$repository = $this->getDoctrine()->getManager()->getRepository('WCSCantineBundle:Lunch');
$pupil = $repository->findOneBy(array(
'eleve' => $id
));
$em = $this->getDoctrine()->getManager();
$em->remove($pupil);
$em->flush();
return $this->redirect($this->generateUrl('wcs_cantine_todayList', array('schoolId' => $schoolId)));
}
My route :
delete_pupil:
path: /
defaults: { _controller: "WCSCantineBundle:CanteenManager:delete" }
My button (in my view) :
Désinscrire
Thank you for your help.
public function deleteAction(Eleve $id, $schoolId)
{
$em = $this->getDoctrine()->getManager();
$pupil = $em->getRepository('WCSCantineBundle:Lunch')->findOneBy(array('eleve' => $id));
$em->remove($pupil);
$em->flush();
return $this->redirect($this->generateUrl('wcs_cantine_todayList', array('schoolId' => $schoolId)));
}
your code fails because the doctrine entity manager has no clue about what $pupil is since there is two different instances of entity managers, the above code is short hand for removing pupil, but you can change it as needed as long as the entity manager 'knows' about the entity
I did it and it works.
My controller :
public function deleteAction($id, $schoolId)
{
$dateNow = new \DateTime();
$em = $this->getDoctrine()->getManager();
$lunches = $em->getRepository('WCSCantineBundle:Lunch')->findBy(array(
'eleve' => $id,
'date' => $dateNow
));
foreach ($lunches as $lunch) {
$em->remove($lunch);
}
$em->flush();
return $this->redirect($this->generateUrl('wcs_cantine_todayList', array('schoolId' => $schoolId)));
}
My route :
delete_pupil:
path: /todayList/{schoolId}/{id}
defaults: { _controller: "WCSCantineBundle:CanteenManager:delete" }
methods: [GET, DELETE]
And my view :
Désinscrire
I missed to pass my arguments in my route with slashes : /todayList/{schoolId}/{id}
I thank everybody for your help.

elastica search how to convert Elastica\Result to actual doctrine object

I am using FOSElasticaBundle with symfony2 and doctrine 2.
I have trouble understanding how to retrieve actual doctrine objets from a search result. I am under the impression that it is the default behaviour but I get this kind of result :
object(Elastica\Result)[1239]
protected '_hit' =>
array (size=5)
'_index' => string 'foodmeup' (length=8)
'_type' => string 'recipes' (length=7)
'_id' => string '2' (length=1)
'_score' => float 2.2963967
'_source' =>
array (size=5)
'name' => string 'Bavaroise vanille' (length=17)
'nickName' => string 'Bavaroise vanille' (length=17)
'content' => null
'userRecipes' =>
array (size=1)
...
'tags' =>
array (size=0)
Here is my FOSElasticaBundle configuration:
#Elastic Search
fos_elastica:
default_manager: orm
clients:
default: { host: localhost, port: 9200 }
indexes:
search:
client: default
index_name: foodmeup
types:
recipes:
mappings:
name: { type: string, boost: 5}
nickName: { type: string }
content: { type: string }
userRecipes:
type: "nested"
properties:
name: { type: string }
content: { type: string }
tags:
type: "nested"
boost: 5
properties:
name: { type: string }
persistence:
driver: orm
model: AppBundle\Entity\FoodAnalytics\Recipe
repository: AppBundle\Repository\FoodAnalytics\RecipeRepository
provider: ~
finder: ~
listener: ~ # by default, listens to "insert", "update" and "delete"
And the code in my controller :
public function searchAction(Request $request)
{
$search = $request->query->get('search');
$finder = $this->get('fos_elastica.index.search.recipes');
$results = $finder->search($search)->getResults();
return array(
'search' => $search,
'results' => $results
);
}
I understood I could use a custom repository method to get the objects, but before I reach that point, what is the default way to get objects ? (Here I want a Recipe Object, an instance of my model).
Thanks a lot !
Got it!
I called the wrong service. The correct controller code to retrieve directly object instances is:
public function searchAction(Request $request)
{
$search = $request->query->get('search');
$finder = $this->get('fos_elastica.finder.search.recipes');
$results = $finder->find($search);
return array(
'search' => $search,
'results' => $results
);
}

Entity Field type hidden in Symfony2

I want to make a hidden value for my Foreign Key Entity in controller.
My previous controller is like this (works fine):
->add('id_grup', 'entity', array('class' => 'Sifo\AdminBundle\Entity\MstGrup'))
I want to assign a hidden value to my form like this:
->add('id_grup', 'hidden', array('data' => $id))
But it gives me an error:
ContextErrorException: Catchable Fatal Error: Argument 1 passed to
Sifo\AdminBundle\Entity\DftGrupMapel::setIdGrup() must be an instance
of Sifo\AdminBundle\Entity\MstGrup, string given, called in
C:\Sifony\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php
on line 360 and defined in
C:\Sifony\src\Sifo\AdminBundle\Entity\DftGrupMapel.php line 179
How can I assign a value to a foreign key entity which is hidden?
Finally it works! I need define the entity default before create form and don't add again in FormBuilder:
public function manageAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('SifoAdminBundle:MstGrup')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find MstGrup entity.');
}
$entity_new = new DftGrupMapel();
$entity_new->setIdGrup($entity);
$new_form = $this->createFormBuilder($entity_new)
->setAction($this->generateUrl('admin_grup_mapel_manage', array('id' => $id)))
->setMethod('POST')
->getForm();
$new_form->handleRequest($request);
if ($new_form->isValid()) {
$em_new = $this->getDoctrine()->getManager();
$em_new->persist($entity_new);
$em_new->flush();
return $this->redirect($this->generateUrl('admin_grup_mapel_manage', array('id' => $id)));
}
return $this->render('SifoAdminBundle:DftGrupMapel:manage.html.twig', array(
'entity' => $entity,
'new_form' => $new_form->createView(),
));
}

Prevent duplicates in the database in a many-to-many relationship

I'm working on a back office of a restaurant's website. When I add a dish, I can add ingredients in two ways.
In my form template, I manually added a text input field. I applied on this field the autocomplete method of jQuery UI that allows:
Select existing ingredients (previously added)
Add new ingredients
However, when I submit the form, each ingredients are inserted in the database (normal behaviour you will tell me ).
For the ingredients that do not exist it is good, but I don't want to insert again the ingredients already inserted.
Then I thought about Doctrine events, like prePersist(). But I don't see how to proceed. I would like to know if you have any idea of ​​the way to do it.
Here is the buildForm method of my DishType:
<?php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('category', 'entity', array('class' => 'PrototypeAdminBundle:DishCategory',
'property' => 'name',
'multiple' => false ))
->add('title', 'text')
->add('description', 'textarea')
->add('price', 'text')
->add('ingredients', 'collection', array('type' => new IngredientType(),
'allow_add' => true,
'allow_delete' => true,
))
->add('image', new ImageType(), array( 'label' => false ) );
}
and the method in my controller where I handle the form :
<?php
public function addDishAction()
{
$dish = new Dish();
$form = $this->createForm(new DishType, $dish);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($dish);
$em->flush();
return $this->redirect($this->generateUrl('prototype_admin_get_dish', array('slug' => $dish->getSlug())));
}
}
return $this->render('PrototypeAdminBundle:Admin:addDish.html.twig', array(
'form' => $form->createView(),
));
}
I was having the same problem. My entities were projects (dishes in your case) and tags (ingredients).
I solved it by adding an event listener, as explained here.
services:
my.doctrine.listener:
class: Acme\AdminBundle\EventListener\UniqueIngredient
tags:
- { name: doctrine.event_listener, event: preUpdate }
- { name: doctrine.event_listener, event: prePersist }
The listener triggers both prePersist (for newly added dishes) and preUpdate for updates on existing dishes.
The code checks if the ingredient already exists. If the ingredient exists it is used and the new entry is discarded.
The code follows:
<?php
namespace Acme\AdminBundle\EventListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Acme\AdminBundle\Entity\Dish;
use Acme\AdminBundle\Entity\Ingredient;
class UniqueIngredient
{
/**
* This will be called on newly created entities
*/
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// we're interested in Dishes only
if ($entity instanceof Dish) {
$entityManager = $args->getEntityManager();
$ingredients = $entity->getIngredients();
foreach($ingredients as $key => $ingredient){
// let's check for existance of this ingredient
$results = $entityManager->getRepository('Acme\AdminBundle\Entity\Ingredient')->findBy(array('name' => $ingredient->getName()), array('id' => 'ASC') );
// if ingredient exists use the existing ingredient
if (count($results) > 0){
$ingredients[$key] = $results[0];
}
}
}
}
/**
* Called on updates of existent entities
*
* New ingredients were already created and persisted (although not flushed)
* so we decide now wether to add them to Dishes or delete the duplicated ones
*/
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
// we're interested in Dishes only
if ($entity instanceof Dish) {
$entityManager = $args->getEntityManager();
$ingredients = $entity->getIngredients();
foreach($ingredients as $ingredient){
// let's check for existance of this ingredient
// find by name and sort by id keep the older ingredient first
$results = $entityManager->getRepository('Acme\AdminBundle\Entity\Ingredient')->findBy(array('name' => $ingredient->getName()), array('id' => 'ASC') );
// if ingredient exists at least two rows will be returned
// keep the first and discard the second
if (count($results) > 1){
$knownIngredient = $results[0];
$entity->addIngredient($knownIngredient);
// remove the duplicated ingredient
$duplicatedIngredient = $results[1];
$entityManager->remove($duplicatedIngredient);
}else{
// ingredient doesn't exist yet, add relation
$entity->addIngredient($ingredient);
}
}
}
}
}
NOTE: This seems to be working but I am not a Symfony / Doctrine expert so test your code carefully
Hope this helps!
pcruz
Since this post is 2 years old I don't know if help is still needed here, anyway..
You should place an addIngredient function within your Dish entity, this function checks if the Ingredient object exists within the current ingredient collection.
addIngredient(Ingredient $ingredient){
if (!$this->ingredients->contains($ingredient)) {
$this->ingredients[] = $ingredient;
}
}
Hopefully it could still help you out.

Resources