#Yls
Y-e-s, 一种愉悦的开发方式。
Yls客户端和服务端均采用JSON格式数据进行传输。使用Yls,你的API组织结构看起来像这样:
1.0
|-user
|-list
|-api.php
|-@id
|-api.php
|-like
|-api.php
|-@like.id
|-api.php
|-avatar
|-api.php
|-message
|-api.php
|-search
|-api.php
2.0
|-user
|-api.php // 2.0版对user接口进行了增量改写
|-a
3.0
|-search
|-api.php // 3.0版对search接口进行了增量改写
你将可以像这样调用API:
require '../Yls/Core/Client.php';
$url = 'http://yls.focrs.com/demo/index.php'; // Yls服务地址
$id = 'web'; // Yls分配的账号
$key = '29d03b2cd1df263770ead73c6e541322'; // Yls分配的私钥
$version = '1.0'; // API版本号(统一设置)
$Client = new Yls\Core\Client($url, $id, $key, $version);
// 单个API查询
list($list) = $Client->Query([
'api' => 'user/list:read', // 调用 /user/api.php中的read()方法
]);
// 带参数的单API查询
list($list) = $Client->Query([
'api' => 'user/list:read',
'param' => ['name' => ['like' =>'Yls']] // 请求user中name包含Yls的记录
]);
// 多参数的API查询
list($list) = $Client->Query([
'api' => 'user/list:read',
'param' => ['gender' => 'male', 'age' => ['gt' => 18]] // 请求user中gender为male,age大于18的记录
]);
// @魔法映射
list($user) = $Client->Query([ // 此时API目录中并没有user/1的目录,此时会自动映射到调用/user/@id,
'api' => 'user/1:read' // 同时@id的值将自动变成1保存在Yls中,通过Yls::Instance()->At('id')可访问
]);
// 深层@魔法映射
list($result) = $Client->Query([ // 调用/user/@id/like/@like.id/api.php中的read()方法,
'api' => 'user/1/like/10:read' // 同时@id(=1)和@like.id(=10)的值分别通过Yls::Instance()->At('id')
]); // 和Yls::Instance()->At('like.id')可访问
// 多API联查,减少网络请求次数,一次性搞定数据查询
list($user, $message) = $Client->Query([
'api' => 'user/1:read',
'param' => ['page' => 2]
], [
'api' => 'user/1/message:read',
'version' => '2.0' // API内也可以自由指定版本号
]);
// Api参数预绑定查询,API联查时,提供类似数据库存储过程中的预定于变量功能
list($user, $search, ...) = $Client->Query([
'api' => 'user/1:read',
'bind' => ['::name' => '.name'] // 将用户name属性绑定到::name中
], [
'api' => 'search:read',
'param' => ['keyword' => '::name'] // 将上一步Api获取的::name值传给当前Api
], ...);
// API级事务机制
list($user, $avatar) = $Client->Query(
'atomic' => true, // 原子操作
'query' => [[
'api' => 'user/1:update',
'param' => ['name' => 'Yls']
], [
'api' => 'user/1/avatar:update',
'param' => ['avatar' => 'http://t.cn/RoCIvbk'] // 头像很美
]]
);
每个目录下的api.php文件包含了当前路由下的对外接口CURD方法(create, update, read, delete)的实现,每个方法都应该有返回值,即使没有返回数据,也应该有一个是否处理成功的bool值。
return [
'create' => function() { return $result; },
'update' => function() { return $result; },
'read' => function() { return $result; },
'delete' => function() { return $result; }
];
return function() {
// 可在此匿名函数内部定义一些共用方法
$GetInfo = function() { return ['id' => 1, 'name' => 'Yls']};
return [
'create' => function() { return $result; },
'update' => function() { return $result; },
'read' => function() { return $GetInfo(); },
'delete' => function() { return $result; }
];
};
这种方式是为了考虑同一api.php文件中实现CURD操作会有大概率的代码冗余,而使用匿名函数可以在内部自由定义一些公共匿名方法,从而达到精简代码的目的。可能有同学会问,这里把api.php定义成一个类不就能解决这些问题吗?比如:
class Api {
function create() { return $result; },
function update() { return $result; },
...
}
但是在类的命名问题上犯难了:每个类名必须不能重复,这破坏了设计上的一致性规则,而且即便引入命名空间解决了冲突问题,但又无法引入@魔法功能,所以干脆通过匿名函数或直接return来解决取名老大难的问题啦!绝对没有搞事情的意思
Yls通过增量性覆盖达到调用最新接口的目的,Yls会根据客户端发起的请求找到相应的Api版本,如果在当前版本找不到请求的接口,则会尝试去上一个版本中找,以此类推向上回溯,直到找到对应的接口。
未来会实现的一些功能特性,备忘。
两个数据库:web, setting, 配置文件db部分配置如下:
'db' => [
'default' => [ // 默认连接配置
'dsn' => 'mysql:dbname=yls;host=127.0.0.1;charset=utf8',
'username' => '******',
'password' => '******',
'prefix' => 'Y', // 表前缀
'create' => 'created:datetime', // 创建记录时将字段created自动赋值为当前时间(YYYY-mm-dd HH:ii:ss)
'update' => 'updated:datetime' // 更新记录时将字段updated更新为当前时间(YYYY-mm-dd HH:ii:ss)
],
'focrs' => [ // 北京机房连接
'dsn' => 'mysql:dbname=focrs;host=127.0.0.1;charset=utf8',
'username' => '******',
'password' => '******',
'prefix' => 'F',
'create' => 'created:timestamp', // 创建记录时将字段created自动赋值为当前UNIX时间戳(1501059706)
'update' => 'updated:timestamp' // 更新记录时将字段updated更新为当前UNIX时间戳(1501059706)
],
],
数据库 | 表 | 说明 |
---|---|---|
yls | YUser | 对应default配置 |
focrs | FUser | 对应focrs配置 |
客户端发起请求
```php
list($list) = $Client->Query([
'api' => 'user/list:read',
'param' => ['NameSearch' => 'Yls'] // 构造条件: YUser.name LIKE "%Yls%" OR YUser.nick LIKE "%Yls%"
]);
DB插入或更新以数组方式传递的数据时,为区分特殊字段使用内置函数或特性而不应该自动加双引号,应将其表达式用{}包裹起来
$data = [
'id' => 1,
'hit' => '{hit + 1}',
'timestamp' => 'NOW()'
];
Yls::Db()->From('~News')->update($data);
http://www.imooc.com/learn/557 发送登录信息(name,password)到登录验证接口,成功则返回token,获取当前用户信息需进一步调用 /my/info/token/012AF3B==接口,
Client | Server
------------------------------------|--------------------------------------------
POST /login { |
name: 'Yls', |
password: 'y-e-s' |
} ==> | 返回包含用户id和时间戳的加密token
| <== token: 1E23F0A2
GET /my?token=1E23F0A2 ==> | 返回用户基本信息
| <== {id: 1, name: 'Yls', avatar: '/path/to/avatar.jpg', ...}
PUT /my/avatar?token=1E23F0A2 ==> | 返回更新成功后的用户头像地址
| <== {avatar: '/new/path/to/avatar.jpg'}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。