I have a problem with my ZF2 form element (select). When i bind my doctrine entity to this form, all my select options get the selected attribute instead of just the one that should. The entity just got a connected object and the Hydrator is set in the for aswell.
Here is some of my code. Hope i just missed something small.
AddressEntity.php
<?php
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use ZF2Core\Entity\AbstractEntity;
/**
* #ORM\Entity
* #ORM\Table(name="`address`")
*/
class Address extends AbstractEntity
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="bigint", options={"unsigned":true})
*/
protected $addressId;
/**
* #ORM\ManyToOne(targetEntity="SNOrganisation\Entity\Organisation", inversedBy="organisationId")
* #ORM\JoinColumn(name="organisationId", referencedColumnName="organisationId", nullable=false)
*/
protected $organisation;
/**
* #ORM\ManyToOne(targetEntity="AddressType")
* #ORM\JoinColumn(name="addressTypeId", referencedColumnName="addressTypeId", nullable=false)
*/
protected $addressType;
/** #ORM\Column(type="string", nullable=true) */
protected $otys;
/** #ORM\Column(type="string") */
protected $address;
/** #ORM\Column(type="string", nullable=true) */
protected $postalcode;
/** #ORM\Column(type="string") */
protected $city;
/** #ORM\Column(type="string", nullable=true) */
protected $email;
/**
* #ORM\ManyToOne(targetEntity="ZF2Country\Entity\Country")
* #ORM\JoinColumn(name="countryId", referencedColumnName="countryId", nullable=false)
*/
protected $country;
/** #ORM\Column(type="datetime") */
protected $created;
/** #ORM\Column(type="datetime", nullable=true) */
protected $deleted;
public function getAddressId()
{
return $this->addressId;
}
public function getOrganisation()
{
return $this->organisation;
}
public function getAddressType()
{
return $this->addressType;
}
public function getOtys()
{
return $this->otys;
}
public function getAddress()
{
return $this->address;
}
public function getPostalcode()
{
return $this->postalcode;
}
public function getCity()
{
return $this->city;
}
public function getEmail()
{
return $this->email;
}
public function getCreated()
{
return $this->created;
}
public function getDeleted()
{
return $this->deleted;
}
public function setAddressId($addressId)
{
$this->addressId = $addressId;
return $this;
}
public function setOrganisation($organisation)
{
$this->organisation = $organisation;
return $this;
}
public function setAddressType($addressType)
{
$this->addressType = $addressType;
return $this;
}
public function setOtys($otys)
{
$this->otys = $otys;
return $this;
}
public function setAddress($address)
{
$this->address = $address;
return $this;
}
public function setPostalcode($postalcode)
{
$this->postalcode = $postalcode;
return $this;
}
public function setCity($city)
{
$this->city = $city;
return $this;
}
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function setCreated($created)
{
$this->created = $created;
return $this;
}
public function setDeleted($deleted)
{
$this->deleted = $deleted;
return $this;
}
public function getCountry()
{
return $this->country;
}
public function setCountry($country)
{
$this->country = $country;
return $this;
}
}
AddressForm.php
<?php
namespace SNOrganisation\Form;
use Zend\Form\Form;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Application\Entity\Address;
use Zend\ServiceManager\ServiceManager;
class AddressForm extends Form
{
public function __construct($name = null, $entityManager, ServiceManager $serviceManager)
{
parent::__construct($name);
$this->setAttribute('method', 'post');
$this->setAttribute('class', 'form-horizontal');
$this->setHydrator(new DoctrineHydrator($entityManager, 'Application\Entity\Address'));
$this->setObject(new Address());
$this->add(array(
'name' => 'addressType',
'type' => 'select',
'options' => array(
'label' => _('Type'),
'label_attributes' => array(
'class' => 'col-lg-2 control-label'
),
'value_options' => $this->getAddressTypeOptions($serviceManager),
),
'attributes' => array(
'class' => 'form-control',
),
));
$this->add(array(
'name' => 'address',
'type' => 'text',
'options' => array(
'label' => _('Address'),
'label_attributes' => array(
'class' => 'col-lg-2 control-label'
),
),
'attributes' => array(
'class' => 'form-control',
'placeholder' => 'Abbey Road 1',
),
));
$this->add(array(
'name' => 'postalcode',
'type' => 'text',
'options' => array(
'label' => _('Postalcode'),
'label_attributes' => array(
'class' => 'col-lg-2 control-label'
),
),
'attributes' => array(
'class' => 'form-control',
'placeholder' => '1234 AB',
),
));
$this->add(array(
'name' => 'city',
'type' => 'text',
'options' => array(
'label' => _('City'),
'label_attributes' => array(
'class' => 'col-lg-2 control-label'
),
),
'attributes' => array(
'class' => 'form-control',
'placeholder' => 'Amsterdam',
),
));
$this->add(array(
'name' => 'country',
'type' => 'select',
'options' => array(
'label' => _('Country'),
'label_attributes' => array(
'class' => 'col-lg-2 control-label'
),
'value_options' => $this->getCountryOptions($serviceManager),
),
'attributes' => array(
'class' => 'form-control',
),
));
$this->add(array(
'name' => 'email',
'type' => 'email',
'options' => array(
'label' => _('Email'),
'label_attributes' => array(
'class' => 'col-lg-2 control-label'
),
),
'attributes' => array(
'class' => 'form-control',
'placeholder' => 'name#domain.tld',
),
));
$this->add(array(
'name' => 'submit',
'type' => 'submit',
'options' => array(
'label' => _('Save'),
),
'attributes' => array(
'class' => 'btn btn-large btn-primary',
),
));
}
protected function getAddressTypeOptions($serviceManager)
{
$data = array();
$addressTypeService = $serviceManager->get('application_service_addresstype');
$addressTypeCollection = $addressTypeService->getAddressTypes()->getResult();
foreach($addressTypeCollection as $addressType)
{
$data[$addressType->getAddressTypeId()] = $addressType->getName();
}
return $data;
}
protected function getCountryOptions($serviceManager)
{
$data = array();
$countryService = $serviceManager->get('zf2country_service_country');
$countryCollection = $countryService->getCountries()->getResult();
foreach($countryCollection as $country)
{
$data[$country->getCountryId()] = $country->getName();
}
return $data;
}
}
AddressController.php
<?php
namespace SNOrganisation\Controller;
use ZF2Core\Controller\AbstractController;
use Zend\View\Model\ViewModel;
use Application\Entity\Address;
class AddressController extends AbstractController
{
public function editAction()
{
$organisationId = (int)$this->params()->fromRoute('id');
$addressId = (int)$this->params()->fromRoute('addressId');
$request = $this->getRequest();
$address = $this->getEntityManager()->getRepository('Application\Entity\Address')->find($addressId);
if ($address)
{
$addressForm = $this->getServiceLocator()->get('snorganisation_form_address');
$addressForm->bind($address);
}
else
{
$this->resultMessenger()->addFatalMessage($this->getTranslator()->translate('The address could not be found'));
$this->redirect()->toRoute('organisation');
}
return new ViewModel(array(
'addressForm' => $addressForm,
));
}
}
Entity Dump
<?php
object(Application\Entity\Address)[700]
protected 'addressId' => string '487956' (length=6)
protected 'organisation' =>
object(DoctrineORMModule\Proxy\__CG__\SenetOrganisation\Entity\Organisation)[701]
public '__initializer__' =>
object(Closure)[583]
public '__cloner__' =>
object(Closure)[584]
public '__isInitialized__' => boolean false
protected 'organisationId' => string '412705' (length=6)
protected 'ownerPerson' => null
protected 'otys' => null
protected 'name' => null
protected 'paymentInterval' => null
protected 'vatNumber' => null
protected 'debtor' => null
protected 'invoiceByEmail' => null
protected 'active' => null
protected 'reasonInactive' => null
protected 'created' => null
protected 'addressCollection' => null
protected 'personCollection' => null
protected 'orderCollection' => null
protected 'serviceManager' => null
protected 'addressType' =>
object(DoctrineORMModule\Proxy\__CG__\Application\Entity\AddressType)[714]
public '__initializer__' =>
object(Closure)[704]
public '__cloner__' =>
object(Closure)[705]
public '__isInitialized__' => boolean false
protected 'addressTypeId' => string '2' (length=1)
protected 'name' => null
protected 'serviceManager' => null
protected 'otys' => null
protected 'address' => string 'Langebrug 87 b' (length=14)
protected 'postalcode' => string '2311 TJ' (length=7)
protected 'city' => string 'Leiden' (length=6)
protected 'email' => null
protected 'country' =>
object(DoctrineORMModule\Proxy\__CG__\ZF2Country\Entity\Country)[724]
public '__initializer__' =>
object(Closure)[711]
public '__cloner__' =>
object(Closure)[710]
public '__isInitialized__' => boolean false
protected 'countryId' => string '157' (length=3)
protected 'nameIso' => null
protected 'name' => null
protected 'iso' => null
protected 'iso3' => null
protected 'serviceManager' => null
protected 'created' =>
object(DateTime)[698]
public 'date' => string '2014-03-22 16:05:49' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Amsterdam' (length=16)
protected 'deleted' => null
protected 'serviceManager' => null
Let me investigate, what is the reason. Sometimes it is convenient to use Zend\Form\Select element, not Doctrine element. But Zend element sometimes can not deal with doctrine Entities. The reason is in the following code of file Zend\Form\View\Helper\FormSelect.php at method renderOptions.
if (ArrayUtils::inArray($value, $selectedOptions)) {
$selected = true;
}
This piece of code makes every option selected. But $selectedOptions is not entity id, it is Entity object. This object is transformed into array via magic method, so we have wrong $selectedOptions.
So I've decided to change form element type from 'Select' to DoctrineModule\Form\Element\ObjectSelect and inject entityManager.
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => array(
'object_manager' => $entityManager,
'target_class' => 'Telecom\Entity\Name',
)
I dont know, why sometimes it is not a problem. Probably I should take a look at Proxy object, generated by Doctrine. I will update the answer if I understand something.
The DoctrineModule\Form\Element\ObjectSelect did the trick
Related
So in summary I'm trying to override a third party module to include an extra dropdown menu on the admin Ui
Heres the third party file at
Prince/Productattach/Block/Adminhtml/Productattach/Edit/Tab/Main.php
namespace Prince\Productattach\Block\Adminhtml\Productattach\Edit\Tab;
/**
*Class Main
*#package Prince\Productattach\Block\Adminhtml\Productattach\Edit\Tab
*/
class Main extends \Magento\Backend\Block\Widget\Form\Generic implements
\Magento\Backend\Block\Widget\Tab\TabInterface
{
/**
* #var \Magento\Store\Model\System\Store
*/
private $systemStore;
/**
* #var \Magento\Customer\Model\ResourceModel\Group\Collection
*/
private $customerCollection;
/**
* Main constructor.
* #param \Magento\Backend\Block\Template\Context $context
* #param \Magento\Framework\Registry $registry
* #param \Magento\Framework\Data\FormFactory $formFactory
* #param \Magento\Store\Model\System\Store $systemStore
* #param \Magento\Customer\Model\ResourceModel\Group\Collection $customerCollection
* #param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Store\Model\System\Store $systemStore,
\Magento\Customer\Model\ResourceModel\Group\Collection $customerCollection,
array $data = []
) {
$this->_systemStore = $systemStore;
$this->_customerCollection = $customerCollection;
parent::__construct($context, $registry, $formFactory, $data);
}
/**
* Prepare form
*
* #return $this
*/
public function _prepareForm()
{
$model = $this->_coreRegistry->registry('productattach');
/*
* Checking if user have permissions to save information
*/
if ($this->_isAllowedAction('Prince_Productattach::save')) {
$isElementDisabled = false;
} else {
$isElementDisabled = true;
}
/** #var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create();
$form->setHtmlIdPrefix('productattach_main_');
$fieldset = $form->addFieldset(
'base_fieldset',
['legend' => __('Attachment Information')]
);
$customerGroup = $this->customerCollection->toOptionArray();
if ($model->getId()) {
$fieldset->addField('productattach_id', 'hidden', ['name' => 'productattach_id']);
}
$fieldset->addField(
'name',
'text',
[
'name' => 'name',
'label' => __('Attachment Name'),
'title' => __('Attachment Name'),
'required' => true,
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'description',
'textarea',
[
'name' => 'description',
'label' => __('Description'),
'title' => __('Description'),
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'files',
'file',
[
'name' => 'file',
'label' => __('File'),
'title' => __('File'),
'required' => false,
'note' => 'File size must be less than 2 Mb.', // TODO: show ACCTUAL file-size
'disabled' => $isElementDisabled
]
);
$fieldset->addType(
'uploadedfile',
\Prince\Productattach\Block\Adminhtml\Productattach\Renderer\FileIconAdmin::class
);
$fieldset->addField(
'file',
'uploadedfile',
[
'name' => 'uploadedfile',
'label' => __('Uploaded File'),
'title' => __('Uploaded File'),
]
);
$fieldset->addField(
'url',
'text',
[
'name' => 'url',
'label' => __('URL'),
'title' => __('URL'),
'required' => false,
'disabled' => $isElementDisabled,
'note' => 'Upload file or Enter url'
]
);
$fieldset->addField(
'customer_group',
'multiselect',
[
'name' => 'customer_group[]',
'label' => __('Customer Group'),
'title' => __('Customer Group'),
'required' => true,
'value' => [0,1,2,3], // todo: preselect ALL customer groups, not just 0-3
'values' => $customerGroup,
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'store',
'multiselect',
[
'name' => 'store[]',
'label' => __('Store'),
'title' => __('Store'),
'required' => true,
'value' => [0],
'values' => $this->systemStore->getStoreValuesForForm(false, true),
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'active',
'select',
[
'name' => 'active',
'label' => __('Active'),
'title' => __('Active'),
'value' => 1,
'options' => ['1' => __('Yes'), '0' => __('No')],
'disabled' => $isElementDisabled
]
);
$this->_eventManager->dispatch('adminhtml_productattach_edit_tab_main_prepare_form', ['form' => $form]);
if ($model->getId()) {
$form->setValues($model->getData());
}
$this->setForm($form);
return parent::_prepareForm();
}
/**
* Prepare label for tab
*
* #return string
*/
public function getTabLabel()
{
return __('Attachment Information');
}
/**
* Prepare title for tab
*
* #return string
*/
public function getTabTitle()
{
return __('Attachment Information');
}
/**
* {#inheritdoc}
*/
public function canShowTab()
{
return true;
}
/**
* {#inheritdoc}
*/
public function isHidden()
{
return false;
}
/**
* Check permission for passed action
*
* #param string $resourceId
* #return bool
*/
public function _isAllowedAction($resourceId)
{
return $this->_authorization->isAllowed($resourceId);
}
}
I have my module setup and my di.xml configured with the usual plus below to override the class.
<preference for="Prince\Productattach\Block\Adminhtml\Productattach\Edit\Tab" type="Vendor\Filecategory\Block\Adminhtml\Productattach\Edit\Tab"/>
then and exact replica of the class with namespace and my extra field added at
Vendor/Filecategory/Block/Adminhtml/Productattach/Edit/Tab/Main.php
namespace Vendor\Filecategory\Block\Adminhtml\Productattach\Edit\Tab;
use \Prince\Productattach\Block\Adminhtml\Productattach\Edit\Tab\Main as Main;
class MainExt extends Main
{
/**
* #var \Magento\Store\Model\System\Store
*/
private $systemStore;
/**
* #var \Magento\Customer\Model\ResourceModel\Group\Collection
*/
private $customerCollection;
/**
* Main constructor.
* #param \Magento\Backend\Block\Template\Context $context
* #param \Magento\Framework\Registry $registry
* #param \Magento\Framework\Data\FormFactory $formFactory
* #param \Magento\Store\Model\System\Store $systemStore
* #param \Magento\Customer\Model\ResourceModel\Group\Collection $customerCollection
* #param array $data
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Store\Model\System\Store $systemStore,
\Magento\Customer\Model\ResourceModel\Group\Collection $customerCollection,
array $data = []
) {
$this->systemStore = $systemStore;
$this->customerCollection = $customerCollection;
parent::__construct($context, $registry, $formFactory, $data, $systemStore);
}
/**
* Prepare form
*
* #return $this
*/
public function _prepareForm()
{
$model = $this->_coreRegistry->registry('productattach');
/*
* Checking if user have permissions to save information
*/
if ($this->_isAllowedAction('Prince_Productattach::save')) {
$isElementDisabled = false;
} else {
$isElementDisabled = true;
}
/** #var \Magento\Framework\Data\Form $form */
$form = $this->_formFactory->create();
$form->setHtmlIdPrefix('productattach_main_');
$fieldset = $form->addFieldset(
'base_fieldset',
['legend' => __('Attachment Information')]
);
$customerGroup = $this->customerCollection->toOptionArray();
if ($model->getId()) {
$fieldset->addField('productattach_id', 'hidden', ['name' => 'productattach_id']);
}
$fieldset->addField(
'name',
'text',
[
'name' => 'name',
'label' => __('Attachment Name'),
'title' => __('Attachment Name'),
'required' => true,
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'Category',
'select',
[
'name' => 'Category',
'label' => __('Category'),
'title' => __('Category'),
'value' => 0,
'options' => ['0' => __('Technical Specification'), '1' => __('Installation Instructions')],
]
);
$fieldset->addField(
'description',
'textarea',
[
'name' => 'description',
'label' => __('Description'),
'title' => __('Description'),
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'files',
'file',
[
'name' => 'file',
'label' => __('File'),
'title' => __('File'),
'required' => false,
'note' => 'File size must be less than 2 Mb.', // TODO: show ACCTUAL file-size
'disabled' => $isElementDisabled
]
);
$fieldset->addType(
'uploadedfile',
\Prince\Productattach\Block\Adminhtml\Productattach\Renderer\FileIconAdmin::class
);
$fieldset->addField(
'file',
'uploadedfile',
[
'name' => 'uploadedfile',
'label' => __('Uploaded File'),
'title' => __('Uploaded File'),
]
);
$fieldset->addField(
'url',
'text',
[
'name' => 'url',
'label' => __('URL'),
'title' => __('URL'),
'required' => false,
'disabled' => $isElementDisabled,
'note' => 'Upload file or Enter url'
]
);
$fieldset->addField(
'customer_group',
'multiselect',
[
'name' => 'customer_group[]',
'label' => __('Customer Group'),
'title' => __('Customer Group'),
'required' => true,
'value' => [0,1,2,3], // todo: preselect ALL customer groups, not just 0-3
'values' => $customerGroup,
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'store',
'multiselect',
[
'name' => 'store[]',
'label' => __('Store'),
'title' => __('Store'),
'required' => true,
'value' => [0],
'values' => $this->systemStore->getStoreValuesForForm(false, true),
'disabled' => $isElementDisabled
]
);
$fieldset->addField(
'active',
'select',
[
'name' => 'active',
'label' => __('Active'),
'title' => __('Active'),
'value' => 1,
'options' => ['1' => __('Yes'), '0' => __('No')],
'disabled' => $isElementDisabled
]
);
$this->_eventManager->dispatch('adminhtml_productattach_edit_tab_main_prepare_form', ['form' => $form]);
if ($model->getId()) {
$form->setValues($model->getData());
}
$this->setForm($form);
return parent::_prepareForm();
}
/**
* Prepare label for tab
*
* #return string
*/
public function getTabLabel()
{
return __('Attachment Information');
}
/**
* Prepare title for tab
*
* #return string
*/
public function getTabTitle()
{
return __('Attachment Information');
}
/**
* {#inheritdoc}
*/
public function canShowTab()
{
return true;
}
/**
* {#inheritdoc}
*/
public function isHidden()
{
return false;
}
/**
* Check permission for passed action
*
* #param string $resourceId
* #return bool
*/
public function _isAllowedAction($resourceId)
{
return $this->_authorization->isAllowed($resourceId);
}
}
However I keep getting Error
Incompatible argument type: Required type: \Magento\Store\Model\System\Store. Actual type: array;
I have tried flush cache and reindex but no luck. Please can someone tell me what im doing wrong here? Also happy to listen to any alternative ways of completing the same thing.
Thanks in advance.
I have managed to complete this by creating a plugin class instead of overriding the whole class. I have attached the post I followed for any one interested in adding a form field to n existing form attached to a third part module.
https://magento.stackexchange.com/questions/174209/magento-2-add-new-field-to-magento-user-admin-form
I'm working on a project using Zend Framework 3 and Doctrine 2, using for DcotrineModule integration, the following is the Entity modeling I'm having problems with:
To work with this modeling with the doctrine I'm using #InheritanceType, below are the relevant excerpts from Entities:
Pessoa Entity:
/**
* Abstração de Pessoa
*
* #author Rodrigo Teixeira Andreotti <ro.andriotti#gmail.com>
*
* #Entity
* #InheritanceType("JOINED")
* #DiscriminatorColumn(name="tipo", type="string")
* #DiscriminatorMap( { "pessoa" = "Pessoa",
* "pessoa_fisica" = "PessoaFisica",
* "pessoa_juridica" = "PessoaJuridica" } )
* #Table(name="pessoa")
*/
abstract class Pessoa implements JsonSerializable, PessoaInterface
{
use JsonSerializeTrait;
/**
* #Id
* #GeneratedValue(strategy="IDENTITY")
* #Column(type="integer", length=32, unique=true, nullable=false, name="id_pessoa")
* #var integer
*/
protected $idPessoa;
/**
* Usuário
* #OneToOne(targetEntity="User\Entity\User", inversedBy="pessoa", cascade={"persist"})
* #JoinColumn(name="usuario", referencedColumnName="id")
*
* #var User
*/
protected $usuario;
/**
* #OneToOne(targetEntity="EnderecoPessoa", mappedBy="pessoa", cascade={"persist"})
* #var EnderecoPessoa
*/
protected $endereco;
/**
* Contatos da pessoa
* #OneToMany(targetEntity="ContatoPessoa", mappedBy="pessoa", cascade={"persist"}, orphanRemoval=true)
* #var ArrayCollection|array
*/
protected $contatos;
const PESSOA_FISICA = "pessoa_fisica", PESSOA_JURIDICA = "pessoa_juridica";
public function __construct()
{
$this->contatos = new ArrayCollection();
}
}
PessoaFisica Entity:
/**
* Abstração da pessoa física
*
* #Entity
* #Table(name="pessoa_fisica")
* #author Rodrigo Teixeira Andreotti <ro.andriotti#gmail.com>
*/
class PessoaFisica extends Pessoa implements JsonSerializable {
use JsonSerializeTrait;
/**
* Nome da pessoa física
* #Column(type="string", length=14)
* #var string
*/
private $nome;
/**
* Número do CPF da pessoa (quando brasileiro)
* #Column(type="string", length=14)
* #var string
*/
private $cpf;
/**
* Número do RG (quando brasileiro)
* #Column(type="string", length=13)
* #var string
*/
private $rg;
/**
* Data de nascimento
* #Column(type="date", name="data_nascimento")
* #var DateTime
*/
private $dataNascimento;
}
PessoaJuridica Entity:
/**
* Abstração de Pessoa Jurídica
*
* #Entity
* #Table(name="pessoa_juridica")
* #InheritanceType("JOINED")
* #author Rodrigo Teixeira Andreotti <ro.andriotti#gmail.com>
*/
class PessoaJuridica extends Pessoa implements JsonSerializable {
use JsonSerializeTrait;
/**
* #Id
* #GeneratedValue(strategy="IDENTITY")
* #Column(type="integer", length=32, unique=true, nullable=false, name="id_pessoa")
* #var integer
*/
protected $idPessoa;
/**
* Nome fantasia
* #Column(type="string", length=32, name="nome_fantasia")
* #var String
*/
protected $nomeFantasia;
/**
* Número do CNPJ
* #Column(type="string", length=14, unique=true, name="cnpj")
* #var string
*/
protected $cnpj;
/**
* Razão social da empresa
* #Column(type="string", length=32, name="razao_social")
* #var string Razão social da empresa, quando necessário
*/
protected $razaoSocial;
}
So far everything works perfectly, the problem is when I need to generate a form for this information, I'm currently working on the "Customer" module, basically what I did for it was:
Create a form with client ID + Pessoa Fieldset
In the Pessoa Fieldset, I created the fieldsets for shared information (user, address, contacts etc)
In the Pessoa Fieldset, it also includes two other Fieldsets, one for each Pessoa's child class (PessoaFisica and PessoaJuridica) - and here come's the problem.
In the screen below you can see my registration form:
This form displays or hides the fieldset of PessoaJuridica or PessoaFisica according to the selected type using javascript, however as they are different fieldsets within the form, when zend hydrates them they are hydrated as different objects as well, ie the inheritance is not applied to the Person object, which should be selected according to the type.
Basically what, in my point of view, would need to happen, would be that there is a way for zend not to render the fieldsets referring to the child classes of the Person class as separate objects, at the moment the form is rendered with these fields so (for example) :
person [fsPeople] [name]
person [fsPessoaJuridica] [nameFantasica]
And this causes the zend not to generate the correct class to be saved in the database.
What would be the correct way to do this implementation of the form?
Well, the response from the #rkeet helped me a lot to understand where the problem was, which is not really a problem =]
Due to the usage of inheritance, you've created separate Entities.
However, the form you initially create in the back-end works with a
single Entity. The front-end you've modified to handle 2. So your
front-end does not match your back-end. As, due to the inheritance,
you now have 2 separate Entities, you should create 2 separate forms,
using different fieldsets (PessoaJuridica or PessoaFisica) as the base
fieldsets.
I'll leave the path I followed here, it might help someone with the same doubt as me.
First, following the logic explained in his comment, I created an abstract fieldset for the PessoaEntity with the information shared between the two types of person, and extended it into two child classes PessoaFisicaFieldset and PessoaJuridicaFieldset, which I describe below:
/**
* Fieldset com dados para a pessoa
*
* #author Rodrigo Teixeira Andreotti <ro.andriotti#gmail.com>
*/
abstract class PessoaFieldset extends Fieldset implements InputFilterProviderInterface
{
private $em;
private $userFs;
private $enderecoFs;
private $contatoFs;
public function __construct(ObjectManager $em,
UserFieldset $userFs,
PessoaEnderecoFieldset $enderecoFs,
ContatoFieldset $contatoFs)
{
parent::__construct('pessoa');
$this->em = $em;
$this->userFs = $userFs;
$this->enderecoFs = $enderecoFs;
$this->contatoFs = $contatoFs;
$this->init();
}
protected function getEm()
{
return $this->em;
}
public function init()
{
$this
->setHydrator(new DoctrineObject($this->getEm()));
$this->add(array(
'type' => 'Hidden',
'name' => 'id_pessoa',
'attributes' => array(
'id' => 'txtId'
)
));
$this->add(array(
'type' => 'hidden',
'name' => 'tipo',
));
$this->add($this->userFs);
$this->add($this->enderecoFs);
$elCollection = new Collection;
$elCollection
->setName('contatos')
->setLabel('Informações de Contato')
->setCount(1)
->setShouldCreateTemplate(true)
->setAllowAdd(true)
->setAllowRemove(true)
->setTargetElement($this->contatoFs);
$this->add($elCollection);
$this->add(array(
'type' => 'Button',
'name' => 'btAddContato',
'options' => array(
'label' => '<i class="fa fa-fw fa-plus"></i> Adicionar',
'label_options' => array(
'disable_html_escape' => true
)
),
'attributes' => array(
'class' => 'btn btn-info',
'id' => 'btAddContato'
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'id_pessoa' => array(
'required' => false,
'filters' => array(
['name'=>'Int']
)
),
'tipo' => array(
'required' => true,
)
);
}
}
This is my PessoaFisicaFieldset class.
/**
* Fieldset com dados para a pessoa Física
*
* #author Rodrigo Teixeira Andreotti <ro.andriotti#gmail.com>
*/
class PessoaFisicaFieldset extends PessoaFieldset implements InputFilterProviderInterface
{
private $em;
public function __construct(ObjectManager $em,
\User\Form\UserFieldset $userFs,
PessoaEnderecoFieldset $enderecoFs,
\Common\Form\ContatoFieldset $contatoFs)
{
parent::__construct($em, $userFs, $enderecoFs, $contatoFs);
$this->init();
}
public function init()
{
parent::init();
$this
->setObject(new PessoaFisica());
$this->get('tipo')->setValue(\Pessoa\Entity\Pessoa::PESSOA_FISICA);
$this->add(array(
'type' => 'Text',
'name' => 'cpf',
'options' => array(
'label' => 'CPF',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtCpf'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'nome',
'options' => array(
'label' => 'Nome',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtNome'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'rg',
'options' => array(
'label' => 'RG',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtRazaoSocial'
)
));
$this->add(array(
'type' => 'DateTime',
'name' => 'dataNascimento',
'options' => array(
'format' => 'd/m/Y',
'label' => 'Data de Nascimento',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line data',
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'nome' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'rg' => array(
'required' => false,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'cpf' => array(
'required' => false,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
),
'validators' => array(
['name' => CpfValidator::class]
)
),
'dataNascimento' => array(
'required' => true,
'filters' => array(
array(
'name' => 'Zend\Filter\DatetimeFormatter',
'options' => array (
'format' => 'd/m/Y',
),
),
),
'validators' => array(
array(
'name' => Date::class,
'options' => array(
'format' => 'd/m/Y'
)
)
)
)
);
}
}
And here is my PessoaJuridicaFieldset
/**
* Fieldset com dados específicos para a pessoa jurídica
*
* #author Rodrigo Teixeira Andreotti <ro.andriotti#gmail.com>
*/
class PessoaJuridicaFieldset extends PessoaFieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $em,
\User\Form\UserFieldset $userFs, PessoaEnderecoFieldset $enderecoFs,
\Common\Form\ContatoFieldset $contatoFs)
{
parent::__construct($em, $userFs, $enderecoFs, $contatoFs);
$this->init();
}
public function init()
{
parent::init();
$this
->setObject(new PessoaJuridica());
$this->get('tipo')->setValue(\Pessoa\Entity\Pessoa::PESSOA_JURIDICA);
$this->add(array(
'type' => 'Text',
'name' => 'cnpj',
'options' => array(
'label' => 'CNPJ',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtCnpj'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'razaoSocial',
'options' => array(
'label' => 'Razão Social',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtRazaoSocial'
)
));
$this->add(array(
'type' => 'Text',
'name' => 'nomeFantasia',
'options' => array(
'label' => 'Nome Fantasia',
'label_attributes' => array(
'class' => 'col-sm-12'
)
),
'attributes' => array(
'class' => 'form-control form-control-line',
'id' => 'txtNomeFantasia'
)
));
}
public function getInputFilterSpecification(): array
{
return array(
'razaoSocial' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'nomeFantasia' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
)
),
'cnpj' => array(
'required' => true,
'filters' => array(
['name' => 'StripTags'],
['name' => 'StringTrim']
),
'validators' => array(
['name' => CnpjValidator::class]
)
)
);
}
}
And to complete I did the entity type treatment on the Controller that will load this form, as below: (only relevant parts)
//...
if ($id) {
$cliente = $this->repository->getById($id);
$form->remove('pessoa');
// loads form according to the type loaded from the database
if (!$request->isXmlHttpRequest()) {
if ($cliente->getPessoa() instanceof \Pessoa\Entity\PessoaFisica) {
$form->add($this->pessoaFisicaFieldset);
} elseif ($cliente->getPessoa() instanceof \Pessoa\Entity\PessoaJuridica) {
$form->add($this->pessoaJuridicaFieldset);
}
var_dump($cliente->getPessoa());
}
$form->bind($cliente);
}
if ($request->isPost()) {
$form->remove('pessoa');
// loads form according to the type selected in the post
if ($request->getPost('tipo') == \Pessoa\Entity\Pessoa::PESSOA_FISICA) {
$form->add($this->pessoaFisicaFieldset);
} elseif ($request->getPost('tipo') == \Pessoa\Entity\Pessoa::PESSOA_JURIDICA) {
$form->add($this->pessoaJuridicaFieldset);
}
$form->get('tipo')->setValue($request->getPost('tipo'));
$form->setData($request->getPost());
if(!$request->isXmlHttpRequest()) {
if ($form->isValid()) {
$cliente = $form->getObject();
if ($cliente->getId() != 0) {
$cliente->getPessoa()->setCadastradoEm(new \DateTime);
}
// ...
}
}
}
//...
Again, thanks #rkeet!
My data transformer receives null values in all cases but those with 'multiple'=>true.
For now I'm just trying to var_dump the values.
This is my form:
$entitiesClasses = array(
'AppBundle\Entity\Category' => array( 'label' => 'entity.vehicle.category' ),
'AppBundle\Entity\Specific\ExteriorColor' => array( 'label' => 'entity.specific.exteriorColor' ),
'AppBundle\Entity\Specific\DoorCount' => array( 'label' => 'entity.specific.doorCount' ),
'AppBundle\Entity\Specific\Fuel' => array( 'label' => 'entity.specific.fuel' ),
'AppBundle\Entity\Specific\Gearbox' => array( 'label' => 'entity.specific.gearbox' ),
'AppBundle\Entity\Specific\Climatisation' => array( 'label' => 'entity.specific.climatisation' ),
'AppBundle\Entity\Specific\WheelFormula' => array( 'label' => 'entity.specific.wheelFormula' ),
'AppBundle\Entity\Specific\InteriorColor' => array( 'label' => 'entity.specific.interiorColor' ),
'AppBundle\Entity\Specific\InteriorType' => array( 'label' => 'entity.specific.interiorType' ),
'AppBundle\Entity\Specific\ParkingAssistant' => array( 'label' => 'entity.specific.parkingAssistant', 'multiple' => true ),
'AppBundle\Entity\Feature' => array( 'label' => 'entity.vehicle.features', 'multiple' => true ),
);
$getEntityInputName = function($className) {
$test = preg_split('/\\\/', $className);
return lcfirst(end($test));
};
foreach($entitiesClasses as $className => $options) {
$inputName = $getEntityInputName($className);
isset($options['multiple']) && $options['multiple'] == true? $inputName .= 's' : null;
$formMapper->add(
$formMapper->getFormBuilder()->create($inputName, 'entity',
array_merge(
$options,
array(
'required' => false,
'class' => $className,
'query_builder' => $query_builder,
))
)->addModelTransformer(new EntityTranslationTransformer($this->em))
This is my transformer:
namespace AppBundle\Form\DataTransformer;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
class EntityTranslationTransformer implements DataTransformerInterface
{
/**
* #var EntityManager
*/
private $em;
/**
* #var mixed $entity
*/
private $entity;
/**
* #param EntityManager $em
* #param string $entity
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function transform($value)
{
if ($value === null) {
return null;
}
return $value;
}
Any idea why this is happening and how to fix it?
if you read here
http://symfony.com/doc/current/cookbook/form/data_transformers.html#creating-the-transformer
transform should change an object into string(an entity to its id), try it as it is in the docs
public function transform($value)
{
if (null === $value) {
return "";
}
return $value->getId();
}
In addition, why do you need a transformer for an entity type field?
So I've a problem that made me crazy :(, I create a form and when I use the class form in my controller I got this error:
Fatal error: Class 'Application\forms\ArticleForm' not found in C:\wamp2\www\test\module\Application\src\Application\Controller\BlogController.php
and even when I try to use Application\forms\ArticleForm this path doesn't found, this is a part of my action : Update the code :
public function addAction()
{
$form = new ArticleForm();// here the class doesn't found !!
//var_dump($form);die;
$form->initForm();
$request = $this->getRequest();
$form->setData($request->getPost());
And this is my ArticleForm :
class ArticleForm extends Form {
public function __construct()
{
parent::__construct('UserEntry');
$this->setAttribute('method', 'post');
$this->setAttribute('enctype', 'multipart/form-data');
$this->setAttribute('class', 'contact_form');
}
public function initForm()
{
$this->addFormFields(); //function where we added all fields
$articleInputFilter = new ArticleInputFilter();
$this->setInputFilter($articleInputFilter->getInputFilter()); //Asign input Filter to form
}
protected function addFormFields()
{
$this->addSubmit();
$this->addTitle();
$this->addContent();
$this->addDate();
$this->addPublication();
$this->addImage();
}
/**
*
*/
protected function addTitle()
{
$this->add(array(
'name' => 'title',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => _('Title')
),
));
}
/**
*
*/
protected function addContent()
{
$this->add(array(
'name' => 'content',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => _('Content')
),
));
}
/**
*
*/
protected function addDate()
{
$this->add(array(
'name' => 'date',
'attributes' => array(
'type' => 'date',
),
'options' => array(
'label' => _('Date'),
'id' => 'datepicker',
),
));
}
/**
*
*/
protected function addPublication()
{
$this->add(array(
'name' => 'publication',
'attributes' => array(
'type' => 'checkbox',
),
'options' => array(
'label' => _('Publication'),
'use_hidden_element' => true,
'checked_value' => 1,
'unchecked_value' => 'no',
),
));
}
/**
*
*/
protected function addImage()
{
$this->add(array(
'name' => 'Image',
'attributes' => array(
'type' => new ImageForm(),
),
'options' => array(
'label' => _('Image')
),
));
}
/**
*
*/
protected function addSubmit()
{
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => _('Add'),
'class' => 'submit',
),
));
}
}
Finally this is my ArticleInputFilter :
class ArticleInputFilter extends InputFilter implements InputFilterAwareInterface
{
/**
* #var string
*/
public $title;
/**
* #var int
*/
public $image;
/**
* #var string
*/
public $content;
/**
* #var Date
*/
public $date;
/**
* #var Boolean
*/
public $publication;
/**
* #param $data
*/
public function exchangeArray($data)
{
$this->title = (isset($data['title'])) ? $data['title'] : $this->title;
$this->image = (isset($data['image'])) ? $data['image'] : $this->image;
$this->content = (isset($data['content'])) ? $data['content'] : $this->content;
$this->publication = (isset($data['publication'])) ? $data['publication'] : $this->publication;
$this->date = (isset($data['date'])) ? $data['date'] : $this->date;
}
/**
* #param InputFilterInterface $inputFilter
* #return void|InputFilterAwareInterface
* #throws \Exception
*/
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
/**
* #return InputFilter|InputFilterInterface
*/
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'title',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 6,
'max' => 100,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'content',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 10,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'publication',
'required' => false,
)));
$inputFilter->add($factory->createInput(array(
'name' => 'date',
'required' => true,
)));
$inputFilter->add($factory->createInput(array(
'name' => 'image',
'required' => true,
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
So please if someone has any idea or solution to my problem I will be very appreciative.
Probably an autoloading problem.
Where is defined your ArticleForm ?
Note : you'd better use the form element manager to get form instance. You can read more on this subject here
I had the same problem. The answer is pretty simple. The problem is in the autoloader so you need to "refresh" or "sincronyze everything" before you get started. So at the top of the function addAction() or the file just require the autoload.php file that is inside of the vendor folder to "update" your project. Something like this:
require 'vendor/autoload.php';
Obviously, you need to write your own path.
I hope that would help.
So i work in a Zend Framework project and i am using Doctrine, i create my Form, Controller and Entities, but when i run my project i got this error :
Object provided to Escape helper, but flags do not allow recursion
This is my Entity :
namespace Application\Entity;
use Doctrine\ORM\Mapping as ORM;
use Zend\Form\Annotation;
/**
* Article
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Application\Entity\ArticleRepository")
*/
class Article
{
/**
* #ORM\Column(name="publication", type="boolean")
*/
private $publication;
public function __construct()
{
$this->date = new \Datetime();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="date")
*/
private $date;
/**
* #var string
*
* #ORM\Column(name="content", type="text")
*/
private $content;
/**
* #ORM\OneToOne(targetEntity="Application\Entity\Image", cascade={"persist","remove"})
*/
private $image;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return Article
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set date
*
* #param \DateTime $date
* #return Article
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set content
*
* #param string $content
* #return Article
*/
public function setContent($content)
{
$this->content = $content;
return $this;
}
/**
* Get content
*
* #return string
*/
public function getContent()
{
return $this->content;
}
/**
* Set publication
*
* #param boolean $publication
* #return Article
*/
public function setPublication($publication)
{
$this->publication = $publication;
return $this;
}
/**
* Get publication
*
* #return boolean
*/
public function getPublication()
{
return $this->publication;
}
/**
* Set image
*
* #param \Application\Entity\Image $image
* #return Article
*/
public function setImage(\Application\Entity\Image $image = null)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return \Application\Entity\Image
*/
public function getImage()
{
return $this->image;
}
}
And this is Form with fields validation:
class ArticleForm extends Form implements ObjectManagerAwareInterface
{
/**
* #var EntityManager
*/
protected $em;
public function init()
{
$this->add(array(
'name' => 'title',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Title'
),
));
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$this->add(array(
'name' => 'content',
'attributes' => array(
'type' => 'textera',
),
'options' => array(
'label' => 'Content'
),
));
$this->add(array(
'name' => 'date',
'attributes' => array(
'type' => 'text',
'class' => 'datepicker',
),
'options' => array(
'label' => 'Date',
),
));
$this->add(array(
'name' => 'publication',
'attributes' => array(
'type' => 'Checkbox',
),
));
$this->add(array(
'name' => 'url',
'attributes' => array(
'type' => 'file',
'id' => 'files',
'class'=> 'upload'
),
'options' => array(
'label' => 'Url'
),
));
$this->add(array(
'name' => 'alt',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Alt'
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'class' => 'submit',
),
));
$this->setInputFilter($this->createInputFilter());
}
public function __construct($name = null, $options = array())
{
parent::__construct($name, $options);
}
public function createInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'title',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 6,
'max' => 100,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'content',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 10,
),
),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'publication',
'required' => false,
)));
$inputFilter->add($factory->createInput(array(
'name' => 'date',
'required' => true,
)));
$inputFilter->add($factory->createInput(array(
'name' => 'image',
'required' => true,
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
public function setObjectManager(ObjectManager $objectManager) {
$this->objectManager = $objectManager;
}
/**
* Get the object manager
*
* #return ObjectManager
*/
public function getObjectManager() {
return $this->objectManager;
}
}
Then my Action :
public function addAction()
{
$form = new ArticleForm($this->getObjectManager());
$article = new Article();
$request = $this->getRequest();
$hydrator = new DoctrineHydrator($this->getObjectManager(), get_class($article));
$form->setHydrator($hydrator);
$form->bind($article);
if ($this->zfcUserAuthentication()->hasIdentity()) {
if ($request->isPost())
{
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getObjectManager()->persist($article);
$this->getObjectManager()->flush();
return $this->redirect()->toRoute('blog');
}
}
}
else
{
return $this->redirect()->toRoute('user');
}
return array('form' => $form);
}
Finally my View where i think i have an error :
<?php
$form = $this->form;
$form->setAttribute('action', $this->url('add', array('action' => 'add')));
$form->prepare();
?>
<?php
echo $this->form()->openTag($form);
?>
<ul>
<li>
<?php echo $this->formHidden($form->get('id'));?>
<li>
<li>
<label>Publication:</label>
<?php echo $this->formInput($form->get('publication'));?>
</li>
<li>
<label>Title:</label>
<?php echo $this->formInput($form->get('title'));?>
</li>
// ....
<li>
<?php echo $this->formSubmit($form->get('submit'));?></li>
</ul>
<?php
echo $this->form()->closeTag();
?>
That it's, this is almost my codes, i tried everything and i didn't found any solution, and i think the error in my view, so please if someone has any idea i will be very appreciative
its propably because of the date-object.
try to change the type of the form element to date:
$this->add(array(
'name' => 'date',
'type' => 'Date',
'attributes' => array(
'type' => 'text',
'class' => 'datepicker',
),
'options' => array(
'label' => 'Date',
),
));
You can get this error when you set an object as attribute instead of a string:
$element->setAttribute('class', $object)
where $element can be a Form, Fieldset or Element
In general, Object provided to Escape helper, but flags do not allow recursion means that the Escape view helper was expecting, but did not get, either a scalar or an object with a __toString() method. It's a fancy way of saying "dude, I can't print this."
The solution is to either do your own rendering (without using the form view helpers), or ensure that the form element value is something you can echo.
You have an init function. Comment out your __construct function and write it like this:
public function __construct(ObjectManager $em, $name = null, $options = array())
{
$this->setObjectManager($em);
parent::__construct($name, $options);
//here you add all the form elements
//(meaning: just put all the content of your init() function here)
//if that's a construct function, you also need to add:
//private $inputFilter;
//at the top of your class, it is not declared in your code
}
Here's the construct function you provided:
public function __construct($name = null, $options = array())
{
parent::__construct($name, $options);
}
The error was thrown, because you wrote:
$form = new ArticleForm($this->getObjectManager());
So the first parameter you passed to the __construct function was an instance of objectManager, and when it was processed in Zend\View\Helper\Escaper\AbstractHelper, there was something wrong. I can't tell you exactly what's going on there, but if you declare the __construct function as I demonstrated, everything works fine.