从zf-rest模块的_embedded资源中删除'_links'属性

时间:2018-10-17 12:54:24

标签: php rest zend-framework zend-framework2

我正在将ZF2与"zfcampus/zf-rest":"1.2.0"一起使用以返回API结果。

对于名为Tag的资源,我收到以下响应:

{
    "_links": {
        "self": {
            "href": "http://mydomain/article/tags"
        }
    },
    "_embedded": {
        "tags": [
            {
                "id": 1,
                "tag": "news",
                "isOfficial": true,
                "_links": {
                    "self": {
                        "href": "http://mydomain/article/tags"
                    }
                }
            }
        ]
    },
    "total_items": 1
}

但是,我想摆脱标签资源下的_links属性,以便获得更干净的输出。

我想要实现的目标看起来像这样;

{
    "_links": {
        "self": {
            "href": "http://mydomain/article/tags"
        }
    },
    "_embedded": {
        "tags": [
            {
                "id": 1,
                "tag": "news",
                "isOfficial": true
            }
        ]
    },
    "total_items": 1
}

如何实现此行为?

请注意,端点的路由器实现为:

'api.rest.article.tags' => [
                'type'    => 'Segment',
                'options' => [
                    'route'    => '/article/tags',
                    'defaults' => [
                        'controller' => 'Api\V1\ArticleTag\Controller',
                    ],
                ],
            ],

2 个答案:

答案 0 :(得分:1)

在使用ZF Hal时,您将得到这样的渲染结果,因为自链接是Hal-Json标准的重要组成部分,并且您的Tag被视为Hal资源,并且将按照上面的示例进行渲染。您可能为此类注册了元数据和水化器,并使用它们来提取这样的实体。

如果您不想将Tag呈现为Hal资源,那么您的解决方案就很简单,只需删除该类的元数据和水化器,然后在您的目录中实现一个JsonSerializable接口类,并添加一个返回所需结果的jsonSerialize方法。呈现器将在呈现它的同时调用jsonSerialize ...

当未找到Hydrator且对象实现此JsonSerializable接口时,这是提取对象的后备。

您可以看到here in the extractEntity method

if ($hydrator) {
    return $hydrator->extract($entity);
}
if ($entity instanceof JsonSerializable) {
    return $entity->jsonSerialize();
}

在JsonSerializable上查看此博客文章:https://www.sitepoint.com/use-jsonserializable-interface/

希望这对您有用,如果您不能随意发表评论,我可以看看是否可以建议其他解决方案。

答案 1 :(得分:0)

更新来自OP的评论使此答案变得多余。保留它可能会帮助某人。如果您使用的是完整的Apigility,则适合您。


其中一个是,V1.2。*版本已在July 2016中发布,因此我建议您从更新应用程序开始。

此外,为什么您要尝试“清理”它呢?获取集合时,删除用于检索单个对象的直接链接毫无用处。


您正在执行“ GET / tags”调用(集合),但您想获得一个对象。

要获取单个商品,请执行“ GET / tags /:id”调用,例如“ GET / tags / 1”。

单个项目的响应应该是这样的(可能有所不同,为此使用最新的适应性):

(请注意,本地开发环境,这就是“ http”的原因)

单次通话:“获取http://api.loc/coordinates/1

{
    "latitude": "33.6062068",
    "longitude": "58.7053709",
    "id": 1,
    "_links": {
        "self": {
            "href": "http://api.loc/coordinates/1"
        }
    }
}

催缴电话:“获取http://api.loc/coordinates

{
    "_links": {
        "self": {
            "href": "http://api.loc/coordinates?page=1"
        },
        "first": {
            "href": "http://api.loc/coordinates"
        },
        "last": {
            "href": "http://api.loc/coordinates?page=10"
        },
        "next": {
            "href": "http://api.loc/coordinates?page=2"
        }
    },
    "_embedded": {
        "coordinates": [
            {
                "latitude": "33.6062068",
                "longitude": "58.7053709",
                "id": 1,
                "_links": {
                    "self": {
                        "href": "http://api.loc/coordinates/1"
                    }
                }
            },
            {
                "latitude": "60.1948871",
                "longitude": "19.2423547",
                "id": 2,
                "_links": {
                    "self": {
                        "href": "http://api.loc/coordinates/2"
                    }
                }
            },
            { ... } another 247 results
        ]
    },
    "page_count": 10,
    "page_size": 25,
    "total_items": 249,
    "page": 1
}

链接应使用LinkExtractor类生成,您可以通过配置类来应用策略。如果您使用的是Apigility(使用您提到的zfcampus/zf-rest模块),则可以应用如下策略:

[ ... ] // more config
'doctrine-hydrator' => [
    'Company\\V1\\Rest\\Company\\CompanyHydrator' => [
        'entity_class' => \Path\To\Company::class,
        'object_manager' => 'doctrine.entitymanager.orm_default',
        'by_value' => true,
        'strategies' => [
            'country' => \ZF\Doctrine\Hydrator\Strategy\EntityExtract::class,
            'currency' => \ZF\Doctrine\Hydrator\Strategy\EntityLink::class,
            'currencies' => \ZF\Doctrine\Hydrator\Strategy\CollectionExtract::class,
        ],
[ ... ] // more config

它们是由汤姆·安德森(Tom Anderson)的ZF Doctrine Hydrator包裹提供的。

*Link策略提供了指向对象的链接,例如可以在GET调用中使用的链接。

*Extract策略直接确保将实体合并到结果中并返回而不是链接。


专门用于删除该_links位。如果使用zf-rest是因为使用了Apigility,则链接是由zf-hal的配置引起的,则可以在{{1}中使用'force_self_link' => false选项}配置。这必须按组完成。

请参见this Apigility docs page并搜索“ force_self_link”。

  

force_self_link-布尔值;设置是否应为实体自动生成自引用链接。默认为true(因为推荐)。

我同意docs:建议保持启用状态。


更新来自OP的评论使此答案变得多余。保留它可能会帮助某人。