2 Star 0 Fork 0

Focrs / Yls

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

#Yls

Y-e-s, 一种愉悦的开发方式。

Yls印象

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文件

每个目录下的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来解决取名老大难的问题啦!绝对没有搞事情的意思 :tw-1f62b:

版本控制

Yls通过增量性覆盖达到调用最新接口的目的,Yls会根据客户端发起的请求找到相应的Api版本,如果在当前版本找不到请求的接口,则会尝试去上一个版本中找,以此类推向上回溯,直到找到对应的接口。

未来草稿

未来会实现的一些功能特性,备忘。

  • DB链式操作;
  • CURD原子操作;
  • 接口参数约束验证;
  • 查询条件自动拼接;

查询条件自动拼接

两个数据库: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);

Auth2.0统一登录授权

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'}

空文件

简介

嗨,我的名字叫叶绿素,英文名字Y-e-s,是一个用世界上最好的语言实现的服务端API框架,不是MVC式或RESTful式的实现,只是为灵活简约式开发提供另一种可选办法,也许你会喜欢也说不定的哦! 展开 收起
PHP
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
PHP
1
https://gitee.com/focrs/Yls.git
git@gitee.com:focrs/Yls.git
focrs
Yls
Yls
master

搜索帮助