Symfony2: optimize collection of forms - forms

In a controller of a Symfony2 application, I use collection of elements. The more elements there are, the more time it takes. It sounds logical but it seems that there are repeated traitments:
I create a form from MyCollectionType
in the buildForm method, I add the ElementType that has its own buildForm method.
Then when the form is built by Symfony2 with the list of elements I pass, the buildForm method of the ElementType is called one time for each element
=> is this not possible that the first ELementType is built, then other are cloned?
I don't see why there would be any different there between these subforms, the only difference will appear setting the data and not building the form.
Then I notice the same for the buildView method: there are a lot of repeated processing for each element, where only the data (possibly processing of listeners) may vary.
For example, in my application, with a ElementType having 6 fields, and a collection of 700 elements, it takes up to 30s to render the form.
Is it due to the way that forms are handled, or can be be optimized ?

I add the same problem for one of my application, what I did is that I reimplemented a basic form class prototype, the method names are almost the same that the Symfony2 ones and reimplemented in the most simple way, It looks like this:
class SimpleForm
{
/**
* #var ContainerInterface $container Main application DIC
*/
protected $container;
/**
* #var array $options Options of the form
*/
protected $options = array();
/**
* #var array $options Raw datas for the form.
*/
protected $data = array();
/**
* #var array $options Data of the form against user input.
*/
protected $boundData = array();
/**
* #var array $errors List of errors after form valisation
*/
protected $errors = array();
/**
* #var array $options Tells if the datas were bound to the form.
*/
protected $isBound = false;
/**
* #var array $options Tells if the form validation is ok
*/
protected $isValid = false;
/**
* Main constructor.
*
* #param ContainerInterface $container The main DIC
* #param array $options Options of the form
*/
public function __construct(ContainerInterface $container, $options = array())
{
$this->container = $container;
$this->options = $options;
$this->buildForm();
}
/**
* Add widgets to the form.
*/
public function buildForm()
{
$this->widgets['keywordType'] = self::$keywordTypes;
}
/**
* #return array
*/
public function getOptions()
{
return $this->options;
}
/**
* #param array $options
*/
public function setOptions($options)
{
$this->options = $options;
}
/**
* #return string
*/
public function getEnctype()
{
return isset($this->options['enctype']) ? $this->options['enctype'] : '';
}
/**
* If the form is bound it return the bound datas, it returns the raws datas otherwise.
*
* #return array
*/
public function getData()
{
return $this->isBound ? $this->boundData : $this->data;
}
/**
* #throws \LogicException
*
* #return array
*/
public function getErrors()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before the errors can be retrieved');
}
return $this->errors;
}
/**
* #throws \LogicException
*
* #return array
*/
public function hasErrors()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before the errors can be checked');
}
return !empty($this->errors);
}
/**
* #throws \LogicException
*
* #return array
*/
public function getBoundData()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before getting the form final datas');
}
return $this->boundData;
}
/**
* #param array $data
*
* #return SimpleForm
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Bind the submitted values to the form.
*
* #param array $values The values to bind
*
* #return SimpleForm
*/
public function bind($values)
{
$values = $this->clean($values);
$this->boundData = Tools::arrayDeepMerge($this->data, $values);
$this->isBound = true;
$this->validate();
return $this;
}
/**
* Clean raw form values before the validation.
*
* #param array $values The raw values submitted by the user.
*
* #return array
*/
protected function clean($values)
{
// ...
return $values;
}
/**
* Run the validation against the form.
*
* #return boolean
*/
protected function validate()
{
$this->errors = array();
// ...
$this->isValid = empty($this->errors);
return $this->isValid;
}
/**
* Return the validation state of the form.
*
* #throws \LogicException
*
* #return boolean
*/
public function isValid()
{
if ($this->isBound == false) {
throw new \LogicException('The form must be bound before getting the validation status');
}
return $this->isValid;
}
/**
* Returns the datas that will be necesary for the view.
*
* #return array
*/
public function createView()
{
return array(
'widgets' => $this->widgets,
'options' => $this->options,
'data' => $this->boundData, // Don't forget to escape values against XSS
'enctype' => $this->getEnctype(),
'errors' => $this->errors,
'name' => $this->getName(),
);
}
/**
* #return string The name of the form
*/
public function getName()
{
return 'search';
}
}
In the Twig templates, I just iterate the data to create the form fields, repopulate values and to display the errors. The form is the same but is generated in 100ms instead of 30 seconds... For all the other forms I kept on using the Symfony2 ones.

The answer is simple: You should optimize yours programming skills instead of symfony forms. This is yours next question (of many) about the same issue.
You want to render over 4200 fields with fieldsets and/or divs around each input, so I suspect that 30 second it's the time in which it renders in the browser.

Related

TYPO3 TCA own evaluation (validation) for a combination of three fields

I read the documentation on the eval property for type=input and tried my own evaluations.
It should evaluate a combination of three fields with this logic:
start_date AND end_date required (not empty) OR date_on_request required.
Class is loaded and function evaluateFieldValue() works, but I miss the feedback in form.
<?php
namespace Vendor\Extension\Evaluation;
class StartDateAndEndDateOrDateOnRequestEvaluation {
/**
* JavaScript code for client side validation/evaluation
*
* #return string JavaScript code for client side validation/evaluation
*/
public function returnFieldJS() {
return 'return value;';
}
/**
* Server-side validation/evaluation on saving the record
*
* #param string $value The field value to be evaluated
* #param string $is_in The "is_in" value of the field configuration from TCA
* #param bool $set Boolean defining if the value is written to the database or not.
* #return string Evaluated field value
*/
public function evaluateFieldValue($value, $is_in, &$set) {
foreach($_POST['data']['tx_extension_domain_model_course'] as $id => $course) {
if ( (!empty($course['start_date']) && !empty($course['start_date'])) || !empty($course['date_on_request']) ) {
$set = true;
} else {
$set = false;
}
}
return $value;
}
/**
* Server-side validation/evaluation on opening the record
*
* #param array $parameters Array with key 'value' containing the field value from the database
* #return string Evaluated field value
*/
public function deevaluateFieldValue(array $parameters) {
return $parameters['value'];
}
}
Im looking for examples, how I can do validation in JavaScript (returnFieldJS):
How I get the three fields?
How can set error classes?
And what should I check in evaluateFieldValue()?
The methods returnFieldJS() and deevaluateFieldValue(array $parameters) are not called for datetime fields. That is why I guess there is no clean way to add JavaScript validation to datetime fields.
To get an error message in the backend you can however use the FlashMessageService. I implemented an example to check that the course_end date is after the course_start date:
<?php
namespace Vendor\Extension\Evaluation;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
class StartDateAndEndDateOrDateOnRequestEvaluation {
/**
* JavaScript code for client side validation/evaluation
*
* #return string JavaScript code for client side validation/evaluation
*/
public function returnFieldJS()
{
return 'return value;';
}
/**
* Server-side validation/evaluation on saving the record
*
* #param string $value The field value to be evaluated
* #param string $is_in The "is_in" value of the field configuration from TCA
* #param bool $set Boolean defining if the value is written to the database or not.
* #return string Evaluated field value
*/
public function evaluateFieldValue($value, $is_in, &$set)
{
$formData = GeneralUtility::_GP('data');
$courseId = key($formData['tx_extension_domain_model_course']);
$course = $formData['tx_extension_domain_model_course'][$courseId];
$courseStart = new \DateTime($course['course_start']);
$courseEnd = new \DateTime($course['course_end']);
if ($courseStart > $courseEnd) {
$this->flashMessage('Invalid field value', 'Course end date can not be before course start date!', FlashMessage::ERROR);
$set = false; //do not save value
}
return $value;
}
/**
* Server-side validation/evaluation on opening the record
*
* #param array $parameters Array with key 'value' containing the field value from the database
* #return string Evaluated field value
*/
public function deevaluateFieldValue(array $parameters)
{
return $parameters['value'];
}
/**
* #param string $messageTitle
* #param string $messageText
* #param int $severity
*/
protected function flashMessage($messageTitle, $messageText, $severity = FlashMessage::ERROR)
{
$message = GeneralUtility::makeInstance(
FlashMessage::class,
$messageText,
$messageTitle,
$severity,
true
);
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$flashMessageService = $objectManager->get(FlashMessageService::class);
$messageQueue = $flashMessageService->getMessageQueueByIdentifier();
$messageQueue->addMessage($message);
}
}

hydrate multiple objects zf2

I need to hyrdate multiple objests in one form. Here is what I use:
Product Form - I have a form where I call three fieldsets
Product Fieldset
Promotion Fieldset
Category Fieldset
I have Models for all the necessary tables, here is an example for the product model:
class Product implements ProductInterface
{
/**
* #var int
*/
protected $Id;
/**
* #var string
*/
protected $Title;
/**
* #var float
*/
protected $Price;
/**
* #var string
*/
protected $Description;
/**
* #var string
*/
protected $Url;
/**
* #var \DateTime
*/
protected $DateAdded;
/**
* #var string
*/
protected $Image;
/**
* #var int
*/
protected $Status;
/**
* #return int
*/
public function getId()
{
return $this->Id;
}
/**
* #param int $Id
*/
public function setId($Id)
{
$this->Id = $Id;
}
/**
* #return string
*/
public function getTitle()
{
return $this->Title;
}
/**
* #param string $Title
*/
public function setTitle($Title)
{
$this->Title = $Title;
}
/**
* #return float
*/
public function getPrice()
{
return $this->Price;
}
/**
* #param float $Price
*/
public function setPrice($Price)
{
$this->Price = $Price;
}
/**
* #return string
*/
public function getDescription()
{
return $this->Description;
}
/**
* #param string $Description
*/
public function setDescription($Description)
{
$this->Description = $Description;
}
/**
* #return string
*/
public function getUrl()
{
return $this->Url;
}
/**
* #param string $Url
*/
public function setUrl($Url)
{
$this->Url = $Url;
}
/**
* #return \DateTime
*/
public function getDateAdded()
{
return $this->DateAdded;
}
/**
* #param \DateTime $DateAdded
*/
public function setDateAdded($DateAdded)
{
$this->DateAdded = $DateAdded;
}
/**
* #return string
*/
public function getImage()
{
return $this->Image;
}
/**
* #param string $Image
*/
public function setImage($Image)
{
$this->Image = $Image;
}
/**
* #return int
*/
public function getStatus()
{
return $this->Status;
}
/**
* #param int $Status
*/
public function setStatus($Status)
{
$this->Status = $Status;
}
In my controllers I want to bind the data to my view so I can edit them.
try {
$aProduct = $this->productService->findProduct($iId);
} catch (\Exception $ex) {
// ...
}
$form = new ProductForm();
$form->bind($aProduct);
In the first place I need to select all the necessary information from the DB. I join three tables product, promotion and category tables. I must return the data to my controller as objects and bind them in my form to be able to edit on the view page.
Please give me some ideas how to accomplish this so I can continue with my development. I am stuck.
I will appreciate all the links which can help me or give me any ideas/examples from the real life.
public function findProduct($Id)
{
$iId = (int) $Id;
$sql = new Sql($this->dbAdapter);
$select = $sql->select('product');
$select->join('promotion', 'promotion.ProductId = product.Id', array('Discount', 'StartDate', 'EndDate', 'PromotionDescription' => 'Description', 'PromotionStatus', 'Type'), 'left');
$select->join('producttocategory', 'producttocategory.ProductId = product.Id', array('CategoryId'), 'left');
$select->join('category', 'category.Id = producttocategory.CategoryId', array('ParentId', 'Title', 'Description', 'Url', 'DateAdded', 'Image', 'Status'), 'left');
$where = new Where();
$where->equalTo('product.Id', $iId);
$select->where($where);
$stmt = $sql->prepareStatementForSqlObject($select);
$result = $stmt->execute();
if ($result instanceof ResultInterface && $result->isQueryResult()) {
$resultSet = new HydratingResultSet($this->hydrator, $this->productPrototype);
return $resultSet->initialize($result);
}
throw new \Exception("Could not find row $Id");
}
I need to hydrate the result and return an object which I will use in the controller to bind the form.
You can to fill entities from a database manually.
If you want to fill automatically need to create a map between a database and entities. I made a library for making a map between DB and entities use annotations in entities https://github.com/newage/annotations.
Next step.
When you get different data from tables. Example:
SELECT
table1.id AS table1.id,
table1.title AS table1.title,
table2.id AS table2.id,
table2.alias AS table2.alias
FROM table1
JOIN table2 ON table1.id = table2.id
Need do foreach by rows and set data to entities comparing row with table name and Entity from a generated map.
Auto generating tree of entities from DB is my next project.
But it's do not finished. https://github.com/newage/zf2-simple-orm.

Symfony2, field type entity, "many-to-many" relation with extra fields, problems with the relation/ArrayCollection/multipe checkboxes in form

I want to create a form for a simple entry management.
I got the entities Entry, EntryUser, and User.
Tables in database: entry, entry_user and user.
I think i am close to be successful, but i got some problems here.
In my form, the author can check the users he want to add to the entry via checkboxes. Symfony/Doctrine should do the relation work for me and add rows into entry_user. One row for one selected checkbox.
Entry.php
/**
* #ORM\Entity
* #ORM\Table(name="entry")
*/
class Entry {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="EntryUser", mappedBy="entry", cascade={"all"}, orphanRemoval=true)
*/
protected $users;
function __construct() {
$this->users = new ArrayCollection();
}
/**
* Add user
*
* #param User $user
* #return $this
*
*/
public function addUser(User $user)
{
if (!$this->users->contains($user)) {
$this->users->add($user);
}
return $this;
}
/**
* Remove user
*
* #param User $user
* #return $this
*/
public function removeUser(User $user)
{
if ($this->users->contains($user)) {
$this->users->removeElement($user);
}
return $this;
}
/**
* #return array
*/
public function getUsers()
{
return $this->users->toArray();
}
/**
* Returns the true ArrayCollection of Users.
* #return Doctrine\Common\Collections\ArrayCollection
*/
public function getUsersCollection()
{
return $this->users;
}
}
User.php
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User implements AdvancedUserInterface, EquatableInterface, \Serializable {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
protected $name;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
* #return User
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
// Many other methods for user sign in, roles and so on...
}
EntryUser.php
/**
* #ORM\Entity
* #ORM\Table(name="entry_user")
*/
class EntryUser {
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var integer
*
* #ORM\Column(name="user_id", type="integer", nullable=true)
*/
protected $user_id;
/**
* #var integer
*
* #ORM\Column(name="entry_id", type="integer", nullable=true)
*/
protected $entry_id;
/**
* #var User
*
* #ORM\ManyToOne(targetEntity="User", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $user;
/**
* #var Entry
*
* #ORM\ManyToOne(targetEntity="Entry", inversedBy="users")
* #ORM\JoinColumn(name="entry_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected $entry;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set user_id
*
* #param integer $userId
* #return EntryUser
*/
public function setUserId($userId)
{
$this->user_id = $userId;
return $this;
}
/**
* Get user_id
*
* #return integer
*/
public function getUserId()
{
return $this->user_id;
}
/**
* Set entry_id
*
* #param integer $entryId
* #return EntryUser
*/
public function setEntryId($entryId)
{
$this->entry_id = $entryId;
return $this;
}
/**
* Get entry_id
*
* #return integer
*/
public function getEntryId()
{
return $this->entry_id;
}
/**
* Set user
*
* #param User $user
* #return EntryUser
*/
public function setUser(User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* #return User
*/
public function getUser()
{
return $this->user;
}
/**
* Set entry
*
* #param Entry $entry
* #return EntryUser
*/
public function setEntry(Entry $entry = null)
{
$this->entry = $entry;
return $this;
}
/**
* Get entry
*
* #return Entry
*/
public function getEntry()
{
return $this->entry;
}
}
I use ManyToOne relationships here because i want to use a file named EntryUser.php to add some custom fields later. I need this because i must store some additional data there in entry_user.
Because:
And it's the right thing to do. Create a new entity with the new fields, and if you need it, create a custom repository to add the methods you need.
A <--- Many to many with field ---> B
would become
A --One to many--> C (with new fields) <-- One to many--B
and of course, C has ManyToOne relationships with both A and B.
See the comments in: ManyToMany relationship with extra fields in symfony2 orm doctrine
My EntryType.php form definition includes the following, to create the checkboxes for the template:
$builder->add('users', 'entity', array(
'class' => 'MyCompMyAppBundle:User',
'multiple' => true,
'expanded' => true,
'property' => 'name',
'label' => 'Freunde',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('u')->select('a')
->from('MyComp\MyAppBundle\Entity\User', 'a')
->where('EXISTS (
SELECT b
FROM MyComp\MyAppBundle\Entity\UserFriend b
WHERE b.created_by = :my_user_id
AND b.friend_user_id = a.id
)')
->andWhere('EXISTS (
SELECT c
FROM MyComp\MyAppBundle\Entity\UserFriend c
WHERE c.created_by = a.id
AND c.friend_user_id = :my_user_id
)')
->setParameter('my_user_id', $this->user->getId());
},
'required' => true,
));
As you can see, i load User objects here for the form field (type: entity).
UserFriend is another entity (table: user_friend). A friend list is saved there. Here all the friends gets loaded. They will be shows as the checkboxes.
Now, if i go to my form in my browser, and check some users for the entry und if i submit the form, i get this error:
ORMException: Found entity of type MyComp\MyAppBundle\Entity\User on association MyComp\MyAppBundle\Entity\Entry#friends, but expecting MyComp\MyAppBundle\Entity\EntryUser
So it is very confusing.
How can i make this work?
How can i make symfony and doctrine work to insert data automatically into entry and entry_user?
Important: I want to make it possible that the author can edit the entry later. So the checkboxes should be selected by default as it is saved in entry_user.
I just try to understand this and got a little bit confused. But i dont know how to make this work.
I found an awesome solution in the web. I was searching for many days now, but this guy made my day! :-)
You can read how it works and learn from an awesome example here!
Happy coding!
For this case you should check "form collections" in Symfony: http://symfony.com/doc/current/cookbook/form/form_collections.html
With this technique you will add a form type to crate a single "EntryUser" and after that you can add a collection of that form to the parent form. Quite easy and well explained in the liked article.

Doctrine Embeddables not working with Symfony forms

Has anyone encountered this problem when using doctrine embeddables and symfony forms?
if you don't know Doctrine Embeddables are, you can read about it here
http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.html
When using value object (CategoryType in my case) with symfony form on form submission (during persisting to DB) I get the following warning
Warning: ReflectionProperty::getValue() expects parameter 1 to be object, string given
This happens because symfony form returns string instead of embeddable object.
The only workaround I have right now is to use mapped => false on type field and create valid embeddable object inside controller action just before persist. But that's far from "nice" solution and I want to avoid that.
My Entity, Value Object and form (simplified for the sake of question)
Foo\BarBundle\Entity\CategoryType
<?php
namespace Foo\BarBundle\Entity;
class CategoryType
{
/**
* #var string
*/
protected $value;
public function __toString()
{
return (string) $this->getValue();
}
/**
* #return string
*/
public function getValue()
{
return $this->value;
}
/**
* #param string $value
*
* #return $this
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
}
Foo\BarBundle\Resources\config\doctrine\CategoryType.orm.yml
CategoryType.orm.yml
Foo\BarBundle\Entity\CategoryType:
type: embeddable
fields:
value:
type: string
Foo\BarBundle\Entity\Category
<?php
namespace Foo\BarBundle\Entity;
class Category
{
/**
* #var integer
*/
protected $id;
/**
* #var string
*/
protected $name;
/**
* #var CategoryType
*/
protected $type;
/**
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* #return \Foo\BarBundle\Entity\CategoryType
*/
public function getType()
{
return $this->type;
}
/**
* #param \Foo\BarBundle\Entity\CategoryType $type
*
* #return $this
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* #return string
*/
public function __toString()
{
return (string) $this->getName();
}
/**
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* #param string $name
*
* #return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}
Foo\BarBundle\Resources\config\doctrine\Category.orm.yml
Foo\BarBundle\Entity\Category:
type: entity
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
name:
type: string
embedded:
type:
class: CategoryType
Foo\BarBundle\Form\CategoryType
<?php
namespace Foo\BarBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class CategoryType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('type')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'Foo\BarBundle\Entity\Category'
)
);
}
/**
* #return string
*/
public function getName()
{
return 'category_form';
}
}
The doctrine embedabble behavior is just a persistence mechanism, so, it can not break the form component which is independant from it (and works with all objects graph).
The issue is your form is not well designed (it does not follow your object graph). Here, you have a category which wraps a category type. So, your form must follow the same structure at the definition level.
You must create a CategoryTypeType form (mapped to your CategoryType class) where your add a value field. Then, in your CategoryType (the form one), you must embed the CategoryTypeType for the type field.
Then, the form component will automatically creates a Category which wraps a CategoryType. Then, Doctrine will simply persists your object as embeddable and everything will work :)

default value for entity widget in a formbuilder

I have seen a lot of topics concerning how to set default data on a form in Symfony2, but I didn't find anything about how to set default data in an entity widget with a query builder. I explain my problem :
I have two entities, communication and Status, with a relation ManyToOne.
Here is my Communication class :
class Communication{
/**
* #ORM\Id
* #ORM\Column(name="Comm_CommunicationId")
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Test\DatabaseBundle\Entity\Statut", inversedBy="communication")
* #ORM\JoinColumn(name="Comm_Status", referencedColumnName="Capt_Code")
*/
private $statut;}
And here is my Status class:
class Statut{
/**
* #ORM\Id
* #ORM\Column(name="Capt_CaptionId")
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #ORM\Column(name="Capt_Code", type="string")
*/
private $code;
/**
* #ORM\Column(name="Capt_FR", type="string")
*/
private $codefr;}
I have built a CommunicationType form to allow me to modify a communication entity:
public function buildForm(FormBuilder $builder, array $options)
{
$builder -> add('caseid','text')
-> add('statut','entity', array('class' => 'Test\DatabaseBundle\Entity\Statut',
'query_builder' => function(\Test\DatabaseBundle\Entity\StatutRepository $sr){
$res = $sr->getCodeOnly();
return $res; },
'property' => 'CodeFr',
'preferred_choices' => array(1),
));}
Here is my controller:
public function ModifierAction($commid){
$comm = $this -> getDoctrine()
-> getEntityManager()
-> getRepository('Test\DatabaseBundle\Entity\Communication')
-> find($commid);
$form = $this -> createForm(new CommunicationType($em), $comm);
....
}
I give you the setter and the getter of my entities :
communication :
/**
* Set id
*
* #param integer $Id
*/
public function setId($Id)
{
$this -> id = $Id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
Status entity :
/**
* Set id
*
* #param integer $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
} /**
* Set code
*
* #param string $code
*/
public function setCode($code)
{
$this->code = $code;
}
/**
* Get code
*
* #return string
*/
public function getCode()
{
return $this->code;
} /**
* Add communication
*
* #param Acme\StoreBundle\Entity\Communication $communication
*/
public function addCommunication(\Test\DatabaseBundle\Entity\Communication $communication)
{
$this->communication[] = $communication;
}
/**
* Get communication
*
* #return Doctrine\Common\Collections\Collection
*/
public function getCommunication()
{
return $this->ccommunication;
} public function __construct()
{
$this->communication = new ArrayCollection();
}
you said doctrine automatically check the object. Do you that , normally, doctrine execute the query and search, in the database, the current value of the object and pass it as the default choice?
With this I can modify my entity, but I don't know how to put my current entity Status value as the default value for the widget "entity". The method "getCodeOnly" search in the database the value of the attibut code of status (Complete, Cancelled, InProgress, Deleted) and always passed Complete as the default value. For exemple, if an entity as the value Cancelled, I want to put Cancelled as the default value when I use this form to modify my entity.
I cannot use getData and preferred_choice to have access to the status value because preferred_choice needs an array as parameter and not an entity.
I also tried to build an array with the different values of status and passed it to my form but du to several problem with my database, it failed.
If anyone have any infomation to solve this problem, i would be happy to see it.