koa和php,PHP异步编程: 基于 PHP 实(chao)现(xi) NODEJS web框架 KOA

本文介绍了如何在PHP中借鉴Node.js框架KOA的特性,通过Workerman或自定义实现异步处理,包括错误处理、超时控制、路由管理及RESTful API,同时展示了在Windows环境下兼容swoole之外的解决方案。
摘要由CSDN通过智能技术生成

PHP异步编程: 基于 PHP 实(chao)现(xi) NODEJS web框架KOA

说明

偶然间在 GITHUB 上看到有赞官方仓库的 手把手教你实现co与Koa 。由于此前用过 KOA ,对于 KOA 的洋葱模型叹为观止。不由得心血来潮的看完了整个文档,接着 CTRL+C、CTRL+V 让代码跑了起来。 文档中是基于 swoole 扩展进行开发,而 swoole 对 WINDOWS 并不友好,向来习惯在 WINDOWS 下开发的我一鼓作气,将Workerman 改写并兼容了此项目。

体验

PHPKoa Demo 是使用 PHPKoa 开发 HTTP SERVER 的一个简单示例!

安装

composer require naka1205/phpkoa

复制代码

使用

Hello World

require __DIR__ . '/vendor/autoload.php';

use Naka507\Koa\Application;

use Naka507\Koa\Context;

$app = new Application();

$app->υse(function(Context $ctx) {

$ctx->status = 200;

$ctx->body = "

Hello World

";

});

$app->listen(3000);

复制代码

Error

require __DIR__ . '/vendor/autoload.php';

use Naka507\Koa\Application;

use Naka507\Koa\Context;

use Naka507\Koa\Error;

use Naka507\Koa\Timeout;

use Naka507\Koa\Router;

use Naka507\Koa\NotFound;

$app = new Application();

$app->υ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

require __DIR__ . '/vendor/autoload.php';

define('DS', DIRECTORY_SEPARATOR);

use Naka507\Koa\Application;

use Naka507\Koa\Context;

use Naka507\Koa\Error;

use Naka507\Koa\Timeout;

use Naka507\Koa\Router;

$app = new Application();

$app->υ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);

//此处已省略 ...

//使用第三方 HTTP 客户端类库,方便测试

use GuzzleHttp\Client;

$router = new Router();

//路由分组

//http://127.0.0.1:5000/curl/get

//http://127.0.0.1:5000/curl/post

//http://127.0.0.1:5000/curl/put

//http://127.0.0.1:5000/curl/delete

$router->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

{title}

{time}

require __DIR__ . '/vendor/autoload.php';

use Naka507\Koa\Application;

use Naka507\Koa\Context;

use Naka507\Koa\Error;

use Naka507\Koa\Timeout;

use Naka507\Koa\Router;

$app = new Application();

$app->υ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);

{title}

NameAge
{name} {age}

//此处已省略 ...

//一维数组

$router->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");

});

{title}

NameAge
{name} {age}

//此处已省略 ...

//二维数组

$router->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

20264902.jpg

require __DIR__ . '/vendor/autoload.php';

defined('DS') or define('DS', DIRECTORY_SEPARATOR);

use Naka507\Koa\Application;

use Naka507\Koa\Context;

use Naka507\Koa\Error;

use Naka507\Koa\Timeout;

use Naka507\Koa\NotFound;

use Naka507\Koa\Router;

//静态文件处理 中间件

use Naka507\Koa\StaticFiles;

$app = new Application();

$app->υ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);

复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值