I'm new in php and symfony
I use a file service for the upload in symfony 2.8
I got 2 tables One Salon to many Files
I can upload multiple files in my newaction.
The problem happened at the editAction of my SalonController.
I would like to remove the older files in order to add newfiles in my editfiles.html.twig. And I tried a foreach in order to get this array...
Could you help me please ?
Here is the error
Type error: Argument 1 passed to DefaultBundle\Service\FileService::upload() must be an instance of DefaultBundle\Entity\File, instance of Doctrine\ORM\PersistentCollection given, called in /var/www/html/salon-beaute/src/SalonBundle/Controller/SalonController.php on line 131
And the stack trace focused on the line 18 of the fileservice.php
public function upload(File $file = null, $type) {
Here is the my newaction and editaction of my SalonController
class SalonController extends Controller
{
/**
* Creates a new salon entity.
*
* #Route("/new", name="salon_new")
* #Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$this->denyAccessUnlessGranted('ROLE_SALON');
$em = $this->getDoctrine()->getManager();
$salon = new Salon();
$options = array('role' => $this->getUser()->getRoles(), 'page' => 'add');
$form = $this->createForm( 'SalonBundle\Form\SalonType',$salon, $options);
$user = $this->getUser();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$uploadService = $this->get('app.file');
$myFiles = $form->get('file')->getData();
foreach($myFiles['path'] as $new_file) {
$file = new File();
$file->setPath($new_file);
$file->setSalon($salon);
$salon->addFile($file);
$uploadService->upload($file, 'salon');
$em->persist($file);
}
$user->setSalon($salon);
$salon->setEnable(false);
$em->persist($user);
$em->persist($salon);
$em->flush();
$this->get('email')->salon($salon);
return $this->redirectToRoute('salon_show', array('id' => $salon->getId()));
}
/**
* Displays a form to edit an existing salon entity.
*
* #Route("/edit", name="salon_edit")
* #Method({"GET", "POST"})
* #Security("has_role('ROLE_SALON')")
*/
public function editAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$salon = $user->getSalon();
$deleteForm = $this->createDeleteForm($salon);
$options = array('role' => $this->getUser()->getRoles(), 'page' => 'edit');
$editForm = $this->createForm('SalonBundle\Form\SalonType', $salon, $options);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
// If new file
$edit_file = $editForm->get('edit_file')->getData();
if (!is_null($edit_file)) {
$file_current = $salon->getFiles();
$salon->getFiles($edit_file);
if (!$this->get('app.file')->upload($salon->getFiles(), 'salon'))
$salon->getFiles($file_current);
}
foreach($edit_file['path'] as $new_edit_file) {
$file = new File();
$file->setPath($new_edit_file);
$file->setSalon($salon);
$salon->addFile($file);
$this->get('app.file')->upload($file);
$em->persist($file);
}
$this->getDoctrine()->getManager()->flush();
$this->addFlash('success', 'Le partenaire a bien été modifié');
return $this->redirectToRoute('salon_show');
}
return $this->render('#Salon/salon/edit.html.twig', array(
'salon' => $salon,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
return $this->render('#Salon/salon/new.html.twig', array(
'salon' => $salon,
'form' => $form->createView(),
));
}
A portion of my SalonType
class SalonType extends AbstractType
{
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$page = $options['page'];
$builder
->add('name', TextType::class, array(
'label' => 'Nom du salon'
))
->add('content', TextareaType::class, array(
'label' => 'Descriptif'
))
->add('address_salon', AddressType::class, array(
'label' => ' '
))
;
if($page == 'add') {
$builder
->add('file', FileType::class, array(
'label' => 'Vous pouvez téléchargez jusqu\'à 3 images',
'required' => false,
'mapped' =>false,
));
}
if($page == 'edit') {
$builder
->add('edit_file', FileType::class, array(
'label' => 'Nouveau fichier',
'required' => false,
'mapped' => false
));
};
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'SalonBundle\Entity\Salon',
'role' => null
));
$resolver
->setRequired(['page']);
}
My fileType
class FileType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('path', \Symfony\Component\Form\Extension\Core\Type\FileType::class, array(
'label' => 'Image',
'multiple' => true,
))
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => null,
));
}
}
My fileService
<?php
namespace DefaultBundle\Service;
use DefaultBundle\Entity\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileService {
private $directory_root;
private $directory_default;
public function __construct($directory_root, $directory_default) {
$this->directory_root = $directory_root;
$this->directory_default = $directory_default;
}
public function upload(File $file = null, $type) {
$path = $this->getDirectory($type);
if (is_null($file))
return false;
// Get file (Class UploadFile)
$file_uploaded = $file->getPath();
if ($file_uploaded->getError())
return false;
// Move file
$file_name = md5(uniqid()) . '.' . $file_uploaded->guessExtension();
$file_uploaded->move($this->directory_root . $path, $file_name);
// Update object file
$path .= '/' . $file_name;
$file->update($file_uploaded, $path);
return true;
}
public function delete(File $file){
$path = $this->directory_root.$file->getPath();
if(file_exists($path))
unlink($path);
}
private function getDirectory($type) {
switch ($type) {
default:
return $this->directory_default;
}
}
}
Your code is kinda messy, by that I mean you have lot of logic in your controller :-)
Just to know which line is the 131 in your controller?
You have an error here (don't know if it's the 131 line)
if (!$this->get('app.file')->upload($salon->getFiles(), 'salon'))
Here you send a collection to upload(), you said it yourself
One Salon to many Files
BUT before trying to hotfix this look at is tutorial here on how to handle multiple file upload.
Also this tutorial has the full demo source code available. The code is quite clear and you should be able to understand it easily.
Edit
If you don't want to rewrite your code you may want to hotfix your code like that
if (!is_null($edit_file)) {
$file_current = $salon->getFiles();
//$salon->getFiles($edit_file); What is the goal of this?
foreach ($salon->getFiles() as $file) {
// Note that now we send a single File object not a collection
if (!$this->get('app.file')->upload($file, 'salon')) {
$salon->setFiles($file_current); // You want to set the files no?
break;
}
}
}
This is 200% ugly, and I'm not even sure if it will work. You should really think about refactoring your code.
Edit 2
The problem you have now is that you are mixing your File object and the UploadedFile object from symfony.
You do $file_uploaded = $file->getPath(); then you have the error
Call to a member function getError() on string
and it's normal because getPath() return a string.
I assume you have look the Uploader Service of the symfony doc. You can see they pass an UploadedFile object which is part of the symfony package, not a custom entity.
If I wanted to do a quick fix, which is definitely not what I recommend, I'll do something like this
// Your controller (newAction)
foreach($myFiles['path'] as $new_file) {
// $new_file is an uploadedFile object, this is the file you want to upload
$file = new File();
$file->setPath($new_file);
$file->setSalon($salon);
$salon->addFile($file);
$uploadService->upload($file, $new_file, 'salon');
$em->persist($file);
}
// Your FileService
public function upload(File $file = null, UploadedFile $file_uploaded = null, $type) {
$path = $this->getDirectory($type);
if (is_null($file_uploaded) || is_null($file))
return false;
// Get file (Class UploadFile), No here you get the file path => a string
//$file_uploaded = $file->getPath();
if ($file_uploaded->getError())
return false;
//... end of your method
}
Related
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);
}
}
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.
I read several solutions for this error but it's not working, i dont know exactly where is the problem, because other get request works
my formType is as follows:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image', null, array('property_path' => 'file'))
->add('tags', null, array('mapped' => false))
->add('machinetags', null, array('mapped' => false));
}
and function of controller is as follows:
/**
* #ApiDoc(description="Associate photo with tags.")
*
* #ParamConverter("photo", class="TestTaskPhotosBundle:Photo")
*
* #Rest\Post("/photos/{id}/tags")
* #Rest\RequestParam(name="tags", requirements=".+", nullable=false, map=true, description="Tags that associates photo.")
* #Rest\View()
*/
public function postTagsToPhotoAction(Photo $photo, array $tags)
{
$em = $this->getDoctrine()->getManager();
//TODO: add validation and maybe form
if ($tags) {
$tags = $em->getRepository('TestTaskTagsBundle:Tag')->findOrCreateByTitles($tags);
}
foreach ($tags as $tag) {
$photo->addTag($tag);
}
$em->persist($photo);
$em->flush();
return array('photo' => $photo);
}
solved, the problem was in cotroller function, the solution is as follows:
public function postMachinetagsToPhotoAction($id, array $machinetags)
{
$em = $this->getDoctrine()->getManager();
//TODO: add validation and maybe form
$photo = $em->getRepository('TestTaskPhotosBundle:Photo')->find($id);
if ($machinetags) {
$machinetags = $em->getRepository('TestTaskMachineTagsBundle:MachineTag')->findOrCreateByTitles($machinetags);
}
foreach ($machinetags as $machinetag) {
$photo->addMachineTag($machinetag);
}
$em->persist($photo);
$em->flush();
return array('photo' => $photo);
}
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.
I create a embedded form. How can I label in ItemType.php with the name from the db?
1.) Like:
$builder->add('id', 'checkbox', array('label'=> $v->getName(),...
2.) By the way symfony2 renders for each ItemType.php a Number 0,1,2. How can I get rid of it?
My action:
$task = new UserFriends();
foreach ($fb_friends as $k => $v) {
$name = $v->getName();
$friend_id = $v->getFriendId();
$id = $v->getId();
$t = new Item();
$t->name = $name;
$t->friendId = $friend_id;
$t->id = $id;
$task->getId()->add($t);
}
$form = $this->createForm(new CreateRequest(), $task, array());
Part of CreateRequest.php-form:
$builder->add('id', 'collection', array('type' => new ItemType(),
Part of my ItemType.php
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('id', 'checkbox', array('label'=> 'Name', 'required' => false, 'mapped' => false));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Frontend\ChancesBundle\Entity\Item',
));
}
public function getName()
{
return 'item';
}
And Part of my Item.php-Entity
class Item
{
public $id;
public $friendId;
public $name;
public function getFriendId()
{
return $this->friendId;
}
You can pass an entity manager to your form and select whatever you want from the database.
In your controller (or whereever you are calling the form):
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new MyFormType($blabla), $blabla, array('em' => $em));
In your form type:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$somethingFromDb = $options['em']->findByName('someName');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array(
'em',
));
$resolver->setAllowedTypes(array(
'em' => 'Doctrine\Common\Persistence\ObjectManager',
));
}