心有多大,梦想就有多大!
技术资本的积累,是为了等待合适时机的全能释放!
ionic用来开发跨平台的app,实现客户端和服务端的分离,他们之间的通信一般是通过XMLHTTPREQUEST的异步方式,由于angualrjs的双向绑定,我们可以非常容易在客户端实现数据处理。
我们知道由于js的'同源策略',XMLHTTPREQUES原则上是不能实现跨域请求的,但是在我们的实际应用场景中,特别是请求第三方api的时候,就必须要实现跨域请求。
当然,解决这个跨域的问题,有很多的方法,比如jsonp,服务端设置http请求头的Access-Control-Allow-Headers等,具体的方式这里不多说了,大家可以自行百度
那么在ionic开发app的时候,我们是通过restful的api与服务端进行数据交换,对于我们的接口设计分成有帮助,包括版本的升级,因为app会不断升级,增加功能,对应的rest的接口也是对应不同的版本。可以参考我之前写的关于yii2的restful的文章
http://blog.csdn.net/u012979009/article/details/52055794
下面我将根据项目的实际整理一下知识
客户端:ionic + angularjs + angualar-resource.js
服务端:yii2框架-restful api
客户端:
angualar-resource.js是一个封装好的功能和性能比$http表现好的模块,具体的一些基础知识可以百度,下面知识简单说一下。
https://docs.angularjs.org/api/ngResource/service/$resource
我们在使用之前需要引入
<script src="lib/ionic/js/angular/angular-resource.js"></script>
那么在我们的应用中
在我们的应用中需要将其当做依赖进行引用
angular.module('myApp', ['ngResource']);
使用
$resource服务本身是一个创建资源对象的工厂,返回的$resource对象中包含了同后端服务器进行的交互的高层API.
var User=$resource(url,[defaultparams],[action],[options]);
上面这一句是创建一个资源的对象
url:请求的uri(必须设置)
defaultparame: 附带在url的query参数(可选设置)
比如:var User=$resource('/api/users/:userId',{userId:'@id','sex':'1'});
@id就是代表在具体请求的参数
User.get({'userId':1},successfn,failfn);
那么这个最终的请求会变成
/api/users/1?sex=1,
{'userId':1}相当于请求的data,那么@id的值等于data.userId这样子来获取的,如果没有找到对应的key键,则将忽略:userId这个值
如下面:
User.get({'id':1},successfn,failfn);
Id并不是在{userId:'@id','sex':'1'}对应的key,所以最终的请求变成
/api/users?id=1&sex=1,
其实userId是占位符,或者可以说是key,最终的会找到对应的值id,那么后面的其他key-value值将作为query参数附带在url后面。
action: 是一个对象,可以自定义action,并且设置不同请求方法的请求体等信息
https://docs.angularjs.org/api/ng/service/$http#usage
格式
{
action1: {method:?, params:?, isArray:?, headers:?, ...},
action2: {method:?, params:?, isArray:?, headers:?, ...},
}
例如
{query: {method: 'get', isArray: false},
save: {method: 'post', headers:{'Content-Type': 'application/x-www-form-urlencoded'}}
}
action: 就是我们为resource定义的方法,可以自定义,比如sendEmail。
method:get,post等http请求方法
params:请求参数
isArray :返回是否数组
headers :设置请求头信息
.....
具体方法可以认真看看,基本用到的也就是上面几个。
可以把User对象理解成同RESTful的后端服务进行交互的接口。
下面说一下关于angular-resource的actions.
anular-resource默认的已经定义好的http请求的action有以下:A、get 查找单个数据
User.get(params,successFn,errrorFn);
params可以不设置
//GET /api/users
User.get(function(resp){
//处理成功
},function(err){
//处理错误
});
如果参数中传入了具名参数(我们例子中的参数是id),那么get()方法会向包含id的URL发送请求:
//发起一个请求:GET-->/api/users/123
User.get({userId:'1234'},function(resp){
//success
},function(error){
//fail
});
User.query(params,successFn,errrorFn);
params可以不设置
query向指定URL发送一个GET请求,并期望返回一个JSON格式的资源对象集合。
//发起一个请求
User.query(function(users){
//读取集合中的第一个用户
var user=users[0];
});
如果设置paramms查找在一定区间的数据
User.query({'startId':10,'endId':500},successFn,errrorFn);
那么请求url变成GET-->/api/users?startId=10&endId=500
query()和get()方法之间唯一的区别是AngularJS期望query()方法返回数组
C、post
User.save(params, payload, successFn, errorFn);保存数据
params: 默认附带在url后面的参数,如果没有数据,需要设置{}对象
payload: 请求体信息,{'name':'bing','sex':1}的json格式
可以这样子使用:
.save({},$httpParamSerializer({'name':'bing','sex':1}),function(resp){console.log(resp);
},function(error){
//fail
});
在这里大家一定要注意一个angularjs的post请求的请求头的Content-Type是application/json,并不是表单post数据时的application/x-www-form-urlencoded,而且post的数据{'name':'bing','sex':1}并不会自动转为符合x-www-form-urlencoded的name=bing&sex=1。而表单post数据的时候,请求体会变成name=bing&sex=1这种格式的,在服务端才能够正确地通过$_POST来获取数据。
大家可以看一下我之前的博客
save: {method: 'post', headers:{'Content-Type': 'application/x-www-form-urlencoded'}}
只有设置这两个地方,post的数据才能在服务端通过$_POST获取。
D、delete
delete(params, payload, successFn, errorFn)
delete方法会向指定URL发送一个DELETE请求,并用数据体来生成请求体。它被用来在服务器上删除一个实例:
// DELETE /api/users/123
User.delete({}, {
id: '123'
}, function(response) {
// 处理成功的删除响应
}, function(response) {
// 处理非成功的删除响应
});
remove(params, payload, successFn, errorFn)
remove方法和delete()方法的作用是完全相同的,它存在的意义是因为delete是JavaScript的保留字,在IE浏览器中会导致额外的问题。
// 发起一个请求:
// DELETE /api/users/123
User.remove({}, {
id: '123'
}, function(response) {
// 处理成功的删除响应
}, function(response) {
// 处理非成功的删除响应
});
服务端:
服务端使用yii2的restful的API接口
为了实现可以接受跨域请求,可以使用yii\filters\Cors
跨域资源共享 CORS 机制允许一个网页的许多资源(例如字体、JavaScript等) 这些资源可以通过其他域名访问获取。 特别是JavaScript's AJAX 调用可使用 XMLHttpRequest 机制, 由于同源安全策略该跨域请求会被网页浏览器禁止. CORS定义浏览器和服务器交互时哪些跨域请求允许和禁止。
yii\filters\Cors 应在 授权 / 认证 过滤器之前定义, 以保证CORS头部被发送。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
],
], parent::behaviors());
}
Cors 可转为使用 cors 属性。
cors['Origin']: 定义允许来源的数组,可为['*'] (任何用户) 或 ['http://www.myserver.net', 'http://www.myotherserver.com']. 默认为 ['*'].
cors['Access-Control-Request-Method']: 允许动作数组如 ['GET', 'OPTIONS', 'HEAD']. 默认为 ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'].
cors['Access-Control-Request-Headers']: 允许请求头部数组,可为 ['*'] 所有类型头部 或 ['X-Request-With'] 指定类型头部. 默认为 ['*'].
cors['Access-Control-Max-Age']: 定义请求的有效时间,默认为 86400.
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
],
], parent::behaviors());
}
可以覆盖默认参数为每个动作调整CORS 头部。例如, 为login动作增加Access-Control-Allow-Credentials参数如下所示:
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
'actions' => [
'login' => [
'Access-Control-Allow-Credentials' => true,
]
]
],
], parent::behaviors());
}
所以在服务端的Controller的必须要设置,当然事先的完成restful的API先
下面是我测试的例子
public function behaviors() {
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => QueryParamAuth::className(),
];
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://192.168.1.101:8100'],
'Access-Control-Request-Headers' => ['Origin', 'X-Requested-With', 'Content-Type', 'Accept'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
],
],
], $behaviors);
}
根据实际的需求和功能设置cors数组的属性。