吉吉霍霍/ ichi-route
PHP项目的路由库
Requires
- php: >=7.0 || >=8.0
README
ICHI PHP ROUTER旨在成为快速、易于使用且能够保护安全漏洞的PHP路由器
许可证
本软件包根据MIT许可证开源
目录
安装
composer require jijihohococo/ichi-route
设置
根据您的服务器,在设置路由之前,您必须创建以下htaccess文件。
Apache
在您的根目录下创建 .htaccess 文件
RewriteEngine On
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
Nginx
在您的根目录下创建 .htacess 文件
rewrite ^/(.*)/$ /$1 redirect;
if (!-e $request_filename){
rewrite ^(.*)$ /index.php break;
}
创建控制器
您必须为您的路由创建控制器。
首先,您需要在项目目录下创建名为 "ichi" 的文件,并在该文件中使用以下代码:
#!/usr/bin/env php <?php require __DIR__.'/vendor/autoload.php'; use JiJiHoHoCoCo\IchiRoute\Command\RouteCommand; $routeCommand=new RouteCommand; $routeCommand->run(__DIR__,$argv);
然后您可以在命令行中创建控制器
php ichi make:controller ItemController
默认文件文件夹是 "app/Controllers"。所以执行命令后,您创建的控制器将位于此默认文件文件夹中。如果您想更改默认文件夹路径,您可以在 "ichi" 文件中更改它。
$routeCommand=new RouteCommand; $routeCommand->setPath('new_app/Controllers'); $routeCommand->run(__DIR__,$argv);
单一路由
您可以使用 "get"、"post"、"put"、"delete" 和 "head" 函数添加路由。
每个函数代表每种路由方法
您可以使用闭包函数或控制器类的函数添加路由。
使用闭包函数
use JiJiHoHoCoCo\IchiRoute\Router\Route; $route=new Route; $route->get('items',function(){ echo "show items"; });
使用控制器类
$route->get('items','App\Controllers\ItemController@show');
在使用路由函数之前,您必须在 composer.json 中自动加载您的控制器文件夹。
"autoload": { "psr-4": { "App\\": "app/" } }
如果您所有控制器的控制器路径相同,您可以在添加路由之前为所有路由设置基本控制器路径。
$route->setBaseControllerPath('App\Controllers');
要运行所有路由,您必须使用 "run()" 函数。
在声明系统中的所有路由之后,您必须使用 "run()" 函数。
$route->run();
运行路由函数后,路由(URL)可以运行
'items/' (GET METHOD)
PATCH方法
要创建PATCH方法,您需要__method请求,并在此处添加'PATCH'值。动作必须是'POST'。
在您的路由中
$route->patch('items','App\Controllers\ItemController@show');
对于表单数据
<form action="<?php echo route('items'); ?>" method="POST"> <?php method('PATCH'); ?> </form>
PUT方法
要创建PUT方法,您需要__method请求,并在此处添加'PUT'值。动作必须是'POST'。
在您的路由中
$route->put('items','App\Controllers\ItemController@show');
对于表单数据
<form action="<?php echo route('items'); ?>" method="POST"> <?php method('PUT'); ?> </form>
DELETE方法
要创建DELETE方法,您需要__method请求,并在此处添加'DELETE'值。动作必须是'POST'。
在您的路由中
$route->delete('items','App\Controllers\ItemController@show');
对于表单数据
<form action="<?php echo route('items'); ?>" method="POST"> <?php method('DELETE'); ?> </form>
使用路由
在前端调用路由
<a href="<?php echo route('items'); ?>">Items</a>
路由参数
在许多情况下,您需要创建路由参数的时间
$route->get('items/show/{id}','App\Controllers\ItemController@show');
在您的控制器类中
namespace App\Controllers; class ItemController{ // 'items/show/{id}' // public function show($id){ echo $id; } }
您也可以使用闭包函数进行
$route->get('items/show/{id}',function($id){ echo $id; })
运行路由函数后,路由(URL)可以运行
'items/show/1' (GET METHOD) 'items/show/2' (GET METHOD)
在前端调用路由
<a href="<?php echo route('items/show/1'); ?>" >Item 1</a> <a href="<?php echo route('items/show/2'); ?>" >Item 2</a>
资源路由
您可以使用单个路由方法进行CRUD路由
$route->resource('items','App\Controllers\ItemController');
在您的控制器类中
namespace App\Controllers; class ItemController{ // GET METHOD // // 'items' // public function index(){ } // GET METHOD // // 'items/create' // public function create(){ } // POST METHOD // // 'items/create' // public function save(){ } // GET METHOD // // 'items/{id}/edit' public function edit($id){ } // PUT METHOD // // 'items/{id}/edit' // public function update($id){ } // DELETE METHOD // // 'items/{id}/destroy' // public function destroy($id){ } }
根据创建控制器的说明,在终端中创建资源控制器
php ichi make:controller ItemController --resource
运行路由函数后,路由(URL)可以运行
'items/' (GET METHOD) // Go to to get items' list 'items/create' (GET METHOD) // Go to create item 'items/create' (POST METHOD) // Create items 'items/1/edit' (GET METHOD) // Go to update item 'items/1/edit' (PUT METHOD) // Update item 'items/1/destroy' (DELETE METHOD) // Delete item
根据创建控制器的说明,在终端中创建API资源控制器
php ichi make:controller ItemController --api-resource
运行路由函数后,路由(URL)可以运行
'items/' (GET METHOD) // Go to to get items' list 'items/create' (POST METHOD) // Create items 'items/1/edit' (GET METHOD) // Go to update item 'items/1/edit' (PUT METHOD) // Update item 'items/1/destroy' (DELETE METHOD) // Delete item
前缀路由
您可以使用前缀路由来创建分组。
$route->group(['url_group'=>'admin'],function(){ $this->get('items','App\Controllers\ItemController@getItems'); $this->get('brands','App\Controllers\BrandController@getBrands'); });
因此以下URL可以使用:
'admin/items' (GET METHOD) 'admin/brands' (GET METHOD)
您可以在分组闭包函数中添加路由。
在声明 "url_group" 时,不要包含 '/'。
子域名路由
如果您想使用子域名,必须在声明路由之前设置主域名。
use JiJiHoHoCoCo\IchiRoute\Router\Route; $route=new Route; $route->setDefaultDomain('your_main_domain.com');
单个子域名
您可以使用 "domain()" 函数设置子域名路由。
您可以在 "domain()" 函数中使用所有路由函数。
您不能在分组函数中使用 domain 函数。
$route->domain('your_subdomain.com',function(){ $this->get('items','Subdomain/ItemController@get'); });
如果您想显示子域名路由,请使用 getSubdomainRoute 函数。第一个参数是域名,第二个参数是此子域名下声明的路由。
<a href="<?php echo getSubdomainRoute('your_subdomain.com','items'); ?>" >Subdomain Items</a>
子域名参数
如果您想在子域名中使用参数
参数用大括号 "{}" 包围作为路由参数。
您必须将子域名参数传递到闭包函数或类的函数中。
类的函数
$route->domain('{subdomain}.com',function(){ $this->get('items','Subdomain/ItemController@get'); });
namespace App\Controllers\Subdomain; class ItemController{ public function get($subdomain){ } }
闭包函数
$route->domain('{subdomain}.com',function(){ $this->get('items',function($subdomain){ }); })
如果您想使用多个子域名参数,在参数和字符串之间使用点 "."。
类的函数
$route->domain('{subdomain}.{person}.com',function(){ $this->get('items','Subdomain/ItemController@get'); });
namespace App\Controllers\Subdomain; class ItemController{ public function get($subdomain,$person){ } }
闭包函数
$route->domain('{subdomain}.{person}.com',function(){ $this->get('items',function($subdomain,$person){ }); });
如果您想在子域名参数中使用路由参数,您必须在类的函数或闭包函数中传递子域名参数和路由参数。
类的函数
$route->domain('{subdomain}.{person}.com',function(){ $this->get('items/{id}','Subdomain/ItemController@get'); });
namespace App\Controllers\Subdomain; class ItemController{ public function get($subdomain,$person,$id){ } }
闭包函数
$route->domain('{subdomain}.{person}.com',function(){ $this->get('items/{id}',function($subdomain,$person,$id){ }); });
如果您想在中间件中获取属于子域名路由的子域名参数
在您的中间件类中
namespace App\Middlewares; use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware; class TestMiddleware extends MainMiddleware{ public function handle(){ $subdomainParameters=$this->getDomainParameters(); } }
您不能像路由参数那样将子域名参数传递给中间件。
依赖注入
您可以使用控制器类进行依赖注入。
您必须根据以下格式有接口和类
您的接口和类必须被自动加载
依赖注入的类的函数将自动运行
在您的控制器类中
namespace App\Controllers; use App\Repositories\ItemRepositoryInteface; class ItemController{ public $item; public function __construct(ItemRepositoryInteface $item){ $this->item=$item; } }
您也可以在存储库中添加另一个依赖注入。
namespace App\Repositories; use App\Repositories\{ItemRepositoryInteface,BrandRepositoryInterface}; class ItemRepository implements ItemRepositoryInteface{ public $brand; public function __construct(BrandRepositoryInterface $brand){ $this->brand=$brand; } }
中间件
您可以将中间件添加到单个路由,如下所示
$route->get('order','App\Controllers\OrderController@order',[ 'App\Middlewares\OrderMiddleware' ]);
您必须声明中间件类
根据我们之前提到的,您的中间件类必须在 composer 中自动加载
namespace App\Middlewares; use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware; class OrderMiddleware extends MainMiddleware{ public function handle(){ //--check your business logic--// return $this->next(); } }
您必须扩展 JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware 并添加 "handle()" 函数。在您的 "handle" 函数中,您必须始终返回 "next()" 函数。您可以在 "handle" 函数中检查您的业务交易。
创建 "ichi" 文件后,您可以通过终端创建中间件,正如我们之前在 创建控制器 中提到的
php ichi make:middleware OrderMiddleware
观察者的默认路径为 "app/Middlewares"。您也可以在 "ichi" 文件中更改此路径。
$routeCommand=new RouteCommand; $routeCommand->setResourcePath('new_app/Middlewares'); $routeCommand->run(__DIR__,$argv);
您可以为多个中间件类添加多个中间件。
$route->get('order','App\Controllers\OrderController@order',[ 'App\Middlewares\LoginMiddleware', 'App\Middlewares\OrderMiddleware' ]);
由于每个 "handle()" 函数中都使用了 "next()" 函数,因此这些中间件将按顺序加载。
您可以在中间件中使用您的路由参数添加参数。
$route->get('items/{id}','App\Controllers\ItemController@getItems',[ 'App\Middlewares\CheckItemMiddleware:id' ]);
在您的中间件类中
namespace App\Middlewares; use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware; class CheckItemMiddleware extends MainMiddleware{ public function handle($id){ //--check your business logic--// return $this->next(); } }
您可以在中间件中使用您的路由参数添加多个参数。
$route->get('items/{id}/{stock_id}', 'App\Controllers\ItemController@getItems',[ 'App\Middlewares\CheckItemMiddleware:id,stock_id' ]);
在您的中间件类中
namespace App\Middlewares; use JiJiHoHoCoCo\IchiRoute\Middleware\MainMiddleware; class CheckItemMiddleware extends MainMiddleware{ public function handle($id,$stock){ //--check your business logic--// return $this->next(); } }
您可以在前缀路由中添加中间件,就像在单个路由和参数路由中做的那样。
$route->group(['url_group' => 'admin' , 'middleware' => ['App\Middlewares\CheckAdminMiddleware'] ],function(){ $this->resource('items','App\Controllers\ItemController'); });
您只能在前缀路由中添加中间件。
$route->group(['middleare' => ['App\Middlewares\CheckUserMiddleware'] ],function(){ $this->get('order','App\Controllers\OrderController@order'); });
如果您所有中间件的路由路径都相同,您可以在添加路由之前为所有路由设置基本中间件路径。
$route->setBaseMiddlewarePath('App\Middlewares');
此库中已经编写了一些中间件。对于这些中间件,您必须完全声明它们的中间件路径。
如果您想为所有路由检查中间件
如果您没有声明基本中间件路径
$route->defaultMiddlewares([ 'App\Middlewares\CheckUserMiddleware' ]);
如果您声明了基本中间件路径
$route->defaultMiddlewares([ 'CheckUserMiddleware' ]);
CSRF令牌认证
您可以使用 CSRF Token 身份验证来保护创建和更新路由
在声明路由之前,您必须生成 CSRF Token。
use JiJiHoHoCoCo\IchiRoute\Router\Route; generateCSRFToken(); $route=new Route; $route->post('items','App\ItemController@create',[ 'JiJiHoHoCoCo\IchiRoute\Middleware\CSRFMiddleware' ]);
您也可以在您的路由中添加 JiJiHoHoCoCo\IchiRoute\Middleware\CSRFMiddleware。
use JiJiHoHoCoCo\IchiRoute\Router\Route; generateCSRFToken(); $route=new Route; $route->group(['middleare' => ['JiJiHoHoCoCo\IchiRoute\Middleware\CSRFMiddleware'] ],function(){ $this->post('items','App\ItemController@create'); });
在您的前端 PHP 文件中
<form action="<?php echo route('items'); ?>" method="POST" > <?php csrfToken(); ?> <input type="text" name="name"> <input type="submit" name="submit"> </form>
API请求认证
您可以为您的路由添加中间件,仅接受 API 请求
$route->get('items_api','App\Controllers\ItemController@getItems',[ 'JiJiHoHoCoCo\IchiRoute\Middleware\APIMiddleware' ]);
要传递 JiJiHoHoCoCo\IchiRoute\Middleware\APIMiddleware,您必须在请求该 API 路由时将 "Content-Type" 头中的值添加为 "application/json"。
CORS
您可以通过 CORS 获取来自另一个域的数据
$route->get('items_api','App\Controllers\ItemController@getItems',[ 'JiJiHoHoCoCo\IchiRoute\Middleware\CORSMiddleware' ]);
您可以使用 JiJiHoHoCoCo\IchiRoute\Setting\CORS 为您的 CORS 添加选项
use JiJiHoHoCoCo\IchiRoute\Setting\CORS; CORS::setAvialableSites(['http://domain-one.com','http://domain-two.com']); // To set Access Control Allow Origins (default is '*') CORS::setAvailableSitesRegex(['/w3schools/']); // To set Access Control Allow Origins according to regex CORS::setAvialableMethods(['GET','POST']); // To set Access Control Allow Origin Methods (default is '*') CORS::setAvailableHeaders(['X-Custom-Header','Upgrade-Insecure-Requests']); // To set Access Control Allow Origin Headers (default is '*') CORS::setToAllowCredential(); // To set Access Control Allow Credentials to TRUE. (default is 'false') CORS::setMaxAge(3600); // To set Access Control Max Age (default is 0)
路由缓存
您可以使用以下方式缓存参数路由
- 数据库
- Redis
- Memcached
在添加路由之前,您必须执行以下操作
数据库缓存
您必须在数据库中运行以下SQL代码来创建 "ichi_routes" 表
CREATE TABLE IF NOT EXISTS ichi_routes( id INT AUTO_INCREMENT, route_key VARCHAR(100) NOT NULL, route_method VARCHAR(100) NOT NULL, expired_time VARCHAR(100) NULL, PRIMARY KEY(id))
并且添加您的pdo对象,并设置过期时间(以秒为单位)
$route->setPDO($pdoObject,10000);
您也可以不设置过期时间
$route->setPDO($pdoObject);
Redis缓存
添加您的redis对象,并设置过期时间(以秒为单位)
$route->setRedis($redisObject,10000);
您也可以不设置过期时间
$route->setRedis($redisObject);
Memcached缓存
添加您的memcached对象,并设置过期时间(以秒为单位)
$route->setMemcached($memcachedObject,10000);
您也可以不设置过期时间
$route->setMemcached($memcachedObject);
自定义错误页面
您可以调用错误页面(无论它是默认的还是有自定义的)
use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage; echo ErrorPage::show(); exit();
默认错误信息是 "404 - URL未找到"。默认HTTP响应代码是 404。
您可以自定义错误信息和HTTP响应代码
use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage; echo ErrorPage::show('403 - Unauthorized Request',403); exit();
如果您不喜欢此库提供的默认错误页面,您可以显示自己的错误页面
use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage; ErrorPage::setErrorPage('<!DOCTYPE html> <html> <head> <title>Page Title</title> </head> <body> <h1>404</h1> <p>404 URL</p> </body> </html>');
如果您想根据您的HTTP响应代码显示更具体的错误,您必须创建一个函数
use JiJiHoHoCoCo\IchiRoute\UI\ErrorPage; $errorPage=function($message,$code){ return <<<HTML <html> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>$message</title> <body style="background-color: white;"> <div style="position: fixed;top:50%;left:50%;transform: translate(-50%, -50%);color:black;font-family: 'Nunito', sans-serif;"> <p>$message</p> </div> </body> </html> HTML; }; ErrorPage::setErrorPage($errorPage);
在您的自定义函数中,您必须有 "$message" 和 "$code" 参数