NextPHP一款基于Psr规范的支持Workerman,Swoole,php-fpm,cli-server,(React,Amphp --- beta) 的框架。支持Aop,注解等特性。

Chengyao

欢迎感兴趣的开发者参与开发

Github: https://github.com/next-laboratory/simple

安装

php >= 8.0

composer create-project next/simple

启动

php bin/workerman.php start

nginx配置参考

swoole/workerman

server {
    server_name www.domain.com;
    listen 80;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "keep-alive";
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        if (!-f $request_filename) {
             proxy_pass http://127.0.0.1:9501;
        }
    }
}

FPM

server {
    server_name www.domain.com;
    listen 80;
    root /data/project/public;
    index index.html index.php;

    location / {
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php/$1 last;
        }
    }

    location ~ ^(.+\.php)(.*)$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

路由

配置

框架提供了env和config两个函数,可以方便获取配置,如果你使用了AOP包,还可以直接使用注解将配置注入示例

class User
{
    #[\Next\Config\Annotations\Config(key: 'qcloud.user.secret_key', default = '123')]
    protected string $secretKey;
}

如上secretKey将会被自动注入,如果配置文件中不存在,则默认123

路由定义

app/Http/Kernel.phpmap方法中注册路由,注册方式请参考next/routing组件文档,或者使用注解方式

#[Controller(prefix: 'index', middleware: [BasicAuthentication::class])]
class Index
{
    #[GetMapping(path: '/user/{id}\.html')]
    public function index(\Psr\Http\Message\ServerRequestInterface $request, $id)
    {
        return new \Next\Http\Message\Response(200, [], 'Hello, world!');
    }
}

上面的代码定义了一个 Index 控制器,并使用 Controller 注解设置了路由的前缀为 index, 该控制器中全部方法的中间件为BasicAuthentication::class, 并且使用GetMapping
注解定义了一个路由,path/user/{id}.html, 那么实际请求的地址可以为/index/user/1.html, 支持的注解如下,分别对应了不同的请求方法,其中RequestMapping对应的请求方法默认为GETPOSTHEAD,可使用method参数来自定义

  • GetMapping
  • PostMapping
  • PutMapping
  • DeleteMapping
  • PatchMapping
  • RequestMapping

控制器

class IntexController {

    #[GetMapping(path: '/{id}')]
    public functin index(ServerRequestInterface $request, $id) {
        // Do something.
    }
}

控制器是单例对象,和路由对应的方法支持依赖注入,并且参数名为request的参数会被注入当前请求类,该类不是单例,对于每个请求都是独立的。路由参数会被按照参数名注入,其他有类型提示的参数也会被注入

请求

请求可以是任何实现了Psr的ServerRequestInterface实例

请使用App\Http\ServerRequest,该类继承Next\Http\Message\ServerRequest类,是实现了Psr7 ServerRequest
的请求类,并且附加了一些简单的方法,开发者可以自定义相关方法

请求头

$request->getHeaderLine($name): string
$request->head($name): string

上面两个方法会返回请求头字符串,header 方法返回值 getHeaderLine 是一样的

Server

$request->server($name): string     // 一条
$request->getServerParams(): array // 全部

获取$_SERVER中的值

判断请求方法

$request->isMethod($method): bool

不区分大小写的方式判断请求方式是否一致

请求地址

$request->url(bool $full = false): string

返回请求的地址,$fulltrue,则返回完整地址

Cookie

$request->cookie(string $name): string   // 单条
$request->getCookieParams(): array       // 全部

获取请求的Cookie,一般也可以直接从Header中获取

Ajax

$request->isAjax(): bool

判断当前请求是否是Ajax请求, 注意:有部分前端框架在发送Ajax请求的时候并没有发送X_REQUESTED_WITH头,所以这个方法会返回false

判断path

$request->is(string $path): bool

判断当前请求的path是否和给定的path匹配,支持正则

获取输入参数

$request->get($key = null, $default = null)                         // $_GET
$request->post($key = null, $default = null)                        // $_POST
$request->all()                                                     // $_GET + $_POST
$request->input($key = null, $default = null, ?array $from = null)  // $_GET + $_POST

获取请求的参数,这些参数是通过PHP全局变量加载进来的,当$key为null的时候会返回全部参数,如果为字符串会返回单个,如果不存在返回default,如果$key是数组,则会返回多个参数,$default此时可以为数组,数组的键为参数键,数组的值为参数的默认值

例如

$request->get('a');

可以给第二个参数传入一个默认值,例如

$request->get('a','default');

获取多个参数可以使用

$request->get(['a','b']);

可以传入一个关联数组,数组的键为参数名,值为默认值,例如

$request->get(['a', 'b'], ['a' => 1]);

此时如果a不存在,则a的值为1

文件

$request->getUploadedFiles();
$request->file("name");

中间件

中间件基于Psr15实现,在App\Http\Kernel 中的$middlewares数组中注册的为全局的中间件,例如请求异常处理,路由服务,Session初始化,CSRF校验等等

首先需要创建一个中间件,例如

<?php

namespace App\Http\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class Login implement MiddlewareInterface
{ 
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface  
    {        
        // 前置操作
        $response = $handler->handle($request);
        // 后置操作     
        return $response;    
}

注解

#[Controller(prefix: '/', middleware(TestMiddleware::class))]
class Index {
    #[GetMapping(path: '/', middlewares: [Test2Middleware::class])]
    public function index() {
        // Do something.
    }
}

上面的注解定义了两个中间件,控制器Index中的方法都注册了TestMiddleware中间件,index方法不仅包含TestMiddleware, 还包含Test2Middleware中间件。

Session

Session可以使用File, Redis 驱动

Session配置文件如下

<?php

return [
    'name'          => 'NextPHP_SESSION_ID',
    'handler'       => [
        'class'   => '\Next\Session\Handlers\File',
        'options' => [
            'path' => env('storage_path') . 'session',
            'ttl' => 3600,
        ]
    ],
    'cookie_expire' => time() + 3600,
];

在控制器中使用

当前请求的session需要在中间件中创建,所以需要开启SessionMiddleware。开启后将session放入Request属性中,在控制器中使用

public function index(App\Http\ServerRequest $request) 
{
    $session = $request->session();
    $session = $request->getAttribute(\Next\Session\Session::class);
}

你也可以自己定义session的存储位置,但是要保证协程间隔离。如果使用workerman,还可以直接使用其提供的session

判断是否存在

$session->has($name): bool

获取

$session->get($name)

添加

$session->set($name, $value): bool

可以是数组或者字符串

获取并删除

$session->pull($name): bool

删除

$session->remove($name): bool

销毁

$session->destory(): bool

错误处理

框架继承了filp/whoops,可以很方便地查看异常情况,使用前需要添加异常处理类Next\Framework\Exceptions\Handlers\WhoopsExceptionHandlerApp/Http/Middlewares/ExceptionHandleMiddleware 中间件中

如果没有安装,需要执行下面的命令安装

composer require filp/whoops

打印变量

打印变量使用了symfony/var-dumper组件,但是为了兼容多种环境,建议使用d函数代替dump,dd 函数。使用前需要添加异常处理类Next\Framework\Exceptions\Handlers\VarDumperAbortHandlerApp/Http/Middlewares/ExceptionHandleMiddleware 中间件中

d(mixed ...$vars)

如果你没有安装symfony/var-dumper,需要先安装

composer require symfony/var-dumper

你可以传入多个变量,如果使用swoole/workerman,需要重启服务

特别注意:异常处理使用中间件的方式,中间件未处理的异常需要用户手动处理,所以在中间件外执行的代码不能使用d函数打印变量

swagger文档

推荐使用下面的扩展包

https://zircote.github.io/swagger-php

1738 1 2
1个评论

青衣煮茶

支持一下

Chengyao

220
积分
0
获赞数
0
粉丝数
2022-09-06 加入
🔝