0
votes

I am working on an Order which has an OrderPerson and a PersonAddress associated to it:

Order -> OrderPerson
Order -> PersonAddress

The PRG when dumped looks like this:

array (size=4)
  'csrfcheck' => string '' (length=65)
  'order' => 
    array (size=4)
      'id' => string '' (length=0)
      'orderPerson' => 
        array (size=9)
          'id' => string '0' (length=1)
          'firstname' => string '' (length=0)
          'surname' => string '' (length=0)... etc
      'personAddress' => 
        array (size=9)
          'id' => string '0' (length=1)
          'address' => string '' (length=0)
          'country' => string '197' (length=3)... etc
      'deliveryNote' => string '' (length=0)
  'deliveryMethod' => string '2' (length=1)
  'submit' => string 'Confirm Details And Make Payment' (length=32)

What I want to do is add InPutFilters to OrderPersonFieldSet.php and PersonAddressFieldSet.php.

I have an InputFilter on the CheckoutForm for OrderFieldSet however I am unsure how to add to the other fieldsets?

Here are the details:

Now to create this object in one go I have created the following classes:

CheckoutForm.php
OrderFieldSet.php
OrderPersonFieldSet.php
PersonAddressFieldSet.php

Here are the details:

CheckoutForm.php

<?php
namespace MyCart\Form;

use Zend\Form\Element;
use Zend\Form\Form;
use Zend\InputFilter\InputFilterInterface;

class CheckoutForm extends Form
{

    public function __construct(
        InputFilterInterface $orderFilter,
        $name = null,
        $options = array()
    ) {
        parent::__construct('checkout', $options);

        $this->orderFilter = $orderFilter;
    }

    public function init()
    {
        $this->add(
            [
                'name' => 'csrfcheck',
                'type' => 'csrf',
                'csrf_options' => [
                    'message' => 'The sender verification credentials have expired, please re-submit the form.',
                    'timeout' => 1200
                ]
            ]
        );

        $this->add(
            [
                'name' => 'order',
                'type' => OrderFieldset::class,
                'options' => [
                    'use_as_base_fieldset' => true
                ]
            ]
        );

        $this->add(
            [
                'name'       => 'submit',
                'type'       => 'submit',
                'attributes' => [
                    'value' => 'Update',
                    'class' => 'form-element'
                ]
            ]
        );

        $this->getInputFilter()->add($this->orderFilter, 'order');


    }
}

OrderFieldSet.php

<?php
namespace MyCart\Form;

use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use MyCart\Entity\Order;
use Zend\Form\Element;
use Zend\Form\Fieldset;

class OrderFieldset extends Fieldset
{
    /**
     * @var \Doctrine\Common\Persistence\ObjectManager
     * @access protected
     */
    protected $objectManager;

    /**
     * @param ObjectManager $objectManager
     * @param Order $orderPrototype
     * @param null $name
     * @param array $options
     */
    public function __construct(
        ObjectManager   $objectManager,
        Order           $orderPrototype,
        $name           = null,
        $options        = array()
    ) {
        parent::__construct($name, $options);

        $this->objectManager = $objectManager;
        $this->setHydrator(new DoctrineObject($objectManager));
        $this->setObject($orderPrototype);
    }

    public function init()
    {

        $this->add(
            [
                'name'       => 'id',
                'type'       => 'hidden',
            ]
        );


        $this->add(
            [
                'name' => 'orderPerson',
                'type' => OrderPersonFieldset::class,
            ]
        );

        $this->add(
            [
                'name' => 'personAddress',
                'type' => PersonAddressFieldset::class,
            ]
        );

        $this->add(
            [
                'name'       => 'deliveryNote',
                'type'       => 'textarea',
                'options'    => [
                    'label' => 'Delivery Note',
                    'instructions' => 'While a delivery note is not required, it may be helpful.',
                ],
                'attributes' => [
                    'class' => 'form-control',
                    'rows'  => '5',
                    'id'    => 'delivery-note',
                ]
            ]
        );



    }
} 

OrderPersonFieldset.php

<?php
namespace MyCart\Form;

use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use MyCart\Entity\OrderPerson;
use RoleBasedUser\Form\UserFieldset;
use Zend\Form\Element;
use Zend\Form\Fieldset;

class OrderPersonFieldset extends Fieldset
{
    /**
     * @var \Doctrine\Common\Persistence\ObjectManager
     * @access protected
     */
    protected $objectManager;

    /**
     * @param ObjectManager $objectManager
     * @param OrderPerson $orderPrototype
     * @param null $name
     * @param array $options
     */
    public function __construct(
        ObjectManager   $objectManager,
        OrderPerson     $orderPrototype,
        $name           = null,
        $options        = array()
    ) {
        parent::__construct($name, $options);

        $this->objectManager = $objectManager;
        $this->setHydrator(new DoctrineObject($objectManager));
        $this->setObject($orderPrototype);
    }

    public function init()
    {

        $this->add(
            [
                'name'       => 'id',
                'type'       => 'hidden',
            ]
        );

//        $this->add(
//            [
//                'name'       => 'rbuUser',
//                'type'       => UserFieldset::class,
//            ]
//        );

        $this->add([
            'type' => 'Toolbox\Library\Form\View\Helper\MyObjectHidden',
            'name' => 'rbuUser',
            'options' => [
                'object_manager' => $this->objectManager,
                'target_class' => 'RoleBasedUser\Entity\User'
            ]
        ]);

        $this->add(
            [
                'type' => 'text',
                'name' => 'companyName',
                'attributes' => [
                    'class'     => 'form-control',
                ],
                'options' => [
                    'label'  => 'Company Name',
                    'instructions' => 'This is optional',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'vatNumber',
                'attributes' => [
                    'class'     => 'form-control',
                ],
                'options' => [
                    'label'  => 'Vat Number',
                    'instructions' => 'This is optional',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'email',
                'attributes' => [
                    'class'     => 'form-control',
                    'required' => 'required',
                ],
                'options' => [
                    'label'  => 'Email Address',
                    'instructions' => 'Please enter your email address',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'firstname',
                'attributes' => [
                    'class'     => 'form-control',
                    'required' => 'required',
                ],
                'options' => [
                    'label'  => 'First Name',
                    'instructions' => 'Please enter your first name',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'surname',
                'attributes' => [
                    'class'     => 'form-control',
                    'required' => 'required',
                ],
                'options' => [
                    'label'  => 'Last Name',
                    'instructions' => 'Please enter your last name',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'tell',
                'attributes' => [
                    'class'     => 'form-control',
                    'required' => 'required',
                ],
                'options' => [
                    'label'  => 'Telephone',
                    'instructions' => 'Please enter your land line number',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'cell',
                'attributes' => [
                    'class'     => 'form-control',
                    'required' => 'required',
                ],
                'options' => [
                    'label'  => 'Mobile',
                    'instructions' => 'Please enter your mobile number',
                ],
            ]
        );

    }
} 

PersonAddressFieldset.php

<?php
namespace MyCart\Form;

use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject;
use MyCart\Entity\PersonAddress;
use Zend\Form\Element;
use Zend\Form\Fieldset;

class PersonAddressFieldset extends Fieldset
{
    /**
     * @var \Doctrine\Common\Persistence\ObjectManager
     * @access protected
     */
    protected $objectManager;

    /**
     * @param ObjectManager $objectManager
     * @param PersonAddress $orderPrototype
     * @param null $name
     * @param array $options
     */
    public function __construct(
        ObjectManager   $objectManager,
        PersonAddress   $orderPrototype,
        $name           = null,
        $options        = array()
    ) {
        parent::__construct($name, $options);

        $this->objectManager = $objectManager;
        $this->setHydrator(new DoctrineObject($objectManager));
        $this->setObject($orderPrototype);
    }

    public function init()
    {

        $this->add(
            [
                'name'       => 'id',
                'type'       => 'hidden',
            ]
        );

        $this->add(
            [
                'name' => 'orderPerson',
                'type' => OrderPersonFieldset::class,
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'address',
                'attributes' => [
                    'class'     => 'form-control',
                    'required'  => 'required'
                ],
                'options' => [
                    'label'  => 'Delivery address',
                    'instructions' => 'Please enter your delivery address',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'city',
                'attributes' => [
                    'class'     => 'form-control'
                ],
                'options' => [
                    'label'  => 'City',
                    'instructions' => 'Delivery city',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'postCode',
                'attributes' => [
                    'class'     => 'form-control'
                ],
                'options' => [
                    'label'  => 'Post Code',
                    'instructions' => 'Delivery post code',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'text',
                'name' => 'region',
                'attributes' => [
                    'class'     => 'form-control',
                    'required' => 'required',
                ],
                'options' => [
                    'label'  => 'Region',
                    'instructions' => 'Enter your region',
                ],
            ]
        );

        $this->add(
            [
                'type' => 'DoctrineModule\Form\Element\ObjectSelect',
                'name' => 'country',
                'options' => [
                    'object_manager' => $this->objectManager,
                    'target_class'   => 'Toolbox\Entity\Countries',
                    'property'       => 'name',
                    'label' => 'Country',
                    'instructions' => 'Your country'

                ],
                'attributes' => [
                    'class'     => 'form-control',
                    'options' => [
                        '197' => 'South Africa'
                    ],
                    'multiple' => false,
                ]
            ]
        );


    }
} 
1

1 Answers

0
votes

There are a number of ways to solve this issue. The firs is as IslandDev has suggested. This I felt was too much of a hack although it worked perfectly fine.

The second is as per the ZF2 manual, you can find it here and another similar one here: While this worked I felt the solution limited the use of filters. Ideally you want to be able to re-use InputFilters in different scenarios and the solution suggested by the manual did not allow for this, so in my opinion, it is a hack too.

What I did to solve this was actually very simple:

In my OrderFieldset.php class I implemented the InputAwareInterfac to give me access to both setInputFilter and getInputFilter (which is normally available in a traditional Form class).

I then injected an orderPersonFilter and a personAddressFilter.

The new class looks like this:

<?php namespace MyCart\Form;

use Doctrine\Common\Persistence\ObjectManager; 
use DoctrineModule\Stdlib\Hydrator\DoctrineObject; 
use MyCart\Entity\Order; 
use Zend\Form\Element; 
use Zend\Form\Fieldset; 
use Zend\InputFilter\InputFilter; 
use Zend\InputFilter\InputFilterAwareInterface; 
use Zend\InputFilter\InputFilterInterface;

class OrderFieldset extends Fieldset implements InputFilterAwareInterface {

    /**
     * @var \Doctrine\Common\Persistence\ObjectManager
     * @access protected
     */
    protected $objectManager;

    /**
     * @var
     */
    protected $inputFilter;

    /**
     * @param ObjectManager $objectManager
     * @param Order $orderPrototype
     * @param InputFilterInterface $orderPersonFilter
     * @param InputFilterInterface $personAddressFilter
     * @param null $name
     * @param array $options
     */
    public function __construct(
        ObjectManager   $objectManager,
        Order           $orderPrototype,
        InputFilterInterface $orderPersonFilter,
        InputFilterInterface $personAddressFilter,
        $name           = null,
        $options        = array()
    ) {
        parent::__construct($name, $options);

        $this->objectManager = $objectManager;
        $this->setHydrator(new DoctrineObject($objectManager));
        $this->setObject($orderPrototype);
        $this->orderPersonFilter = $orderPersonFilter;
        $this->personAddressFilter = $personAddressFilter;

        $this->inputFilter = new InputFilter();
    }

    public function init()
    {

        $this->add(
            [
                'name'       => 'id',
                'type'       => 'hidden',
            ]
        );


        $this->add(
            [
                'name' => 'orderPerson',
                'type' => OrderPersonFieldset::class,
            ]
        );

        $this->add(
            [
                'name' => 'personAddress',
                'type' => PersonAddressFieldset::class,
            ]
        );

        $this->add(
            [
                'name'       => 'deliveryNote',
                'type'       => 'textarea',
                'options'    => [
                    'label' => 'Delivery Note',
                    'instructions' => 'While a delivery note is not required, it may be helpful.',
                ],
                'attributes' => [
                    'class' => 'form-control',
                    'rows'  => '5',
                    'id'    => 'delivery-note',
                ]
            ]
        );

        $this->getInputFilter()->add($this->orderPersonFilter, 'orderPerson');
        $this->getInputFilter()->add($this->personAddressFilter, 'personAddress');


    }

    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        $this->inputFilter = $inputFilter;

        return $this;
    }

    /**
     * Retrieve input filter
     *
     * @return InputFilterInterface
     */
    public function getInputFilter()
    {
        return $this->inputFilter;
    }

}

My CheckoutForm.php class needed to be updated as follows:

$this->getInputFilter()->add($this->get('order')->getInputFilter(), 'order');

A nice clean solution and if required, I can use the input filters in other scenarios.