MIT-LICENSE.txt (1168, 2019-10-04) composer.json (482, 2019-10-04) example (0, 2019-10-04) example\demo.php (315, 2019-10-04) example\demo2.php (764, 2019-10-04) example\demo3.php (1946, 2019-10-04) example\demo4.php (1237, 2019-10-04) example\demo5.php (2632, 2019-10-04) example\demo6.php (1519, 2019-10-04) example\demo7.php (1815, 2019-10-04) example\file.txt (11, 2019-10-04) example\hello.html (294, 2019-10-04) example\info.html (479, 2019-10-04) example\public (0, 2019-10-04) example\public\css (0, 2019-10-04) example\public\css\default.css (75, 2019-10-04) example\public\favicon.ico (4286, 2019-10-04) example\public\images (0, 2019-10-04) example\public\images\20264902.jpg (16422, 2019-10-04) example\table.html (481, 2019-10-04) example\template (0, 2019-10-04) example\template\index.html (534, 2019-10-04) src (0, 2019-10-04) src\All.php (1206, 2019-10-04) src\Any.php (944, 2019-10-04) src\Application.php (3138, 2019-10-04) src\Async.php (95, 2019-10-04) src\AsyncTask.php (1510, 2019-10-04) src\CallCC.php (285, 2019-10-04) src\Context.php (1268, 2019-10-04) src\Error.php (1148, 2019-10-04) src\Gen.php (697, 2019-10-04) src\HttpException.php (536, 2019-10-04) src\Middleware.php (104, 2019-10-04) src\NotFound.php (382, 2019-10-04) src\Request.php (2069, 2019-10-04) src\Response.php (1690, 2019-10-04) ... ...
PHPKoa
=================
[![Latest Stable Version](https://poser.pugx.org/naka1205/phpkoa/version)](https://packagist.org/packages/naka1205/phpkoa)
[![Total Downloads](https://poser.pugx.org/naka1205/phpkoa/downloads)](https://packagist.org/packages/naka1205/phpkoa)
[![License](https://poser.pugx.org/naka1205/phpkoa/license)](https://packagist.org/packages/naka1205/phpkoa)
PHP异步编程:
基于 `PHP` 实(chao)现(xi) `NODEJS` web框架 [KOA](https://github.com/koajs/koa)
说明
=======
偶然间在 `GITHUB` 上看到有赞官方仓库的 [手把手教你实现co与Koa](https://github.com/youzan/php-co-koa) 。由于此前用过 `KOA` ,对于 `KOA` 的洋葱模型叹为观止。不由得心血来潮的看完了整个文档,接着 `CTRL+C`、`CTRL+V` 让代码跑了起来。
文档中是基于 `swoole` 扩展进行开发,而 `swoole` 对 `WINDOWS` 并不友好,向来习惯在 `WINDOWS` 下开发的我一鼓作气,将[Workerman](https://github.com/walkor/Workerman) 改写并兼容了此项目。
体验
=======
1. [PHPKoa Demo](https://github.com/naka1205/phpkoa_demo) 是使用 `PHPKoa` 开发 `HTTP SERVER` 的一个简单示例!
2. [PHP Krpano](https://github.com/naka1205/phpkrpano) PHP 全景图片生成!
3. [PKBook](https://github.com/naka1205/pkbook) 静态博客发布程序!
4. [H5Make](https://github.com/naka1205/H5Make) H5编辑器!
建议
=======
欢迎各位大神提交[issues](https://github.com/naka1205/phpkoa/issues/1)
安装
=======
```
composer require naka1205/phpkoa
```
使用
=======
### Hello World
```php
υse(function(Context $ctx) {
$ctx->status = 200;
$ctx->body = "
Hello World ";
});
$app->listen(3000,function(){
echo "PHPKoa is listening in 3000\n";
});
```
### Error
```php
υse(new Error());
$app->υse(new NotFound());
$app->υse(new Timeout(3)); //设置3秒超时
$router = new Router();
//正常访问
$router->get('/hello', function(Context $ctx, $next) {
$ctx->status = 200;
$ctx->body = "
Hello World ";
});
//访问超时
$router->get('/timeout', function(Context $ctx, $next) {
yield async_sleep(5);
});
//访问出错
$router->get('/error', function(Context $ctx, $next) {
$ctx->thrοw(500, "Internal Error");
yield;
});
$app->υse($router->routes());
$app->listen(3000);
```
### Router
```php
υse(new Error());
$app->υse(new Timeout(5));
$router = new Router();
$router->get('/demo1', function(Context $ctx, $next) {
$ctx->body = "demo1";
});
$router->get('/demo2', function(Context $ctx, $next) {
$ctx->body = "demo2";
});
$router->get('/demo3/(\d+)', function(Context $ctx, $next, $vars) {
$ctx->status = 200;
$ctx->body = "demo3={$vars[0]}";
});
$router->get('/demo4', function(Context $ctx, $next) {
$ctx->redirect("/demo2");
});
//RESTful API
$router->post('/demo3/(\d+)', function(Context $ctx, $next, $vars) {
//设置 session
$ctx->setSession('demo3',$vars[0]);
//设置 cookie
$ctx->setCookie('demo3',$vars[0]);
$ctx->status = 200;
$ctx->body = "post:demo3={$vars[0]}";
});
$router->put('/demo3/(\d+)', function(Context $ctx, $next, $vars) {
//获取单个 cookie
$cookie_demo3 = $ctx->getCookie('demo3');
//或者
$cookies = $ctx->cookies['demo3'];
//获取单个 session
$session_demo3 = $ctx->getSession('demo3');
//或者
$session = $ctx->session['demo3'];
$ctx->status = 200;
$ctx->body = "put:demo3={$vars[0]}";
});
$router->delete('/demo3/(\d+)', function(Context $ctx, $next, $vars) {
//清除所有 cookie
$ctx->clearCookie();
//清除所有 session
$ctx->clearSession();
$ctx->status = 200;
$ctx->body = "delete:demo3={$vars[0]}";
});
//文件上传
$router->post('/files/(\d+)', function(Context $ctx, $next, $vars) {
$upload_path = __DIR__ . DS . "uploads" . DS;
if ( !is_dir($upload_path) ) {
mkdir ($upload_path , 0777, true);
}
$files = [];
foreach ( $ctx->request->files as $key => $value) {
if ( !$value['file_name'] || !$value['file_data'] ) {
continue;
}
$file_path = $upload_path . $value['file_name'];
file_put_contents($file_path, $value['file_data']);
$value['file_path'] = $file_path;
$files[] = $value;
}
$ctx->status = 200;
$ctx->body = json_encode($files);
});
$app->υse($router->routes());
$app->listen(3000);
```
```php
mount('/curl', function() use ($router) {
$client = new Client();
$router->get('/get', function( Context $ctx, $next ) use ($client) {
$r = (yield $client->request('GET', 'http://127.0.0.1:3000/demo3/1'));
$ctx->status = $r->getStatusCode();
$ctx->body = $r->getBody();
});
$router->get('/post', function(Context $ctx, $next ) use ($client){
$r = (yield $client->request('POST', 'http://127.0.0.1:3000/demo3/2'));
$ctx->status = $r->getStatusCode();
$ctx->body = $r->getBody();
});
$router->get('/put', function( Context $ctx, $next ) use ($client){
$r = (yield $client->request('PUT', 'http://127.0.0.1:3000/demo3/3'));
$ctx->status = $r->getStatusCode();
$ctx->body = $r->getBody();
});
$router->get('/delete', function( Context $ctx, $next ) use ($client){
$r = (yield $client->request('DELETE', 'http://127.0.0.1:3000/demo3/4'));
$ctx->status = $r->getStatusCode();
$ctx->body = $r->getBody();
});
});
//http://127.0.0.1:5000/files
$router->get('/files', function(Context $ctx, $next ) {
$client = new Client();
$r = ( yield $client->request('POST', 'http://127.0.0.1:3000/files/2', [
'multipart' => [
[
'name' => 'file_name',
'contents' => fopen( __DIR__ . '/file.txt', 'r')
],
[
'name' => 'other_file',
'contents' => 'hello',
'filename' => 'filename.txt',
'headers' => [
'X-Foo' => 'this is an extra header to include'
]
]
]
]));
$ctx->status = $r->getStatusCode();
$ctx->body = $r->getBody();
});
// $router->get('/curl/(\w+)', function(Context $ctx, $next, $vars) {
// $method = strtoupper($vars[0]);
// $client = new Client();
// $r = (yield $client->request($method, 'http://127.0.0.1:3000/demo3/123'));
// $ctx->status = $r->getStatusCode();
// $ctx->body = $r->getBody();
// });
$app->υse($router->routes());
$app->listen(5000);
```
### Template
```html
{title}
{time}
```
```php
υse(new Error());
$app->υse(new Timeout(5));
$router = new Router();
$router->get('/hello', function(Context $ctx) {
$ctx->status = 200;
$ctx->state["title"] = "HELLO WORLD";
$ctx->state["time"] = date("Y-m-d H:i:s", time());;
yield $ctx->render(__DIR__ . "/hello.html");
});
$app->υse($router->routes());
$app->listen(3000);
```
```html
{title}
```
```php
get('/info', function(Context $ctx) {
$info = array("name" => "小明", "age" => 15);
$ctx->status = 200;
$ctx->state["title"] = "这是一个学生信息";
$ctx->state["info"] = $info;
yield $ctx->render(__DIR__ . "/info.html");
});
```
```html
{title}
```
```php
get('/table', function(Context $ctx) {
$table = array(
array("name" => "小明", "age" => 15),
array("name" => "小花", "age" => 13),
array("name" => "小刚", "age" => 17)
);
$ctx->status = 200;
$ctx->state["title"] = "这是一个学生名单";
$ctx->state["table"] = $table;
yield $ctx->render(__DIR__ . "/table.html");
});
```
中间件
=======
静态文件处理 中间件 [PHPKoa Static](https://github.com/naka1205/phpkoa_static)
```html
PHPkoa Static
```
```php
υse(new Error());
$app->υse(new Timeout(5));
$app->υse(new NotFound());
$app->υse(new StaticFiles(__DIR__ . DS . "static" ));
$router = new Router();
$router->get('/index', function(Context $ctx, $next) {
$ctx->status = 200;
yield $ctx->render(__DIR__ . "/index.html");
});
$app->υse($router->routes());
$app->listen(3000);
```
使用 第三方ORM
```
composer require topthink/think-orm
```
创建 MYSQL 数据表
```mysql
CREATE TABLE `too_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`account` varchar(***) NOT NULL DEFAULT '' COMMENT '账号',
`password` char(32) NOT NULL DEFAULT '' COMMENT '登录密码',
`nickname` varchar(32) NOT NULL DEFAULT '' COMMENT '用户昵称',
`status` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT '状态',
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
```
自定义数据模型
```php
accept,'json');
if ( $pos !== false ) {
$ctx->type = 'application/json';
$result = [ "code" => 0, "msg" => '操作失败'];
$data = $ctx->body;
if ( $data ) {
$result['code'] = 200;
$result['msg'] = '操作成功';
$result['data'] = $data;
}
$ctx->body = json_encode( $result );
}
}
}
```
动态模板 使用JQ 进行AJAX 请求
```html
/api/user/{id}
```