大家知道我最近在给 "阿北的知识分享" 微信小程序改版,使用的是 yii2 中的 restful 功能,接下来把遇到的一些问题及小技巧分享一下.
先安利一下小程序码 链接
开始分享.
URL 要重写
我们知道 restful 风格的 url 一般是这样的
GET /users
POST /users
DELETE /users/1
我们 yii2 默认的 url 形式是 index.php?r=controller/action.
虽然说 yii2 已经提供了专门针对于 restful 的路由规则,但是我们还是需要服务器支持 url 重写把 index.php 去掉.
我用的是 nginx,如下配置
location / {
if (!-e $request_filename) {
rewrite ^ /(.*) /index.php last;
}
}
如果你的是 apache 可以如下配置
// Apache需要支持url重写其AllowOverride为all
AllowOverride:all
//web目录下增加.htaccess,隐藏index.php文件 内容如下
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
或
RewriteEngine On RewriteBase / RewriteCond % {
REQUEST_FILENAME
} ! -f RewriteCond % {
REQUEST_FILENAME
} ! -d RewriteRule ^ (. * )\ ? *$ index.php / $1[L, QSA]
不要 DELETE 了
默认情况下 yii2 的 restful 已经提供了 index,view,update,create 和 delete 共 5 个 action 来满足于对资源的不同行为.可能你的接口中不需要 delete,有两个方法
url 规则中配置(推荐)
比如我不希望开放 DELETE /users/1 则可以配置对应的 url 规则如下
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except'=>['delete']
],
重写 action
我们知道这些内置方法使用了 actions 方法实现,我们可以复写这个函数.
class UserController extends ActiveController {
public $modelClass = 'app\models\User';
public
function actions() {
$actions = parent: :actions();
unset($actions['delete']);
return $actions;
}...
}
两种方法都可以实现但是返回结果不相同,感兴趣的同学可以自己体验下.
加个 action 叫 abc
内置方法满足了很多,需求太复杂我想自己在控制器里增加一个 actionAbc 的方法,如何配置那?看下面的代码,还是在 urlManager 里搞定.
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'except'=>['delete','update','index'],
'extraPatterns'=>[
'POST abc'=>'abc',
]
],
这样你就可以通过 POST /users/abc 来调用 User 控制器的 abc Action 了.
我要更多数据
我想通过 GET /users 获取会员的 id 和 nickname 字段,很简单在 get 参数中传入 fields='id,nickname',这很容易毕竟 id 和 nickname 就是 user 表的列,但是我还想获得每个会员下的订单数,而订单数并不属于 user 表,方法如下
增加 get 参数
我们需要增加一个叫做 expand 的参数,值为你要获取的字段名字,逗号分隔每一个.
GET /users?fields='id,nickname'&expand='oTotal'
配置 user 模型
我们需要重写一个叫做 extraFields 的方法
public function extraFields() {
return [
'oTotal'
];
}
编写具体逻辑
接下来我们要在 User 模型中编写实现 oTotal 的函数
public function getOTotal(){
return Order::find()->where(['user_id'=>$this->id])->count();
}
你发现了什么?你是否记起了在 yii2 中一个叫做关联的概念,你是否发现获取多种数据变得很简单了?
json 怎么病了
使用小程序发起服务器请求,比如新建一本书,我们一般喜欢编写如下代码
wx.request({
method: 'POST',
data: {
name: name
},
url: app.globalData.remoteUrl + '/books',
header: {
'content-type': 'application/json'
},
success: function(res) {}
})
这里我设置了'content-type': 'application/json',问题发生了,我在服务器端无法获取 json 中的 name 值.
很简单,默认情况下 yii2 的 restful 并不支持对请求中 json 的数据解析,还好小小配置下就可以了.
// config/web.php
'components' => [
'request' => [
'cookieValidationKey' => '',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
],
]
增加一个 JsonParser 解析器就可以了.
认证问题
网页上有登录,但是 restful 上没有 session,没关系我们可以使用 access token 来搞定,配置很简单.
比如我现在要求 GET /users 必须是登陆后访问.
配置 user 模型和表
首先为 user 表配置一个 access_token 字段,同时在 User 模型下做一个 generateAccessToken 方法
public function generateAccessToken(){
$this->access_token = Yii::$app->security->generateRandomString();
}
该方法主要用于生成 access_token 值.
当然我们的 User 模型需要实现 yiiwebIdentityInterface 接口,否则使用 Yii::$app->user 无法访问的,关于 IdentityInterface 我想在 yii2 登录这里已经很熟悉了,记住 restful 的认证如果生效还要实现如下方法
public static
function findIdentityByAccessToken($token, $type = null) {
$model = User: :find() - >where(['access_token' = >$token]) - >one();
return $model;
}
到这里 User 模型就配置好了,小提醒:如果你想做一些登录那一刻的事儿,可以也放到 findIdentityByAccessToken,比如记录登录时间啥的.
配置 action
接下来我们来对具体的接口进行认证限制,复写 behaviors 行为,如下
use yii\filters\auth\HttpBearerAuth;
class UserController extends ActiveController {
public $modelClass = "app\models\User";
public function behaviors() {
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats'] = ['application/json'=>Response::FORMAT_JSON];
$behaviors['authenticator'] = [
'class'=>HttpBearerAuth::className(),
'only'=>[
'index'
],
];
return $behaviors;
}
}
这样就搞定了,我们这里用的是 HttpBearerAuth 认证,就是在请求的 header 里面写 Authorization,yii2 的 restful 还支持其他的.记住这个认证过程是自动的,并且我们在认证的方法里可以使用 Yii::$app->user->id 获取当前会员的 ID.
列表更多参数
我们知道通过 GET /users 可以获得会员列表,但是你可能说我要获取来自于微信平台的会员(user 表里有一个字段 plat 代表来源平台),怎么办?
我们需要重新编写该接口并接受 plat 参数,在 User 控制器中先设置新的 prepareDataProvider 函数,它用来接收参数并生成会员列表数据,返回的是一个 ActiveDataProvider 结果集.
namespace app\modules\xcx\controllers;
use Yii;
use yii\rest\ActiveController;....class UserController extends ActiveController {
public $modelClass = 'app\models\User';
public
function actions() {
$actions = parent: :actions();
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public
function prepareDataProvider() {
$params = Yii: :$app - >request - >queryParams;
$modelClass = $this - >modelClass;
$query = $modelClass: :find() - >where(['plat' = >$params['plat']]);
$provider = new ActiveDataProvider(['query' = >$query - >orderBy(['created_at' = >SORT_DESC])]);
return $provider;
}
}
首先通过 $actions['index']['prepareDataProvider'] = [$this,'prepareDataProvider'] 告诉 yii2 我要自定义获取结果集的方法,接下来定义这个方法,在 prepareDataProvider 里可以通过 Yii::$app->request->queryParams 接收过来的 get 参数的值.
小结
以上就是目前为止在使用 yii2 的 restful 开发小程序时候使用的一些知识和技巧,希望对你有用,以后如果有再分享哈.
来源: https://segmentfault.com/a/1190000012939232