When to call validator in Symfony forms? - symfony

I dont know when to call validation in this situation ? I made some constraints in Form/Model/User.php class for propertys, and don't know where to call it and how.And how to display errors on the same page.
What is best practice to do this right ?
public function userRegistrationAction(Request $request) {
$formUser = new FormUser();
$form = $this->createForm(UserType::class, $formUser);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$userEntity = new EntityUser();
$name = $form['name']->getData();
$surname = $form['surname']->getData();
$email = $form['email']->getData();
$password = $this->get('security.password_encoder')
->encodePassword($userEntity, $form['password']->getData());
$now = new\DateTime('now');
$userEntity->setName($name);
$userEntity->setSurname($surname);
$userEntity->setEmail($email);
$userEntity->setPassword($password);
$userEntity->setCreated($now);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($userEntity);
$entityManager->flush();
$request->getSession()
->getFlashBag()
->add('success', '- Success! ');
return $this->render('AppBundle:Welcome:homepage.html.twig', array(
'name' => $name,
'lastName' => $surname,
));
}

Did you created a formUser entity to fill a form then fill a user entity ? This make a lot of redundancies.
Your controller should looks like that:
<?php
public function userRegistrationAction(Request $request)
{
$userEntity = new EntityUser();
/*
You can directly provide your user entity to your form
There is no need to create a specific entity fir the form
*/
$form = $this->createForm(UserType::class, $userEntity);
$form->handleRequest($request);
/*
method isValid checks the form has been submitted so there
is no need to call isSubmitted by yourself
*/
if ($form->isValid()) {
/*
The password encryption part could be improved by
doing it outside of the controller
*/
$password = $this->get('security.password_encoder')
->encodePassword($userEntity, $userEntity->getPassword())
;
$userEntity->setPassword($password);
$entityManager = $this->getDoctrine()->getManager();
/*
By providing your user at your form at the begining all it
remains to do is persisting it and flush the manager
to insert it into your database.
*/
$entityManager->persist($userEntity);
$entityManager->flush();
$this->addFlash('success', '- Success! ');
return $this->render('AppBundle:Welcome:homepage.html.twig', array(
'name' => $name,
'lastName' => $surname,
));
}
return $this->render('AppBundle:User:userRegistration.html.twig', array(
'form' => $form->createView()
));
}
Now your form should look like that
<?php
class UserType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('surname')
->add('email')
->add('password', PasswordType::class)
->add('submit', SubmitType::class)
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\EntityUser',
));
}
/**
* #return string
*/
public function getName()
{
return 'user_type';
}
}
Your entity EntityUser
<?php
/**
* #ORM\HasLifecycleCallbacks()
*/
class EntityUser extends Entity
{
/**
* #ORM\PrePersist
*/
public function setCreatedAtValue()
{
/*
By using the PrePersist annotation you will automatically set
the createdAt property
*/
$this->createdAt = new \DateTime();
}
}
And finally your twig template
{# form_row is a shortcut to render at once
form_errors(form.field)
form_label(form.field)
form_widget(form.field)
so if you have errors on some of your fields there will be displayed #}
{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.surname }}
{{ form_row(form.email) }}
{{ form_row(form.password) }}
{{ form_row(form.submit) }}
{{ form_end(form) }}

OK, this was the problem: 'validation_groups' => ['registration'], i set this group for only one field, now i delete this and working nice, no need for callig validator after isValid.
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'validation_groups' => ['registration'], //delete this
'method' => 'post',
'data_class' => User::class,
'csrf_protection' => true,
'cascade_validation' => true
));
}

Related

Hide a field according to its role Symfony 3

First sorry for my english because is not great!
So I want to hide a field according to it's role because if I make with Twig the field to display on the bottom form
My code for understand, this's my LinkType :
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('link')
->add('description')
// this field to hidden according the role
->add('published', CheckboxType::class);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Link'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_link';
}
a part of Controler:
public function newAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$categories = $em->getRepository('AppBundle:Category')->findAll();
$subCategories = $em->getRepository('AppBundle:SubCategory')->findAll();
$gestionCategorie = $this->container->get('app.categorie');
$link = new Link();
$repository = $this
->getDoctrine()
->getManager()
->getRepository('AppBundle:Link');
$category = $repository->findCategory();
$subCategory = $repository->findSubCategory();
$form = $this
->get('form.factory')
->create('AppBundle\Form\LinkType', $link)
->add('categories', ChoiceType::class, array(
// on inverse les clés et valeurs
'choices' => array_flip($category),
'label' => "Catégorie",
'attr' => ['class' => 'form-control'],
))
->add('sousCategories', ChoiceType::class, array(
// on inverse les clés et valeurs
'choices' => array_flip($subCategory),
'label' => "Sous-catégorie",
'attr' => ['class' => 'form-control'],
));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
If you have other questions, don't hesitate
If you want to do this in the controller, first remove your field in your form class, then add:
$user = $this->getUser();
if (in_array('MY_ROLE_NAME', $user->getRoles())) {
$builder->add('published', CheckboxType::class);
}
A better and cleaner approach is using a form as a service and injecting token storage service into it:
// services.yml
AppBundle\Form\:
resource: '../../src/AppBundle/Form'
public: true
autowire: true
// Form type class
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
//...
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$user = $this->tokenStorage->getToken()->getUser();
$builder
->add('title')
->add('link')
->add('description');
if (in_array('MY_ROLE_NAME', $user->getRoles())) {
$builder->add('published', CheckboxType::class);
}
}

How to load data in ChoiceType choices options from the database

I want to build a form with ChoiceType and the option values/choices are based on database table (with records already).
When the form displayed, the list of religions will be available at the dropdown list/combo box.
Example :
$builder->add('name', ChoiceType::class, array(
'choices' => $religions //List of religions
));
So far here are my codes:
class Religion
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=50)
*/
protected $name;
/*** getter/setter ... ***/
}
/Form/ReligionType
class ReligionType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', ChoiceType::class, array(
'choices' => ____________
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Religion'
));
}
public function getName()
{
return 'app_bundle_religion_type';
}
}
/Controller
/**
* #Route("/religion/select", name="religion_select")
*
*/
public function selectAction()
{
$em = $this->getDoctrine()->getManager();
$religions = $em->getRepository('AppBundle:Religion')->findAll();
$form = $this->createForm(ReligionType::class, ________);
return $this->render(
'religion/index.html.twig', array(
'form' => $form->createView()
)
);
}
I don't really know what to write so i leave it as __________ and what are the missing codes.
/ReligionRepository
class ReligionRepository extends EntityRepository
{
public function findAll()
{
return $this->getEntityManager()
->createQuery(
'SELECT p FROM AppBundle:Religion p ORDER BY p.name ASC'
)
->getResult();
}
}
/Twig File
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form) }}
<button type="submit">Save</button>
{{ form_end(form) }}
{% endblock %}
as suggested by Rvanlaak, here's the solution.
//ReligionType
$builder->add('religions', EntityType::class, array(
'class' => 'AppBundle\Entity\Religion',
'choice_label' => 'name'
));
//Controller
public function newAction(Request $request)
{
$religion = new Religion();
$form = $this->createForm(ReligionType::class, $religion);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($religion);
$em->flush();
//return $this->redirectToRoute('homepage');
}
return $this->render(
'religion/new.html.twig',
array(
'form' => $form->createView()
)
);
}
I did like this:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('currency', null, [
'expanded' => true,
'multiple' => true,
'label' => 'Currency'
])
In my entity like this:
protected $currency;
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->Currency = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #param \MyBundle\Entity\Currency $Currency
*
* #return $this
*/
public function addCurrency(\MyBundle\Entity\Currency $Currency)
{
$this->Currency[] = $Currency;
return $this;
}
/**
* Remove Currency
*
* #param \MyBundle\Entity\Currency $Currency
*/
public function removeCurrency(\MyBundle\Entity\Currency $Currency)
{
$this->Currency->removeElement($Currency);
}
/**
* Get Currency
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCurrency()
{
return $this->Currency;
}
Both posted solutions didn't work for me because the ChoiceType type was removed from it. Here is a solution with the ChoiceType still existing:
I wanted to generate a list with types of absents users can choose from. These types are created by a user in the system settings. I first load them from db, then create one array (for loop) with where the ["name"] will be the name the user sees. The id is the value that the html select field will have and return when selected and saved.
What I added and could not find anywhere was the extra option to pass an option in the createForm function. This enables you to send data to the form basicly.
$systemAbsents = $this->getDoctrine()->getRepository(SystemAbsent::class)->getAllNonDeletedSystemAbsents();
$choices = [];
// Add each choice to the list. The id's have to match correctly so the html choicetype will return the chosen id that then will be saved in the db.
for ($i = 0; $i < count($systemAbsents); $i++) {
$choices += [$systemAbsents[$i]["name"] => $systemAbsents[$i]["id"]];
}
$absent = new Absent();
// Create form and pass the choices to later connect them with the ChoiceType field.
$form = $this->createForm(AbsentType::class, $absent, ['choices' => $choices]);
$form->handleRequest($request);
Then in the form, you can use the data and pass it to the 'choices' option.
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->choices = $options['choices'];
$builder
->add('choices', ChoiceType::class, [
'choices' => $this->choices,
'label_attr' => [
'class' => 'bold',
],
'attr' => [
'class' => 'input-margin select-field w-100',
],
'mapped' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'choices' => [],
]);
}
The array I create in the for loop looks like this:
[
"absent-type-1" => 10
"absent-type-2" => 11
"absent-type-3" => 12
"absent-type-4" => 13
"absent-type-5" => 14
"absent-type-6" => 15
"absent-type-7" => 16
"absent-type-8" => 17
]
The ID starts at 10 because I deleted some while testing.
If you by default want to show a selected value in the ChoiceType field you can do setData after you create the form. Like this:
// Create form
$form = $this->createForm(AbsentType::class, $absent, ['choices' => $choices]);
// Add this line to set a default. But make sure you pass the value equal to the html `value` attribute.
$form->get('system_absents')->setData($absent->getSystemAbsentID());
$form->handleRequest($request);
There is a possiblity you get an Array to string conversion error. I dont know how exactly this works but i've once used this solution before.

Symfony2 Conditional Validation

I have a FormType method.
<?php
class PostType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title')
->add('text')
->add('paymentMethod', 'choice', array(
'required' => true,
'choices' => array(
'cach' => 'Cach',
'check'=> 'Check'
)
))
->add('checkId', 'integer', array(
'required' => true
))
->add('submit', 'submit');
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Post',
]);
}
/**
* #return string
*/
public function getName()
{
return 'appbundle_post';
}
}
?>
The field checkId is displaying only when the choice 'check' is selected with the field paymentMethod.
Here is the javascript:
PaymentMethod = {
hideCheckId: function(){
$('.check-id').hide();
},
showCheckId: function(){
$('.check-id').fadeIn();
},
whenPaymentMethodChange: function(){
$('#appbundle_post_paymentMethod').on('change', function(){
var method = this.value ;
if(method == 'check'){
PaymentMethod.showCheckId();
}else{
PaymentMethod.hideCheckId();
}
})
}
};
PaymentMethod.hideCheckId();
PaymentMethod.whenPaymentMethodChange();
I would like the field 'checkId' to be required to TRUE only when the option check is selected.
How can I do that?
Ok thanks, Here is the solution for everyone:
Add a callback method function in your entity class.
/**
* #param ExecutionContextInterface $context
* #Assert\Callback()
*/
public function isPaymentIsCheck(ExecutionContextInterface $context)
{
if ($this->getPaymentMethod() == 'check' and $this->getCheckId() == '') {
$context->buildViolation('A check ID as to be defined')
->atPath('checkID')
->addViolation();
}
}
Don't forget to add the Assert and ExecutionContextInterface component in you entity class:
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
And finally don't forget to display errors in the twig template:
{% if form.vars.errors|length %}
<div class="alert alert-danger">{{ form_errors(form) }}</div>
{% endif %}
Hope it will help you.
More info here: http://symfony.com/doc/current/reference/constraints/Callback.html
What KevinR wrote would definitely solve your problem, but in my opinion there's even cleaner solution:
http://symfony.com/doc/current/book/validation.html#group-sequence-providers
Imagine a User entity which can be a normal
user or a premium user. When it's a premium user, some extra
constraints should be added to the user entity (e.g. the credit card
details). To dynamically determine which groups should be activated,
you can create a Group Sequence Provider. First, create the entity and
a new constraint group called Premium:
This is exactly your how you would solve this kinda of problem
public function getGroupSequence()
{
$groups = array('Post'); //Or array('Default') whichever you prefer
if ($this->getPaymentMethod() === 'Check') {
$groups[] = 'Check';
}
return $groups;
}
Of course you'll have to add validation group paymentMethod property in your entity mapping. Here's annotation example, for more examples check above link.
/**
* #Assert\IsTrue(groups={"Check"})
*/
private $checkId;

Symfony2: Can't create new entity with form

I am having problem with creating new Collection entity with Form.
I want to create new Collection entity with form and then to be redirected to collections page with 'collection_user_collections' route, and be able to see new collection in user's collections list. But instead when I press submit button on form, I get following error:
No route found for "POST /profile/": Method Not Allowed (Allow: GET, HEAD)
Below is my code:
class Collection{
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
private $name;
private $url;
private $type;
const STATUS_PRIVATE = 0;
const STATUS_PUBLIC = 1;
/**
* #ORM\ManyToOne(targetEntity="MyMini\UserBundle\Entity\User", inversedBy="collections")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
private $date_created;
private $date_modified;
/* getters and setters are here*/
}
I am using CollectionType to build form:
class CollectionType extends AbstractType{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name','text')
->add('type', 'choice', array('choices' => array(
Collection::STATUS_PRIVATE => 'Private',
Collection::STATUS_PUBLIC => 'Public',
)))
->add('save', 'submit', array('label' => 'Create Collection'))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'MyMini\CollectionBundle\Entity\Collection'
));
}
public function getName()
{
return 'mymini_collectionbundle_collection';
}
}
This is createAction, here I tried to insert current user's username and date when entity was created. I am using FOSUserBundle to manage app users:
/**
* #Route("/create-collection/", name="collection_create_collection")
* #Template()
*/
public function createAction(Request $request)
{
$collection = new Collection();
$user = $this->get('security.token_storage')->getToken()->getUser();
$username = $user->getUsername();
$form = $this->createForm(new CollectionType(), $collection);
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$collection->setUser($user);
$collection->setDateCreated(new \DateTime());
$em->persist($collection);
$em->flush();
return $this->redirectToRoute('collection_user_collections', array('username' => $username));
}
return array('collection'=>$collection, 'form' => $form->createView());
}
Twig for form:
<div class="collection-create">
<h3 id="create-collection">Create a collection</h3>
<a class="close-reveal-modal" aria-label="Close">×</a>
{{ form(form) }}
</div>
The exception you're receiving is expected. You are calling the createForm method without passing all necessary arguments. The right way to create a form is:
$this->createForm(
new CollectionType(),
$collection,
array(
'action' => $this->generateUrl('collection_create_collection') ),
'method' => 'PUT', // or 'POST'
)
);

Update Data from Collection Form in Symfony2

I can't find how to update data in form collection to database, like in normal Edit action, the EditForm generated and pass to UpdateAction. I can make form for EditForm but can't find how to update data to database.
How to Embed a Collection of Forms is showing how to add and delete it using persist and remove but how to bind it from post data and update it into database? My collection actually just entity without table in database. It's used just for population many fields from my primary entity DftAbsensi into single form.
This is my primary entity DftAbsensi (without getter and setter):
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
class DftAbsensi
{
private $id;
private $tanggal;
private $status;
This is the collection entity for Absensi :
<?php
namespace Sifo\AdminBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
class CollectionAbsensi
{
private $statusS;
private $tanggal;
public function __construct()
{
$this->tanggalS = new ArrayCollection();
$this->statusS = new ArrayCollection();
}
public function setTanggal($tanggal)
{
$this->tanggal = $tanggal;
return $this;
}
public function getTanggal()
{
return $this->tanggal;
}
public function setStatusS(ArrayCollection $statusS)
{
$this->statusS = $statusS;
return $this;
}
public function getStatusS()
{
return $this->statusS;
}
}
This is DftAbsensiType :
<?php
namespace Sifo\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class DftAbsensiType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('id', 'text', array('required' => false))
->add('status', 'choice', array(
'choices' => array('H' => 'Hadir', 'A' => 'Tanpa Keterangan', 'S' => 'Sakit', 'I' => 'Izin', 'L' => 'Libur'),
'required' => false,
'empty_value' => '- Pilih -'))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sifo\AdminBundle\Entity\DftAbsensi'
));
}
public function getName()
{
return 'sifo_adminbundle_dftabsensi';
}
}
Actually I'm using collection just for populating many fields from databases. Persist database just in my primary entity DftAbsensi above. This is Collection for Absensi Type :
<?php
namespace Sifo\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CollectionAbsensiType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('tanggal', 'date', array('label' => false, 'required' => false, 'attr'=>array('style'=>'display:none;'), 'widget' => 'single_text', 'format' => 'yyyy-MM-dd'))
->add('statusS', 'collection', array(
'label' => false,
'options' => array('label' => false, 'required' => false),
'type' => new DftAbsensiType())
);
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Sifo\AdminBundle\Entity\CollectionAbsensi'
));
}
public function getName()
{
return 'sifo_adminbundle_collectionabsensi';
}
}
This is how to population data in my controller. This form used for EditForm :
<?php
namespace Sifo\AdminBundle\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sifo\AdminBundle\Entity\DftAbsensi;
use Sifo\AdminBundle\Entity\CollectionAbsensi;
use Sifo\AdminBundle\Form\CollectionAbsensiType;
use Sifo\AdminBundle\Form\DftAbsensiType;
/**
* DftAbsensi controller.
*
*/
class DftAbsensiController extends Controller
{
public function manageAction(Request $request, $id)
{
$user = $this->getUser();
$emGrupPelajar = $this->getDoctrine()->getManager();
$entityGrupPelajar = $emGrupPelajar->getRepository('SifoAdminBundle:DftGrupPelajar')->findByIdGrup($id);
/* check tanggal and set if exist */
$tanggal = $request->request->get('sifo_adminbundle_collectionabsensi')['tanggal'];
if($tanggal == NULL)
$tanggal = $request->request->get('form')['tanggal'];
$tanggal = new \DateTime($tanggal);
/* Show data */
$emShow = $this->getDoctrine()->getManager();
$collectionAbsensi = new CollectionAbsensi();
foreach ($entityGrupPelajar as $temp) {
$entity = new DftAbsensi();
$entity = $emShow->getRepository('SifoAdminBundle:DftAbsensi')->findOneBy(array('idGrupPelajar' => $temp, 'tanggal' => $tanggal));
if ($entity)
{
$entityPelajar = $emShow->getRepository('SifoAdminBundle:MstPelajar')->find($temp->getIdPelajar());
$dftAbsensi = new DftAbsensi();
$dftAbsensi->setId($entity->getId())
->setIdGrupPelajar($entity->getIdGrupPelajar())
->setStatus($entity->getStatus())
;
$collectionAbsensi->getStatusS()->add($dftAbsensi);
$collectionAbsensi->setTanggal($tanggal);
}
}
$emShow->flush();
$formEdit = $this->createForm(new CollectionAbsensiType(), $collectionAbsensi, array(
'action' => $this->generateUrl('admin_absensi_update', array('id' => $id)),
'method' => 'PUT',
));
$formEdit->add('save', 'submit', array('attr' => array('class' => 'btn btn-info')));
return $this->render('SifoAdminBundle:DftAbsensi:manage.html.twig', array(
'form_refresh' => $formRefresh->createView(),
'form_edit' => $formEdit->createView(),
'user' => $user,
));
}
As mentioned before, my CollectionAbsensi actually just used for population fields from databases. But for updating I'm using DftAbsensi Entity. There is no table for CollectionAbsensi in my databases. This is how I update the data:
public function updateAction(Request $request, $id)
{
$user = $this->getUser();
$emGrupPelajar = $this->getDoctrine()->getManager();
$entityGrupPelajar = $emGrupPelajar->getRepository('SifoAdminBundle:DftGrupPelajar')->findByIdGrup($id);
/* set tanggal */
$tanggal = new \DateTime($request->request->get('sifo_adminbundle_collectionabsensi')['tanggal']);
/* populate data */
$emShow = $this->getDoctrine()->getManager();
$collectionAbsensi = new CollectionAbsensi();
foreach ($entityGrupPelajar as $temp) {
$entity = new DftAbsensi();
$entity = $emShow->getRepository('SifoAdminBundle:DftAbsensi')->findOneBy(array('idGrupPelajar' => $temp, 'tanggal' => $tanggal));
if ($entity)
{
$entityPelajar = $emShow->getRepository('SifoAdminBundle:MstPelajar')->find($temp->getIdPelajar());
$dftAbsensi = new DftAbsensi();
$dftAbsensi->setId($entity->getId())
->setIdGrupPelajar($entity->getIdGrupPelajar())
->setStatus($entity->getStatus())
;
$collectionAbsensi->getStatusS()->add($dftAbsensi);
$collectionAbsensi->setTanggal($tanggal);
}
}
$formEdit = $this->createForm(new CollectionAbsensiType(), $collectionAbsensi);
$formEdit->handleRequest($request);
$emShow->flush();
$response = $this->forward('SifoAdminBundle:DftAbsensi:manage', array(
'id' => $id,
'request' => $request,
));
return $response;
}
There is no error from this code. The problem is the databases not updated when I press Save button. I confused for binding data and how to update them into database in updateAction above. Can a collection form not be used for updating data?
My form is attendance system which look like this :
Actually this is still not really answer my question about "How to update data in form collection?". I do update my data with old way : Get all the data from request manually and bind it to entity then update it into database.
Here my code :
public function updateAction(Request $request, $id)
{
$user = $this->getUser();
/* get request */
$data = $request->request->get('sifo_adminbundle_collectionabsensi')['statusS'];
/* update data */
$total = count($data);
for ($i = 0; $i < ($total / 2); $i++) {
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('SifoAdminBundle:DftAbsensi')->find($data[$i]['id']);
if ($entity){
$entity->setStatus($data[$i]['status'])
->setOperator($user->getNama());
$em->flush();
}
}
$response = $this->forward('SifoAdminBundle:DftAbsensi:manage', array(
'id' => $id,
'request' => $request,
));
return $response;
}
If someone has a better idea, post your answer here.

Resources