前言
现在主流的项目开发都是前后端分离,数据通过json对象格式进行传输。但是magento框架,和传统PHP框架相比,区别很大。虽然也支持以RestApi的形式传输数据,但是要么格式并非是传统jsonObject要么就是需要大量的get、set方法。本文就是在此基础上使用插件对原来的数据返回进行了封装,实现了接口可以返回json对象。
前置条件(创建一个可供访问的接口模块)
- 自定义创建一个模块,并在模块下面创建访问的包
模块: /app/code/Mageplaza (路径固定,名称随便取)
包:/app/code/Mageplaza/JsonReturn
- 定义接口
创建接口文件:/app/code/Mageplaza/JsonReturn/Api/JsonDataInterface (路径固定,名字随便起) 一定得是interface文件
- 创建路由
定义di配置文件、webapi 配置文件和 module配置文件
di.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Mageplaza\JsonReturn\Api\JsonDataInterface" type="Mageplaza\JsonReturn\Model\ReturnJson"/>
</config>
module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Mageplaza_JsonReturn" setup_version="1.0.0">
</module>
</config>
webapi.xml
<?xml version="1.0" ?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route method="GET" url="/V1/json-return">
<service class="Mageplaza\JsonReturn\Api\JsonDataInterface" method="returnJsonData"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
- 定义模型用来实现接口
Model:/app/code/Mageplaza/JsonReturn/Model/ReturnJson
<?php
namespace Mageplaza\JsonReturn\Model;
use Mageplaza\JsonReturn\Api\JsonDataInterface;
class ReturnJson implements JsonDataInterface
{
/**
* @inheritDoc
*/
public function returnJsonData()
{
return [
'item' =>
[
[
'name' => '蔡徐坤', 'age' => 234,
'hobby' => ['key' => '唱', '跳', 'rap', '篮球']
],
[
'name' => '坤坤', 'age' => 124,
'hobby' => ['key' => '说唱', '跳高', 'rap', '篮球']
],
],
'msg' => '提示信息',
'code' => 200
];
}
}
- 定义注册文件(必须要 固定的)
/app/code/Mageplaza/JsonReturn/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Mageplaza_JsonReturn',
__DIR__
);
运行发现问题
前置条件创建完成后,清楚缓存,进行升级,在postman进行访问
php bin/magento s:up
在post进行访问
http://{{host}}/rest/V1/json-return 访问api 路径前面需要带上rest
想要的格式是这样的
{
"item": [
{
"name": "蔡徐坤",
"age": 234,
"hobby": {
"key": "唱",
"0": "跳",
"1": "rap",
"2": "篮球"
}
},
{
"name": "坤坤",
"age": 124,
"hobby": {
"key": "说唱",
"0": "跳高",
"1": "rap",
"2": "篮球"
}
}
],
"msg": "提示信息",
"code": 200
}
但最后的结果是这样的
item、msg、code 属性统统消失。前端肯定没法处理这种数据。这就是问题所在。
解决办法:
从网上搜到了一些解决办法,选择了其中一个非常nice的分享出来
外国盆友的解决办法
按照该方法,我们对原来的文件进行修改。
- 新建插件文件
/app/code/Mageplaza/JsonReturn/Plugin/ServiceOutputProcessorPlugin.php (路径固定,文件名随便起)
<?php
namespace Mageplaza\JsonReturn\Plugin;
use Magento\Framework\Webapi\ServiceOutputProcessor;
class ServiceOutputProcessorPlugin
{
public function aroundConvertValue(ServiceOutputProcessor $subject, callable $proceed, $data, $type)
{
if ($type == 'array') {
return $data;
}
return $proceed($data, $type);
}
}
- 修改di.xml 文件
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Mageplaza\JsonReturn\Api\JsonDataInterface" type="Mageplaza\JsonReturn\Model\ReturnJson"/>
<type name="Magento\Framework\Webapi\ServiceOutputProcessor">
<plugin name="mageplaza_jsonReturnplugin" type="Mageplaza\JsonReturn\Plugin\ServiceOutputProcessorPlugin" disabled="false"/>
</type>
</config>
升级项目,进行测试
结果:已经符合预期
新的问题
这种是通过插件,修改了框架原本的返回接口。magento通过插件修改的类,这种形式是对全局生效的。那么就又有问题了,如果之前已有的代码使用了框架最初的返回结果,或者说,今后需要使用框架原生的返回值,那么通过插件修改,会导致原来的项目运行出问题,没法兼容框架代码!!!
解决办法
查看插件代码,发现插件是对 Webapi/ServiceOutputProcessor.php 这个文件进行了 二次封装,主要涉及到的方法是 convertValue
Webapi/ServiceOutputProcessor.php
$result[] = $datum;
这一步就是将原来的返回 关联数组的结构 key=>value 改成了 索引数组 导致了 返回出去的数据 最外面有一层 [] ,并且原先的 item,data等属性全部消失。
插件的写法作用
最终改版
综上所述,了解了 插件的写法原理,我们对插件进行优化,将原先常用的 array返回类型,改成自定义的名字,可以随便填,需要和插件里面的代码保持一致就行。这里我用jsonObject 。
结束语
到此我们就完成了对magento webapi返回值的修改。