У меня проблемы с увлажнением формы. Когда я вытаскиваю свою сущность из базы данных, OrderLinePerson
Поле заполнено правильно с подключенным объектом. При попытке увлажнить форму это не так.
Ниже приведен пример кода:
<?php
namespace SenetOrder\Form;
use ZF2Core\Form\AbstractForm;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use SenetOrder\Entity\OrderLine;
use SenetOrder\Form\OrderLinePersonFieldset;
class OrderLineForm extends AbstractForm
{
protected $organisation;
public function __construct($name, $organisation)
{
$this->organisation = $organisation;
parent::__construct($name);
$this->setAttribute('method', 'post');
$this->setAttribute('class', 'form-horizontal');
}
public function init()
{
$this->setHydrator(new DoctrineHydrator($this->getEntityManager()));
$this->setObject(new OrderLine());
$this->add([
'name' => 'orderLineType',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => [
'object_manager' => $this->getEntityManager(),
'target_class' => 'SenetOrder\Entity\OrderLineType',
'property' => 'name',
'disable_inarray_validator' => true,
'empty_option' => '',
'label' => _('Type'),
'label_attributes' => [
'class' => 'col-lg-3 control-label'
],
],
'attributes' => [
'class' => 'form-control',
],
]);
$this->add(array(
'name' => 'start',
'type' => 'date',
'options' => array(
'label' => _('Start date:'),
'label_attributes' => array(
'class' => 'col-lg-3 control-label'
),
'format' => 'd-m-Y',
),
'attributes' => array(
'type' => 'text',
'class' => 'form-control datepicker',
'placeholder' => 'dd-mm-yyyy',
'value' => date('d-m-Y'),
),
));
$this->add(array(
'name' => 'end',
'type' => 'date',
'options' => array(
'label' => _('End date:'),
'label_attributes' => array(
'class' => 'col-lg-3 control-label'
),
'format' => 'd-m-Y',
),
'attributes' => array(
'type' => 'text',
'class' => 'form-control datepicker',
'placeholder' => 'dd-mm-yyyy',
),
));
$this->add([
'type' => 'SenetOrder\Form\OrderLinePersonFieldset',
]);
$this->add([
'name' => 'submit',
'type' => 'submit',
'options' => [
'label' => _('Save'),
],
'attributes' => [
'class' => 'btn btn-large btn-primary',
],
]);
}
}
Подключенный Fieldset
namespace SenetOrder\Form;
use Zend\Form\Fieldset;
use SenetOrder\Entity\OrderLinePerson;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
class OrderLinePersonFieldset extends Fieldset
{
protected $serviceManager;
public function __construct($name, $entityManager, $serviceManager, $organisation)
{
$this->organisation = $organisation;
$this->serviceManager = $serviceManager;
parent::__construct($name);
$this->setHydrator(new DoctrineHydrator($entityManager));
$this->setObject(new OrderLinePerson());
$this->add([
'name' => 'person',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => [
'disable_inarray_validator' => true,
'object_manager' => $entityManager,
'target_class' => 'SenetPerson\Entity\Person',
'label' => _('Person'),
'label_attributes' => [
'class' => 'col-lg-3 control-label'
],
'value_options' => $this->getOrganisationPersonOptions(),
],
'attributes' => [
'class' => 'form-control',
],
]);
}
protected function getOrganisationPersonOptions()
{
$data = [''];
if(!is_null($this->organisation))
{
$service = $this->serviceManager->get('senetperson_service_person');
$collection = $service->getBySearch(null, null, 'employee')->getResult();
$data = [];
foreach($collection as $person)
{
$data[$person->getPersonId()] = $person->parseFullname();
}
}
return count($data) === 0 ? [''] : $data;
}
}
Действие, как обрабатывать форму
<?php
public function addAction()
{
$orderLine = new OrderLine();
$orderLine->setOrder($this->order);
$request = $this->getRequest();
$form = $this->getServiceLocator()->get('FormElementManager')->get('SenetOrder\Form\OrderLineForm');
$form->bind($orderLine);
// Handle request
if($request->isPost())
{
$form->setData($request->getPost());
if($form->isValid())
{
$orderLine->setCreated(new \DateTime());
var_dump($request->getPost());
var_dump($orderLine);die;
die('hi there ok form');
$this->getEntityManager()->persist($orderLine);
$this->getEntityManager()->flush();
$this->resultMessenger()->addSuccessMessage($this->getTranslator()->translate('The order has been successfully added'));
return $this->redirect()->toRoute('order/view', array('orderId'=>$order->getOrderId()));
}
$this->resultMessenger()->addErrorMessage('There are errors in your form', $form->getMessages());
}
// Set breadcrumb label
$nav = $this->getServiceLocator()->get('breadcrumb_navigation');
$page = $nav->findByLabel(':name');
$page->setLabel($this->order->getName());
return new ViewModel(array(
'form' => $form,
));
}
Выше приведен код, который выполняется. Ниже дампа сущности после $form->setData()
выполнен. Также дамп объекта запроса
<?php
## REQUEST
object(Zend\Stdlib\Parameters)[193]
public 'orderLineType' => string '1' (length=1)
public 'start' => string '01-09-2014' (length=10)
public 'end' => string '29-09-2014' (length=10)
public 'orderLinePerson' =>
array (size=1)
'person' => string '286512' (length=6)
public 'submit' => string '' (length=0)
## ENTITY DUMP
object(SenetOrder\Entity\OrderLine)[861]
protected 'orderLineId' => null
protected 'order' =>
object(SenetOrder\Entity\Order)[864]
protected 'orderId' => string '1' (length=1)
protected 'name' => string 'Hé leuk, orders in ZF2!' (length=24)
protected 'description' => string 'Hé floepert, stiekem verder programmeren he!' (length=45)
protected 'organisation' =>
object(DoctrineORMModule\Proxy\__CG__\SenetOrganisation\Entity\Organisation)[901]
public '__initializer__' =>
object(Closure)[867]
...
public '__cloner__' =>
object(Closure)[868]
...
public '__isInitialized__' => boolean false
protected 'organisationId' => string '6300' (length=4)
protected 'ownerPerson' => null
protected 'otys' => null
protected 'name' => null
protected 'paymentInterval' => null
protected 'vatNumber' => null
protected 'debtor' => null
protected 'invoiceByEmail' => null
protected 'deleted' => null
protected 'created' => null
protected 'addressCollection' => null
protected 'orderCollection' => null
protected 'invoiceCollection' => null
protected 'address' =>
object(DoctrineORMModule\Proxy\__CG__\Application\Entity\Address)[904]
public '__initializer__' =>
object(Closure)[897]
...
public '__cloner__' =>
object(Closure)[896]
...
public '__isInitialized__' => boolean false
protected 'addressId' => string '56' (length=2)
protected 'organisation' => null
protected 'addressType' => null
protected 'otys' => null
protected 'address' => null
protected 'postalcode' => null
protected 'city' => null
protected 'email' => null
protected 'department' => null
protected 'country' => null
protected 'created' => null
protected 'deleted' => null
protected 'person' =>
object(DoctrineORMModule\Proxy\__CG__\SenetPerson\Entity\Person)[933]
public '__initializer__' =>
object(Closure)[900]
...
public '__cloner__' =>
object(Closure)[881]
...
public '__isInitialized__' => boolean false
protected 'personId' => string '286278' (length=6)
protected 'otys' => null
protected 'initials' => null
protected 'firstname' => null
protected 'middlename' => null
protected 'lastname' => null
protected 'position' => null
protected 'birthday' => null
protected 'gender' => null
protected 'file' => null
protected 'created' => null
protected 'deleted' => null
protected 'personRoleCollection' => null
protected 'personOrganisationCollection' => null
protected 'personLogin' => null
protected 'ownedOrderCollection' => null
protected 'personOrderCollection' => null
protected 'personHourCollection' => null
protected 'personPhoneCollection' => null
protected 'personEmailCollection' => null
protected 'personContractCollection' => null
protected 'created' =>
object(DateTime)[862]
public 'date' => string '2014-09-08 11:55:11.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Amsterdam' (length=16)
protected 'orderLineCollection' =>
object(Doctrine\ORM\PersistentCollection)[921]
private 'snapshot' =>
array (size=0)
...
private 'owner' =>
&object(SenetOrder\Entity\Order)[864]
private 'association' =>
array (size=16)
...
private 'em' =>
object(Doctrine\ORM\EntityManager)[351]
...
private 'backRefFieldName' => string 'order' (length=5)
private 'typeClass' =>
object(Doctrine\ORM\Mapping\ClassMetadata)[932]
...
private 'isDirty' => boolean false
private 'initialized' => boolean false
private 'coll' =>
object(Doctrine\Common\Collections\ArrayCollection)[920]
...
protected 'orderLineType' =>
object(SenetOrder\Entity\OrderLineType)[1353]
protected 'orderLineTypeId' => string '1' (length=1)
protected 'name' => string 'Secondment' (length=10)
protected 'start' =>
object(DateTime)[1350]
public 'date' => string '2014-09-01 00:00:00.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Amsterdam' (length=16)
protected 'end' =>
object(DateTime)[1348]
public 'date' => string '2014-09-29 00:00:00.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Amsterdam' (length=16)
protected 'created' =>
object(DateTime)[1354]
public 'date' => string '2014-09-12 12:18:38.000000' (length=26)
public 'timezone_type' => int 3
public 'timezone' => string 'Europe/Amsterdam' (length=16)
protected 'deleted' => null
protected 'orderLinePerson' => null
Чего я хочу достичь, так это того, что orderLinePerson
поле заполнено своим объектом OrderLinePerson
заменить весь набор полей
$this->add([
'type' => 'SenetOrder\Form\OrderLinePersonFieldset',
]);
с элементом внутри этого набора полей:
$this->add([
'name' => 'orderLinePerson',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'options' => [
'disable_inarray_validator' => true,
'object_manager' => $entityManager,
'target_class' => 'SenetPerson\Entity\Person',
'label' => _('Person'),
'label_attributes' => [
'class' => 'col-lg-3 control-label'
],
'value_options' => $this->getOrganisationPersonOptions(),
],
'attributes' => [
'class' => 'form-control',
],
]);
Наборы полей — это наборы элементов, которые представляют свойства связанного объекта.
Так что с вашим конфигом есть объект OrderLine
с зависимым объектом OrderLinePerson
который сам имеет зависимый объект SenetPerson\Entity\Person
, Я думаю, что это не ваше намерение?
Отсутствует orderLinePerson в группе проверки
У меня была похожая настройка с формой, содержащей настраиваемые зависимости Select с БД. Форма не будет автоматически гидрировать объект значениями POST. Я не смог определить причину, поэтому мне пришлось применить обходной путь:
if ($form->isValid() === false){
...show form
}
$hydrator = $form->getHydrator();
$userEntity = $hydrator->hydrate($httpRequest->getPost()->toArray(), $userEntity);
ОБНОВИТЬ:
Я обнаружил, что причина была в том, что я расширял Zend \ Form \ Form и переопределял метод getInputFilter (). Это депопулирует гидратированную сущность. После того, как я создал свои собственные методы для заполнения фильтра и вызвал их, сущность не изменилась.