0

複雑なネスト(注文)Zend\Formが複数回編集できます。ユーザーは最初に注文を作成しますが、すぐに注文する必要はありません。彼はただ注文(またはより正確にはそのデータ)を保存し、後でそれを編集することができます。この場合、アプリケーションはOrderオブジェクト(すべてのネストされた構造を持つ)をロードし、フォームにbindをロードします。重要なステップは次のとおりです。Zend Framework 2/3で検証する前にZend FormからgetData()を取得する方法は?

  1. ... ID
  2. $orderForm->bind($orderObject) によって

Orderオブジェクトを取得

  • リクエストから順番のIDを取得する今、私はデータをキャッチしたいとJSONにシリアル化します。 (バックグラウンド:フォームのクローニング - 次のステップで空の新しいフォームを作成し、それを渡す必要があります。保存したらクローンを取得します)23の間に起こります。だから私は

    $formData = $this->orderForm->getData(); 
    $formJson = json_encode($formData, JSON_UNESCAPED_SLASHES); 
    

    をしようと、エラーになっています:

    Zend\Form\Form::getData cannot return data as validation has not yet occurred

    まあ、私はそれを回避しようとする可能性があり、validate形式:

    $formIsValid = $this->orderForm->isValid(); 
    

    をそれだけにつながりますさらにトラブル:

    Zend\InputFilter\BaseInputFilter::setData expects an array or Traversable argument; received NULL

    検証の前にフォームデータを取得する方法はありますか?

  • +0

    最後のエラーメッセージには、setDataメソッドで設定するデータがnullであることです。検証する前にフォームにデータを入力する必要があります。あなたの道をリファクターしましょう。最初に、注文のIDを取得します。 2番目:IDで注文オブジェクトを取得します。第三に、水和物を使用してオーダーオブジェクトからデータを抽出する。第4:フォームのsetDataメソッドを使用して、抽出されたデータ(配列)をフォームに渡します。第五:それを検証する。第六:getDataメソッドを使用して、フォームのフィルターにかけられた有効なデータを取得します。注文オブジェクトをフォームに直接バインドすることはできません。 – Marcel

    答えて

    0

    いいえ、コメントスペースは、あなたがアーカイブしようとしていることに関するすべてを言うには小さすぎます。あなたが最初の投稿で言及したすべてのステップをリファクタリングしましょう。これがあなたの目標につながります。それはすべて水和に関するものです。

    これは、商品を含む注文実体がどのように見えるかを示す小さな例になります。注文実体が製品実体に従うと、この例のために必要となる。

    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); 
        } 
    } 
    

    上記のものは、いくつかの可能な製品を含む単一の注文を表しています。 2番目のメンバproductsは、Productエンティティを持つ配列にすることができます。このエンティティは、単純な順序のデータ構造を表します。

    この時点で、フォームには、このエンティティを含むデータのオブジェクトとして使用するフォームが必要です。私たちのフォームのための可能な工場はこのように見えるかもしれません。

    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(); 
    } 
    

    フォームからデータを取得することは絶対にできません。まだ検証されていません。フォームデータを検証する必要があります。その後、フォームからフィルタリング/検証されたデータを取得できます。ハイドレーターとエンティティは、多くのデータを処理する必要があるときに役立ちます。

    関連する問題