Zend framework2 在Zend Framework 2/3中进行验证之前,如何从Zend\表单获取数据()?

Zend framework2 在Zend Framework 2/3中进行验证之前,如何从Zend\表单获取数据()?,zend-framework2,zend-form,zend-framework3,zend-validate,Zend Framework2,Zend Form,Zend Framework3,Zend Validate,我有一个复杂的嵌套(order)Zend\Form,可以多次编辑。用户首先创建订单,但不需要立即下订单。他只需保存订单(或者更准确地说:订单数据)并在以后编辑即可。在这种情况下,应用程序加载一个Order对象(及其所有嵌套结构),并将其保存到表单中。重要的步骤是: 从请求中获取订单的ID 通过ID $orderForm->bind($orderObject) 现在我想捕获数据并将其序列化为JSON。(背景:表单克隆——在下一步中,应创建一个空的新表单,并将表单传递给它;保存后,我们将获得一个克

我有一个复杂的嵌套(order)
Zend\Form
,可以多次编辑。用户首先创建订单,但不需要立即下订单。他只需保存订单(或者更准确地说:订单数据)并在以后编辑即可。在这种情况下,应用程序加载一个
Order
对象(及其所有嵌套结构),并将其保存到表单中。重要的步骤是:

  • 从请求中获取订单的
    ID
  • 通过
    ID
  • $orderForm->bind($orderObject)
  • 现在我想捕获数据并将其序列化为JSON。(背景:表单克隆——在下一步中,应创建一个空的新表单,并将表单传递给它;保存后,我们将获得一个克隆。)它应发生在
    2
    3
    之间。所以我在努力

     $formData = $this->orderForm->getData();
     $formJson = json_encode($formData, JSON_UNESCAPED_SLASHES);
    
    以及获取错误:

    Zend\Form\Form::getData无法返回数据,因为尚未进行验证

    嗯,我可以试着解决这个问题,并验证表单:

    $formIsValid = $this->orderForm->isValid();
    
    但这只会带来更多的麻烦:

    Zend\InputFilter\BaseInputFilter::setData需要一个数组或可遍历参数;接收空值


    是否有办法在验证之前获取表单数据?

    好的,注释空间太小,无法说明您试图归档的内容。让我们重构你在开始文章中提到的每一个步骤。这将引导我们实现你的目标。这都是关于水合作用的

    这将是一个小示例,其中包含产品的订单实体可能是什么样子。在order实体之后是product实体,我们在本例中需要product实体

    namespace Application\Entity;
    
    class Order implements \JsonSerializable 
    {
        /**
         * ID of the order
         * @var integer
         */
        protected $orderID;
    
        /**
         * Array of \Application\Entity\Product         
         * @var array 
         */
        protected $products;
    
        public function getOrderID() : integer
        {
            return $this->orderID;
        }
    
        public function setOrderID(integer $orderID) : Order
        {
            $this->orderID = $orderID;
            return $this;
        }
    
        public function getProducts()
        {
            if ($this->products == null) {
                $this->products = [];
            }
    
            return $this->products;
        }
    
        public function setProducts(array $products) : Order
        {
            $this->products = $products;
            return $this;
        }
    
        /**
         * @see \JsonSerializable::jsonSerialize()
         */
        public function jsonSerialize()
        {
            return get_object_vars($this);
        }
    }
    
    以下实体表示一个产品

    class Product implements \JsonSerializable
    {
        protected $productID;
    
        protected $name;
    
        public function getProductID() : integer
        {
            return $this->productID;
        }
    
        public function setProductID(integer $productID) : Product
        {
            $this->productID = $productID;
            return $this;
        }
    
        public function getName() : string
        {
            return $this->name;
        }
    
        public function setName(string $name) : Product
        {
            $this->name = $name;
            return $this;
        }
    
        /**
         * @see \JsonSerializable::jsonSerialize()
         */
        public function jsonSerialize()
        {
            return get_object_vars($this);
        }
    }
    
    上图是我们的实体,它代表一个订单,其中包含多个可能的产品。第二个成员产品可以是包含产品实体的数组。这个实体代表我们简单订单的数据结构

    此时,我们需要一个表单,它使用这个实体作为它包含的数据的对象。我们表格的可能工厂可能是这样的

    namespace Application\Form\Factory;
    
    class OrderFormFactory implements FactoryInterface
    {
        public function createService(ServiceLocatorInterface $serviceLocator)
        {
            $parentLocator = $serviceLocator->getServiceLocator();
            $inputFilter = $parentLocator->get('InputFilterManager')->get(OrderInputFiler::class);
            $hydrator = new ClassMethods(false);
            $entity = new OrderEntity();
    
            return (new OrderForm())
                ->setInputFilter($inputFilter)
                ->setHydrator($hydrator)
                ->setObject($entity);
        }
    }
    
    这是我们表格的工厂。我们为表单设置了一个查询器、一个输入过滤器和一个实体。所以你不必绑东西。下面的代码显示了如何使用此表单处理数据

    // retrieve an order from database by id
    // This returns a order entity as result
    $order = $this->getServiceLocator()->get(OrderTableGateway::class)->fetchById($id);
    
    // Extract the order data from object to array assumed the
    // retrieved data from data base is an OrderEntity object
    // the hydrator will use the get* methods of the entity and returns an array
    $data = (new ClassMethods(false))->extract($order);
    
    // fill the form with the extracted data
    $form = $this->getServiceLocator()->get('FormElementManager')->get(OrderForm::class);
    $form->setData($data);
    
    if ($form->isValid()) {
    
        // returns a validated order entity
        $order = $form->getData();
    }
    

    从尚未验证的表单中获取数据是绝对不可能的。您必须验证表单数据,然后才能从表单中获取经过筛选/验证的数据。当您必须处理大量数据时,编辑器和实体将为您提供很大帮助。

    最后一条错误消息显示,您要使用setData方法设置的数据为空。在验证表单之前,必须向表单提供数据。让我们重构您的方式。首先:获取订单的ID。第二个:通过ID获取order对象。第三个:使用编辑器从order对象提取数据。第四:通过表单的setData方法将提取的数据(数组)提供给表单。第五:验证它。第六:通过getData方法获取表单中经过过滤、验证的数据。不能将order对象直接绑定到窗体。