3

我一直在考虑一种处理对apigility资源的POST请求中的嵌套/复杂值的好方法。

例如,一个订单可能在一个请求的用于创建订单的 POST 中包含一组订单项。order 和 order-item 都作为资源存在。但是,我非常希望只有一个请求可以创建订单和订单项目实体。在资源中处理它不是问题,但我想知道您将如何使用 apigiliy UI 配置该资源(让我们称之为 order-place) - 或者,如果根本不可能,使用配置。应用验证器和过滤器是 apigility 的关键特性之一,我想继续使用它,即使是复杂的请求数据。

在你问之前,使用下划线分隔值范围,例如 order_comment 和 order_item_comment 不应该是一个选项。

有任何想法吗?:)

另外:一个示例 json 请求有效负载可能如下所示:

{
"created_at": "2000-01-01",
"amount" : "5000.00",
"address" : {
    "name": "some name",
    "street": "some street"
    ...
},
"items" : [
    {"productId":99,"qty":1}
    ...
]
}
4

2 回答 2

3

从威尔特的回答开始,我发现以下代码也有效:

# file path: /module/MyApi/config/module.config.php

// some other stuff

  'MyApi\\V1\\Rest\\MyRestService\\Validator' => array(
       'address' => array(
            0 => array(
                'name'     => 'name',
                'required' => true,
                'filters'  => array(),
                'validators' => array(),
            ),
            1 => array(
                'name'     => 'street',
                'required' => true,
                'filters'  => array(),
                'validators' => array(),
            ),
            'type' => 'Zend\InputFilter\InputFilter'
        ),
        'amount' => array(
            'name'       => 'amount',
            'required'   => true,
            'filters'    => array(),
            'validators' => array()
        )

我得到的唯一问题是何时address作为字段(字符串或数字)而不是数组或对象传递。在这种情况下,Apigility 会抛出异常:

Zend\InputFilter\Exception\InvalidArgumentException: Zend\InputFilter\BaseInputFilter::setData 需要一个数组或 Traversable 参数;在第 175 行的 /var/www/api/vendor/zendframework/zendframework/library/Zend/InputFilter/BaseInputFilter.php 中收到字符串

添加address一个更简单的(必需的)字段可以避免异常,但是 Apigility 看不出我们是否address作为一个数组传递namestreet或一个虚拟字符串有任何区别。

于 2015-02-11T15:27:56.127 回答
2

If you are using the ContentValidation module then you can configure an input filter for the nested resources by assigning it to a variable. Then you have to add a type key (essential otherwise reusing the filter won't work). Now you are able to use this variable in your input_filter_specs and you can reuse the whole filter inside another filter. So something like this in your config.php:

<?php

namespace Application;

// Your address config as if it was used independently
$addressInputFilter => array(
    'name' => array(
        'name' => 'name',
        'required' => true,
        'filters' => array(
            //...
        )
        'validators' => array(
            //...
        )
    ),
    'street' => array(
        'name' => 'street',
        'required' => true,
        'filters' => array(
            //...
        )
        'validators' => array(
            //...
        )
    ),
    // 'type' key necessary for reusing this input filter in other configs
    'type' => 'Zend\InputFilter\InputFilter'
),


'input_filter_specs' => array(
    // The key for your address if you also want to be able to use it independently
    'Application\InputFilter\Address'=> $addressInputFilter,
    // The key and config for your other resource containing a nested address
    'Application\InputFilter\ItemContainingAddress'=> array(
        'address' => $addressInputFilter,
        'amount' => array(
            'name' => 'amount',
            'required' => true,
            'filters' => array(
                //...
            ),
            'validators' => array(
                //...
            )
        )
        //... your other fields
    )
)
于 2014-12-08T09:20:56.493 回答