资讯专栏INFORMATION COLUMN

使用Yii2时遇到的实际问题

fnngj / 3095人阅读

摘要:在使用这个的时候有的数据是需要加上的,因为不然如果内容里面带有了这种就会出问题。修改默认的解析所使用的类为新建的扩展类如果说字符串需要使用的时候需要设置经过本次的修改算是对如何修改和扩展有了一定的认识。

最近一直在学习Yii2框架,可能是一直以来对它的青睐,让我难以对其它框架再产生兴趣,学习中遇到了许多问题,于是把问题和解决办法也记录下来,这样方便以后复习和交流。

目录

扩展XmlResponseFormatter

在原有的Yii2框架上,新建一个api应用

配置Yii2 request Parser使之可以通过Yii::$app->request->post()来接收 xml 和 json的数据

使用 TimestampBehavior 来自动填充 created_at 和 updated_at

扩展XmlResponseFormatter

在做微信接口测试的时候发现,每次返回数据的时候都是自己写的 xml 信息然后 echo 出来,今天突然看到了 Yii::$app->response->format = Response::FORMAT_XML; 原来通过这个就可以设置返回的数据为 xml ,当然 response 这个类在 Controller 里面是没有加载的,所以首先得加载一下 use yiiwebResponse; ,最后把需要返回的数据用数组的形式来返回即可:

response->format = Response::FORMAT_XML;
    return [
            "ToUserName"=>$postObject->FromUserName,
            "FromUserName"=>$postObject->ToUserName,
            "CreateTime"=>time(),
            "MsgType"=>"music",
            "Music"=>[
                "Title"=>$recognition,
                "Description"=>$decode,
                "MusicUrl"=>$musicurl,
                "HQMusicUrl"=>$musicurl,
            ]
        ];
}

这样使用之后发现请求得到的结果是:



    
    
    1416207112
    music
    
        maps maroon5
        120976464.mp3?xcode=7ba3137f5fd742bcba7a6f5a2ffb7764172503013bacbdc8
        http://zhangmenshiting.baidu.com/data2/music/120976464/120976464.mp3?xcode=7ba3137f5fd742bcba7a6f5a2ffb7764172503013bacbdc8
        http://zhangmenshiting.baidu.com/data2/music/120976464/120976464.mp3?xcode=7ba3137f5fd742bcba7a6f5a2ffb7764172503013bacbdc8
    

问题就来了,微信需要的格式是前外层以 ... 来定义的,后来终于在 Response 里面的 formatters 发现了信息,它里面定义了每个类相应的信息,我们可以通过手动指定一些信息来覆盖掉系统默认的。

Yii::$app->response->formatters = [Response::FORMAT_XML=> ["class"=>yiiwebXmlResponseFormatter", "rootTag"=>"xml"];

通过这样设置之后,最外层的 response 终于变成了 xml,又发现了一个问题,那就是我的内容里面根本就没有SimpleXMLElement相关的东西,这个怎么会多出来?回看了一下逻辑代码发现有:

$postObject = simplexml_load_string($postStr, "SimpleXMLElement", LIBXML_NOCDATA);

最后只能在return的时候加上类型转换为字符串,这下终于恢复正常了。

return [
    "ToUserName"=>(string)$postObject->FromUserName,
    "FromUserName"=>(string)$postObject->ToUserName,
    // ...
]

在使用这个的时候有的数据是需要加上 CDataSection() 的,因为不然如果内容里面带有了 < 这种就会出问题。这个确实让我头疼了很久,首先看了一下源代码原来的类 XmlResponseFormatter, 确实无法满足相应的需求,满足不了需求就只能扩展了

step1. 在应用下创建一个 component 目录
step2. 在component目录下新建一个 MyXmlResponseFormatter.php 的文件
step3. 实现这个类

 $value) {
                if (is_int($name) && is_object($value)) {
                    $this->buildXml($element, $value);
                } elseif (is_array($value) || is_object($value)) {
                    $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
                    $element->appendChild($child);
                    // 主要就是修改这一个点,如果值是一个数组,并且含有 CDATA 的,那么就直接创建一个 CdataSection 节点,
                    // 而不把它本身当作列表再回调。
                    if(array_key_exists(self::CDATA, $value)){
                        $child->appendChild(new DOMCdataSection((string) $value[0]));
                    }else{
                        $this->buildXml($child, $value);
                    }
                } else {
                    $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
                    $element->appendChild($child);
                    $child->appendChild(new DOMText((string) $value));
                }
            }
        } else {
            $element->appendChild(new DOMText((string) $data));
        }
    }
}

step4. 修改默认的 xml 解析所使用的类为新建的扩展类

Yii::$app->response->formatters = [
    Response::FORMAT_XML=> ["class"=>"weixincomponentMyXmlResponseFormatter"]
];

step5. 如果说字符串需要使用 CDATA 的时候需要设置

use weixincomponentMyXmlResponseFormatter as MXRF;

return [
    "ToUserName"=>[$postObj->FromUserName,MXRF::CDATA=>true],
    "FromUserName"=>[$postObj->ToUserName,MXRF::CDATA=>true],
    "CreateTime"=>time(),
    "MsgType"=>"music",
    "Music"=>[
        "Title"=>[$recognition,MXRF::CDATA=>true],
        "Description"=>[$decode,MXRF::CDATA=>true],
        "MusicUrl"=>[$musicurl,MXRF::CDATA=>true],
        "HQMusicUrl"=>[$musicurl,MXRF::CDATA=>true],
    ]
];

经过本次的修改算是对如何修改和扩展Yii2 有了一定的认识。

在原有的Yii2框架上,新建一个api应用

在做东西的时候需要清晰的结构和逻辑,这样做出来的东西相对来说会比较漂亮,所以为了api我们可能得新建一个应用,这里面全是api相关的程序,我通过Google “yii2 create new application”,“yii2 add new application”,都没有找到相要的答案,于是只能开动自己的脑筋了。

$ cp -a environments/dev/frontend environments/dev/api

$ cp -a environments/prod/frontend environments/prod/api

# file: environments/index.php
 [
        "setWritable" => [
            // ... 在原来的后面添加上
            "api/runtime",
            "api/web/assets"
        ],
        "setCookieValidationKey" => [
            // ... 在原来的后面添加上
            "api/config/main-local.php",
        ],
    ],
    "Production" => [
        // 这里和上面一样的添加
    ],
];

创建相应的目录:

$ mkdir -p api/{assets,config,controllers,models,runtime,web/assets}

$ touch api/{assets,config,controllers,models,runtime,web/assets}/.gitkeep

复制配置文件:

$ cp -a frontend/config/params.php frontend/config/main.php frontend/config/bootstrap.php frontend/config/.gitignore api/config

$ cp frontend/runtime/.gitignore api/runtime/

$ cp frontend/web/.gitignore api/web

# file api/config/main.php

return [
    "id" => "app-api",
    // ...
    "controllerNamespace" => "apicontrollers",
]

# file common/config/bootstrap.php
Yii::setAlias("api", dirname(dirname(__DIR__)) . "/api");

// 配置的其它信息看自己的需求而定

$ ./init

新建一个Controller来测试一下:

# file: api/controllers/SiteController.php


然后通过浏览器访问相应的地址 http://hostname/api/web/index.php?r=site/index 能出来 test 则代表 ok 啦,以上步骤都是一步步的尝试和查看源代码得来的,可能会有不规范的地方,若有不对的地方请到 Github (yii2-usage)上留言。

配置Yii2 request Parser使之可以通过Yii::$app->request->post()来接收 xml 和 json的数据

大家都知道 Yii2 接收 POST 数据是使用 Yii::$app->request->post();,但是如果发送过来的数据格式是 jsonxml 的时候,通过这个方法就无法获取到数据了,Yii2 这么强大的组件型框架肯定想到了这一点。

对于 json 的解析 Yii2 已经写好了 [[JsonResponseFormatter]] ,在配置文件里面配置一下即可使用。

# file app/config/main.php

"components" =>[
    "request" => [
        "parsers" => [
            "application/json" => "yiiwebJsonParser",
            "text/json" => "yiiwebJsonParser",
        ],
    ],
],

配置好之后访问提交过来的数据就太简单啦

# json raw data
{"username": "bob"}

# access data
$post_data = Yii::$app->request->post();
echo $post_data["username"];

# or
echo Yii::$app->request->post("username");

可以通过 composer 添加依赖:bobchengbin/yii2-xml-request-parser 来完成

# file app/config/main.php

"components" =>[
    "request" => [
        "parsers" => [
            "text/xml" => "bobchengbinYii2XmlRequestParserXmlRequestParser",
            "application/xml" => "bobchengbinYii2XmlRequestParserXmlRequestParser",

            "application/json" => "yiiwebJsonParser",
            "text/json" => "yiiwebJsonParser",
        ],
    ],
],

经过上面的三步之后,就可以直接访问提交过来的 xml 数据了。

# raw data


# access data
Yii::$app->request->post("username");

这样不管别人传过来的数据是 html、json、xml 格式都可以非常方便的获取了,在和各种接口打交道的时候用上这个可以方便太多了。

使用 TimestampBehavior 来自动填充 created_at 和 updated_at

Yii2 官方默认提供了一个 TimestampBehavior 来方便我们来自动填充 created_atupdated_at ,它会自动在你插入新数据的时候帮你填充这两个值为当前时间,当然你也可以设置成别的时间,当你更新数据的时候它会自动把 updated_at 改成最后更新的时间。

我创建了一个 user_weixin 表,然后设置 created_atupdated_at 两个字段为 datetime 类型,并在相应的 Model 里面使用上 TimestampBehavior

# file app/models/UserWeixin.php



然后正常的调用保存数据,发现那两个字段的值均为 "0000-00-00 00:00:00",看到这个感觉甚是奇怪,去看了一下默认生成的用户模型,common/models/User.php,发现它也没有做其它的别的操作就可以的啊,我这样为什么不行呢,去看了一下表结构,发现系统创建的 user 表的两个字段是使用的 int 类型,而不是 datetime,于是把 user_weixin 表的两个字段也改成了 int 类型,再测试一次发现好了。

不甘心的我去看了一下 TimestampBehavior 类的注释,发现确实没有说明这个问题,所以大家在声明 created_at 和 updated_at 字段类型的时候需要注意一下

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/20881.html

相关文章

  • YII2通过composer优化vendor

    摘要:本文讨论通过工具安装框架并优化过程中遇到的问题,约定读者对基本原理有一定了解,并且有安装框架的实际经验。这个命令是优化包的关键一环。命令要谨慎使用。 本文讨论通过composer工具安装Yii2框架并优化Vendor过程中遇到的问题,约定读者对composer基本原理有一定了解,并且有安装Yii2框架的实际经验。 在Yii2社区里经常会遇到一类问题,那就是 安装完官方推荐的版本后1 ...

    dcr309duan 评论0 收藏0
  • codeception (6) Yii2中安装codeception遇到问题及解决方法

    摘要:版本这个原因是因为禁用了函数,所以我们需要更改找到的配置文件输入命令会出现两个相关的地址配置文件在中找到,打开之后搜索将去掉,保存处理这个问题有两种方式,第一种是修改在中加上,应该是禁用的意思还有一种方式就是将升级到以上,这个错误就不会出现 codeception版本 v2.1.8 shell_exec PHP Warning: shell_exec() has been disabl...

    Lionad-Morotar 评论0 收藏0
  • Yii2select2使用

    摘要:新手,不擅长写,纯粹只是分享一下自己遇到的问题供大家参考一下这个插件,就是带搜索功能的下拉选择框效果如图使用前先确定自己的项目安装了,如果没有的话就用安装一下使用的时候先在头部引用插件如果表单是,可以使用下面代码是键值对数组,下面所声明的 新手,不擅长写js,纯粹只是分享一下自己遇到的问题供大家参考一下 select2这个插件,就是带搜索功能的下拉选择框效果如图:showImg(ht...

    Cristic 评论0 收藏0
  • Yii2select2使用

    摘要:新手,不擅长写,纯粹只是分享一下自己遇到的问题供大家参考一下这个插件,就是带搜索功能的下拉选择框效果如图使用前先确定自己的项目安装了,如果没有的话就用安装一下使用的时候先在头部引用插件如果表单是,可以使用下面代码是键值对数组,下面所声明的 新手,不擅长写js,纯粹只是分享一下自己遇到的问题供大家参考一下 select2这个插件,就是带搜索功能的下拉选择框效果如图:showImg(ht...

    pingink 评论0 收藏0

发表评论

0条评论

fnngj

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<