I have a ManyToMany that I broke into OneToMany and ManyToOne relationship. I want to build a form that has checkboxes instead of collection, and I am using the 'DoctrineObject' hydrator, but it does not work and I don't know what is going wrong.
I removed from my code below all of the other not related fields.
Role Entity:
/**
* #orm\Entity
* #orm\Table(name="roles")
*/
class RolesEntity extends HemisEntity {
/**
* #orm\Id
* #orm\Column(type="integer");
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #orm\Column(name="role_code",type="string")
*/
protected $roleCode;
/**
* #orm\OneToMany(targetEntity="RolesPermissionsEntity", mappedBy="role", cascade={"persist"})
*/
protected $rolePermissions;
public function __construct()
{
$this->rolePermissions = new ArrayCollection();
}
public function setRolePermissions($rolePermissions)
{
$this->rolePermissions = $rolePermissions;
return $this;
}
public function addRolePermissions(Collection $rolePermissions)
{
foreach ($rolePermissions as $rolePermission) {
$rolePermission->setRole($this);
$this->rolePermissions->add($rolePermission);
}
}
public function removeRolePermissions(Collection $rolePermissions)
{
foreach ($rolePermissions as $rolePermission) {
$rolePermission->setRole(null);
$this->rolePermissions->removeElement($rolePermission);
}
}
public function getRolePermissions()
{
return $this->rolePermissions;
}
}
The ManyToMany table entity (it has more fields and so I broke it):
/**
* #orm\Entity
* #orm\Table(name="roles_permissions")
*/
class RolesPermissionsEntity extends HemisEntity {
/**
* #orm\Id
* #orm\Column(type="integer");
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #orm\ManyToOne(targetEntity="RolesEntity", inversedBy="rolePermissions")
* #orm\JoinColumn(name="role_id", referencedColumnName="id")
**/
protected $role;
/**
* #orm\ManyToOne(targetEntity="PermissionsEntity", inversedBy="permissionRoles")
* #orm\JoinColumn(name="permission_id", referencedColumnName="id")
**/
protected $permission;
public function setRole($role)
{
$this->role = $role;
return $this;
}
public function getRole()
{
return $this->role;
}
public function setPermission($permission)
{
$this->permission = $permission;
return $this;
}
public function getPermission()
{
return $this->permission;
}
}
My form look like this:
class RoleForm extends Form implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('role');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new RolesEntity());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'roleCode',
'options' => array(
'label' => 'Role Code'
),
));
$this->add(array(
'name' => 'rolePermissions',
'type' => 'DoctrineModule\Form\Element\ObjectMultiCheckbox',
'options' => array(
'label' => 'Permissions',
'object_manager' => $objectManager,
'target_class' => 'Hemis\Fnd\PermissionsEntity',
'property' => 'permissionDesc'
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Submit',
),
));
}
public function getInputFilterSpecification()
{
return array(
'roleCode' => array(
'required' => false
),
'rolePermissions' => array(
'required' => true
)
);
}
}
The problem is that when I dump the $role it does not contains any rolePermissions and even that they are passed from the form they are just not hydrated into the object. I hope that my question is clear.
Any idea about what is wrong with my code or there is a better way to do that using checkboxes?
class RoleForm extends Form implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
// ...
$this->add(array(
'name' => 'rolePermissions',
'type' => 'Zend\Form\Element\Collection',
'options' => array(
'label' => 'Role Permissions',
'count' => 0,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Zend\Form\Fieldset',
'options' => array(
'use_as_base_fieldset' => true
),
'elements' => array(
// add form fields for the properties of the RolesPermissionsEntity class here
array(
'name' => 'id',
'type' => 'Zend\Form\Element\Hidden',
),
array(
'name' => 'role',
'type' => 'Zend\Form\Element\Checkbox',
// other options
),
// ...
),
),
),
));
// ...
}
// ...
}
Related
i'm trying to insert data to database but submitted forms does nothing.
this is my service manager:
class AutosManager
{
/**
* Entity manager.
* #var Doctrine\ORM\EntityManager;
*/
private $entityManager;
/**
* Constructor.
*/
public function __construct($entityManager)
{
$this->entityManager = $entityManager;
}
public function addNewAutos($data)
{
$autos = new Autos();
$autos->setTitle($data['title']);
$autos->setDescription($data['description']);
$currentDate = date('Y-m-d H:i:s');
$autos->setDateCreated($currentDate);
$this->entityManager->persist($autos);
$this->entityManager->flush();
}
this is my controller addAction
public function addAction()
{
// Create the form.
$form = new PostForm();
if ($this->getRequest()->isPost()) {
// Get POST data.
$data = $this->params()->fromPost();
// Fill form with data.
$form->setData($data);
if ($form->isValid()) {
// Get validated form data.
$data = $form->getData();
$this->AutosManager->addNewAutos($data);
return $this->redirect()->toRoute('retrieve');
}
}
return new ViewModel([
'form' => $form
]);
}
i can retrieve data from database to the index page but i cannot add. hope to find the solution.
this is my Autos Entity
namespace Retrieve\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #ORM\Entity(repositoryClass="\Retrieve\Repository\AutosRepository")
* #ORM\Table(name="auto")
*/
class Autos
{
/**
* #ORM\Id
* #ORM\Column(name="id")
* #ORM\GeneratedValue
*/
protected $id;
/**
* #ORM\Column(name="title")
*/
protected $title;
/**
* #ORM\Column(name="description")
*/
protected $description;
/**
* #ORM\Column(name="featured")
*/
protected $featured;
/**
* #ORM\Column(name="date_created")
*/
protected $dateCreated;
/**
* Returns ID of this post.
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Sets ID of this post.
* #param int $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Returns title.
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Sets title.
* #param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* Returns featured.
* #return integer
*/
public function getFeatured()
{
return $this->featured;
}
/**
* Sets featured.
* #param integer $featured
*/
public function setFeatured($featured)
{
$this->featured = $featured;
}
/**
* Returns post description.
*/
public function getDescription()
{
return $this->description;
}
/**
* Sets post description.
* #param type $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Returns the date when this post was created.
* #return string
*/
public function getDateCreated()
{
return $this->dateCreated;
}
/**
* Sets the date when this post was created.
* #param string $dateCreated
*/
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
}
}
hope this helps to find solution.
I found the problem: it was an inputfilter element I wasn't using that was authenticating in forms. But the solution only brings me to a different problem:
Notice: Undefined index: title in C:\xampp\htdocs\ameyaw\module\BusinessGhana\src\Service\AutosManager.php on line 38
Notice: Undefined index: description in C:\xampp\htdocs\ameyaw\module\BusinessGhana\src\Service\AutosManager.php on line 39
Notice: Undefined index: featured in C:\xampp\htdocs\ameyaw\module\BusinessGhana\src\Service\AutosManager.php on line 58
Message:
An exception occurred while executing 'INSERT INTO auto (title, description, featured, date_created) VALUES (?, ?, ?, ?)' with params [null, null, null, "2017-06-15 05:04:44"]:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'title' cannot be null
this is my form and fieldset
use Zend\Form\Fieldset;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use BusinessGhana\Entity\Autos;
class AddFieldset extends Fieldset
{
protected $objectManager;
public function init()
{
$this->add([
'type' => 'text',
'name' => 'title',
'attributes' => [
'id' => 'autoTitle'
],
'options' => [
'label' => 'Title',
'display_empty_item' => true,
'empty_item_label' => 'Maximum of 60 characters',
],
]);
$this->add([
'type' => 'textarea',
'name' => 'description',
'attributes' => [
'id' => 'autoDescription'
],
'options' => [
'label' => 'Description',
'display_empty_item' => true,
'empty_item_label' => 'description',
],
]);
$this->add([
'type' => 'radio',
'name' => 'featured',
'attributes' => [
'id' => 'autoFeatured'
],
'options' => array(
'label' => 'Featured',
'value_options' => array(
array('value' => '0',
'label' => 'No',
'selected' => true,
'label_attributes' => array(
'class' => 'col-sm-2 btn btn-default',
),
),
array(
'value' => '1',
'label' => 'Yes',
'label_attributes' => array(
'class' => 'col-sm-2 btn btn-danger',
),
),
),
'column-size' => 'sm-12',
'label_attributes' => array(
'class' => 'col-sm-2',
),
),
]);
}
}
use Zend\Form\Form;
//use Zend\InputFilter\InputFilter;
class AddForm extends Form
{
public function init()
{
$this->add([
'name' => 'dependentForm',
'type' => AddFieldset::class,
]);
$this->add([
'type' => 'submit',
'name' => 'submit',
'attributes' => [
'value' => 'Submit',
],
]);
}
}
i know hydration can solve this problem but i dont know how to use it yet.
After browsing several tutorials reagrding Zend2 /Doctrine 2 and Fieldsets i finally figured out the filedset/collction.
But new "fields" wont be added to the database table. Any changes in the existing elements are stored. Major Class Organization callsthe fieldset ActBusinessCountry:
Major Class Organization
class Organization {
protected $inputFilter;
/**
* #ORM\Id
* #ORM\Column(type="integer");
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $organizational;
/**
* #ORM\Column(type="string")
*/
protected $structure;
/**
* #param \Doctrine\Common\Collections\ArrayCollection
* #ORM\OneToMany(targetEntity="People\Entity\ActBusinessCountry",mappedBy="company",cascade={"persist", "merge", "refresh", "remove"})
*/
protected $organizaton_opcountry;
public function __construct()
{
$this->organizaton_opcountry = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* #param \Doctrine\Common\Collections\ArrayCollection $organizaton_opcountry
*/
public function addOrganizaton_opcountry(Collection $organizaton_opcountry)
{
foreach ($organizaton_opcountry as $opcountry) {
$this->organizaton_opcountry->add($opcountry);
}
return $this->organizaton_opcountry;
}
public function removeOrganizaton_opcountry(Collection $organizaton_opcountry)
{
foreach ($organizaton_opcountry as $opcountry) {
$tag->setCompany(null);
$this->organizaton_opcountry->removeElement($opcountry);
}
}
/**
* #return Collection
*/
public function getOrganizaton_opcountry()
{
return $this->organizaton_opcountry;
}
Sub class/fieldset is ActBusinessCountry
class ActBusinessCountry {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* #ORM\ManyToOne(targetEntity="People\Entity\Organization",inversedBy="organizaton_opcountry")
* #ORM\JoinColumn(name="company_id", referencedColumnName="id")
*/
public $company;
/**
* #ORM\Column(type="string")
*/
public $country;
/**
* #ORM\Column(type="string")
*/
public $company_id;
/**
* Allow null to remove association
*/
public function setId($id = null)
{
$this->id = $id;
}
public function getId()
{
return $this->id;
}
public function getCompany()
{
return $this->company;
}
public function setCompany(Company $company = null)
{
$this->company = $company;
}
public function getCountry()
{
return $this->country;
}
public function setCountry($country)
{
$this->country = $country;
}
}
Organization Form:
$countrySelect = new ActBusinessCountryFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'organizaton_opcountry',
'options' => array(
'should_create_template' => true,
'use_as_base_fieldet' => true,
'count' => 1,
'allow_add' => true,
'target_element' => $countrySelect,
),
));
Fielset Elements:
class ActBusinessCountryFieldset extends Fieldset implements ObjectManagerAwareInterface
{
protected $objectManager;
public function __construct(ObjectManager $objectManager)
{
$this->setObjectManager($objectManager);
parent::__construct('fieldset');
$this ->setHydrator(new DoctrineHydrator($objectManager, 'People\Entity\ActBusinessCountry'))
->setObject(new \People\Entity\ActBusinessCountry());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'country',
'attributes' => array(
'class' => 'form-control input-small',
),
'options' => array(
'object_manager' => $this->getObjectManager(),
'target_class' => 'People\Entity\Country',
'value' => 'country',
'property' => 'country_name',
'class'=>'form-control',
'label_attributes' => array(
'class'=> 'col-sm-3 control-label',
),
),
));
}
public function getInputFilterSpecification()
{
return array(
'id' => array(
'required' => false
)
);
return array(
'country' => array(
'required' => true
)
);
}
Controller Flushing Part:
if ($this->request->isPost()) {
// Cancel button
if(isset($_POST['cancel'])) {
echo "<script>window.close();</script>";
}
$form->setData($this->request->getPost());
var_dump($this->request->getPost('organizaton_opcountry'));
var_dump($queryresult->getOrganizaton_opcountry());
//$queryresult->addOrganizaton_opcountry();
if ($form->isValid()) {
// Security request
if ($this->isAllowed('admin_res','admin_priv')) {
$form->bindValues();
$this->getEntityManager()->persist($queryresult);
$this->getEntityManager()->flush();
}
//echo "<script>window.close();</script>";
}
}
I am afraid, that i just missed a point. Though the post var_dump($this->request->getPost('organizaton_opcountry')); in the controller does output the following, after adding a third element and submitting:
array
0 =>
array
'id' => string '1' (length=1)
'country' => string 'Chad' (length=4)
1 =>
array
'id' => string '2' (length=1)
'country' => string 'Bermuda' (length=7)
2 =>
array
'id' => string '' (length=0)
'country' => string '(Not Specified)' (length=15)
Maybe you guys have an idea, or you have had the same problem before.
Thank you very much for any hint.
Kind regards,
David
Maybe u take a look at:
Saving a Doctine 2 Entity that contains an ObjectSelect element using Zend Form
Check the inputFilter in the Fieldset and add an inputfilter for the fieldset in the form e.g.:
$this->setValidationGroup(array(
'User' => array(
'name',
'role' // <- Fieldset
)
));
For the category structure on my proejct I'm building an entity. For the add form I use the DoctrineObject hydrator. When there is a value for the $parent this works fine, but whe there is no parent it gives me an error because there is no id to select the parent with. The value of the parent property should be null in this case.
I'd create an filter to do so. This filter is executed but the hydrator doesn't seem to get what I want it to do.
Does anybody know how to solve this?
My entity:
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Flex\Entity\Entity;
/**
* #Gedmo\Tree(type="materializedPath")
* #ORM\Table(name="categories")
* #ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\MaterializedPathRepository")
*/
class Category extends Entity
{
/**
* #ORM\OneToMany(mappedBy="parent", targetEntity="FlexCategories\Entity\Category")
*/
protected $children;
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
protected $id;
/**
* #Gedmo\TreeLevel
* #ORM\Column(nullable=true, type="integer")
*/
protected $level;
/**
* #ORM\Column(length=64, type="string")
*/
protected $name;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(inversedBy="children", targetEntity="FlexCategories\Entity\Category")
* #ORM\JoinColumns({
* #ORM\JoinColumn(onDelete="SET NULL", referencedColumnName="id")
* })
*/
protected $parent;
/**
* #Gedmo\TreePath(appendId=false, endsWithSeparator=false, separator="/", startsWithSeparator=true)
* #ORM\Column(length=255, nullable=true, type="string", unique=true)
*/
protected $path;
/**
* #Gedmo\Slug(fields={"name"}, unique=false)
* #Gedmo\TreePathSource
* #ORM\Column(length=64)
*/
protected $slug;
public function setId($value)
{
$this->id = $value;
}
public function setName($value)
{
$this->name = $value;
}
public function setParent($value)
{
$this->parent = $value;
}
}
My form:
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\ServiceManager\ServiceManager;
use Zend\ServiceManager\ServiceManagerAwareInterface;
class CategoryForm extends Form implements InputFilterProviderInterface, ServiceManagerAwareInterface
{
private $_serviceManager;
public function init()
{
// Init hydrator
$hydrator = new DoctrineObject($this->_serviceManager->get('doctrine.entitymanager.orm_default'),
'FlexCategories\Entity\Category');
// Set form basic configurations
$this->setAttribute('method', 'post')
->setHydrator($hydrator);
// Add parent field
$this->add(array(
'name' => 'parent',
'type' => 'Zend\Form\Element\Hidden',
));
// Add name field
$this->add(array(
'attributes' => array(
'required' => 'required',
),
'name' => 'name',
'options' => array(
'label' => 'Name',
),
'type' => 'Zend\Form\Element\Text',
));
// Add description field
$this->add(array(
'name' => 'description',
'options' => array(
'label' => 'Description',
),
'type' => 'Zend\Form\Element\Textarea',
));
// Add CSRF element
$this->add(array(
'name' => 'csrf',
'type' => 'Zend\Form\Element\Csrf',
));
// Add submit button
$this->add(array(
'attributes' => array(
'type' => 'submit',
'value' => 'Save',
),
'name' => 'submit',
));
}
public function getInputFilterSpecification()
{
return array(
'description' => array(
'filters' => array(
array(
'name' => 'Zend\Filter\StringTrim'
),
),
'required' => false,
),
'name' => array(
'filters' => array(
array(
'name' => 'Zend\Filter\StringTrim'
),
),
'required' => true,
'validators' => array(
array(
'name' => 'Flex\Validator\EntityUnique',
'options' => array(
'entity' => 'FlexCategories\Entity\Category',
'filter' => array(
array('property' => 'parent',
'value' => array('_context', 'parent')),
),
'property' => 'name',
'serviceLocator' => $this->_serviceManager,
),
),
),
),
'parent' => array(
'filters' => array(
array(
'name' => 'Flex\Filter\NullIfEmpty'
),
),
'required' => false,
),
);
}
public function setServiceManager(ServiceManager $serviceManager)
{
$this->_serviceManager = $serviceManager;
$this->init();
return $this;
}
}
My controller:
use Flex\Controller\AbstractController;
use FlexCategories\Entity\Category;
use FlexCategories\Form\CategoryForm;
class AdminController extends AbstractController
{
public function addAction()
{
// Load form
$form = $this->getServiceLocator()->get('FlexCategories\Form\CategoryForm');
// Create and bind new entity
$category = new Category();
$form->bind($category);
// Load parent category if present
$parentId = $this->params()->fromRoute('id', null);
if ($parentId !== null)
{
if (!is_numeric($parentId))
throw new \InvalidArgumentException('Invalid parent id specified');
$entityManager = $this->getEntityManager();
$repository = $entityManager->getRepository('FlexCategories\Entity\Category');
$parent = $repository->find($parentId);
if (!$parent)
throw new \InvalidArgumentException('Invalid parent id specified');
$form->get('parent')->setValue($parent->getId());
}
// Process request
$request = $this->getRequest();
if ($request->isPost())
{
$form->setData($request->getPost());
if ($form->isValid())
{
$entityManager = $this->getEntityManager();
$entityManager->persist($category);
$entityManager->flush();
$this->flashMessenger()->addSuccessMessage(sprintf('The category "%1$s" has succesfully been added.', $category->getName()));
return $this->redirect()->toRoute($this->getEvent()->getRouteMatch()->getMatchedRouteName());
}
}
// Return form
return array(
'form' => $form,
);
}
public function indexAction()
{
// Load all categories
$entityManager = $this->getEntityManager();
$repository = $entityManager->getRepository('FlexCategories\Entity\Category');
$categories = $repository->findBy(array(), array('path' => 'asc'));
return array(
'categories' => $categories,
);
}
}
My database:
CREATE TABLE `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`level` int(11) DEFAULT NULL,
`name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`path` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`slug` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_3AF34668B548B0F` (`path`),
KEY `IDX_3AF34668727ACA70` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
ALTER TABLE `categories`
ADD CONSTRAINT `FK_3AF34668727ACA70` FOREIGN KEY (`parent_id`) REFERENCES `categories` (`id`) ON DELETE SET NULL;
I'd solve this problem by create an "HiddenElement" element based on "DoctrineModule\Form\ElementObjectSelect" and use this as the input type.
You need a strategy which handles '' values. ('' != null) as ocramius points out its possible to haven an primary key with ''.
you ran into this problem as soon as you use the "empty_option" currently u cant just set null to it, the form post will always transfer ''.
see https://github.com/doctrine/DoctrineModule/pull/119
see https://github.com/doctrine/DoctrineModule/pull/106
so add a strategy for this field to the hydrator to convert '' to null.
this could look like:
use Zend\Stdlib\Hydrator\Strategy\DefaultStrategy;
class ForeignKey extends DefaultStrategy
{
public function hydrate($value)
{
if($value == '') {
return NULL;
}
return $value;
}
}
I want to set EntitiesManager instance available on my Controller. I want the Instance available with $this->em on Controller. This is my configuration :
module.config.php
[...]
'doctrine' => array(
'driver' => array(
'application_entities' => array(
'class' =>'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/Application/Entity')
),
'orm_default' => array(
'drivers' => array(
'Application\Entity' => 'application_entities'
),
),
),
),
'di' => array(
'instance' => array(
'alias' => array(
'application' => 'Application\Controller\IndexController',
),
'Application\Controller\IndexController' => array(
'parameters' => array(
'em' => 'doctrine_em',
),
),
),
),
IndexController.php
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use \Doctrine\ORM\EntityManager;
class IndexController extends AbstractActionController
{
protected $em;
public function setEm(EntityManager $em) {
$this->em = $em;
return $this;
}
public function indexAction() {
$user1 = $this->em->find('\Application\Entity\User', 1);
var_dump($user1->getFullname());
}
I got this error : "Fatal error: Call to a member function find() on a non-object". It seem than EntityManager is not correctly instantiate.
What Am I missing?
Thank you!
You dont need anything in the module config
You edit the Module.php, onbootstrap function
public function onBootstrap(\Zend\EventManager\EventInterface $e) {
$serviceManager = $e->getApplication()->getServiceManager();
$em = $serviceManager;
$controllerLoader = $serviceManager->get('ControllerLoader');
$controllerLoader->addInitializer(function ($controller) use ($em) {
if (method_exists($controller, 'setEm')) {
$controller->setEm($em);
}
});
}
the controller stays as you have it, with the $em field, and the setEm method
//..
protected $em;
public function setEm(EntityManager $em) {
$this->em = $em;
return $this;
}
//..
Offers.php
/**
* #var \ZGoffers\MainBundle\Entity\OfferParameter
*
* #ORM\OneToMany(targetEntity="OfferParameter", mappedBy="offer", cascade={"all"})
*/
private $parameters;
OfferParameter.php
/**
* #var \ZGoffers\MainBundle\Entity\Offer
*
* #ORM\ManyToOne(targetEntity="Offer", inversedBy="offer", cascade={"all"})
*/
private $offer;
OfferType.php
class OfferType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('advertiser')
->add('name')
->add('url', 'text', array('label' => 'URL'))
->add('externalUrl', 'text', array('label' => 'External URL'))
->add('dailyCap', 'text', array('label' => 'Daily Cap'))
->add('parameters', 'collection', array(
'type' => new OfferParameterType(),
'allow_add' => true,
'allow_delete' => true
))
->add('active', 'choice', array(
'choices' => array(0 => 'Disabled', 1 => 'Enabled')
));
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'ZGOffers\MainBundle\Entity\Offer'
);
}
}
OfferParameterType.php
class OfferParameterType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('field')
->add('type', 'choice', array(
'choices' => array(
'=' => 'EQUALS',
'>' => 'IS GREATER THAN',
'>=' => 'IS GREATER THAN OR EQUALS',
'<' => 'IS LESS THAN',
'<=' => 'IS GREATER THAN OR EQUALS'
)
))
->add('value');
}
public function getDefaultOptions(array $options)
{
return array(
'data_class' => 'ZGOffers\MainBundle\Entity\OfferParameter'
);
}
}
Form Handling
public function process()
{
if ('POST' == $this->request->getMethod()) {
// bind form data
$this->form->bindRequest($this->request);
// If form is valid
if ($this->form->isValid() && ($offer = $this->form->getData()) instanceof Offer) {
foreach ($offer->getParameters() as $parameter) {
$parameter->setOffer($offer); // THIS SHOULDNT BE NEEDED
}
// save offer to the database
$this->entityManager->persist($offer);
$this->entityManager->flush();
return true;
}
}
return false;
}
My question is.... How the hell do you delete elements in form collections in SF2????
I have multiple forms that are just like this one in my project and it's really putting a halt to development :(
Thanks for all help!
You may need to do something like below :
->add('parameters', 'collection', array(
'type' => new OfferParameterType(),
'allow_add' => true,
'allow_delete' => true,
'attr'=>array('style'=>'display:none;')
))
That makes your whole OfferParameterType collection hidden.
Or in OfferParameterType apply same thing for each field like below :
->add('field',null, array('attr'=>array('style'=>'display:none;')))