定制 iassasin/easyroute 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

iassasin/easyroute

Composer 安装命令:

composer require iassasin/easyroute

包简介

Very lightweight and simple router for PHP

README 文档

README

PHP Version Build Status Coverage Status

Simple router do not require a lot of setups, install in few minutes and just works.

Installation

To start using router complete 4 simple steps:

  1. Install easyroute via composer:
composer require iassasin/easyroute
  1. Setup yours routes in root directory of project. For example in file routes.php:
require_once 'vendor/autoload.php';
use Iassasin\Easyroute\Router;
use Iassasin\Easyroute\Route;

$router = new Router();
$router->setControllersPath($_SERVER['DOCUMENT_ROOT'].'/controllers/');
$router->addRoutes([
	new Route('/(:controller:(/:action:(/:arg)?)?)?', ['controller' => 'home', 'action' => 'index', 'arg' => null]),
]);
$router->processRoute();
  1. Tell web server redirect all requests (except static assets/) to router via .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/assets/
RewriteRule ^(.*)$ routes.php [B,QSA,L]
  1. Create first controller in controllers/home.php:
class ControllerHome {
	public function index($arg){
		return '<html><body>Home page! '.($arg !== null ? 'Argument: '.$arg : 'Argument not set').'</body></html>';
		// or use "return new Response('...')" which is more flexible
	}
}

That's it!

Note that file name must match :controller name from URL template and controller class name must match :controller name with prefix Controller. In example above route /home/index matches file controllers/home.php and class ControllerHome.

Useful features

Route with parameters

Route is a regex string with simpler syntax for naming route arguments. For example:

  • /:controller/:action/:arg (all parameters are required)
  • /(foo|bar)-:arg/gotcha (regex and partial parameter matching. Valid are /foo-123/gotcha, /bar-qwerty/gotcha, but not /qwerty/gotcha)
  • /:arg? (parameter arg can be ommited, but not /. Valid are /, /param, but not /sub/param)
  • /(:controller:(/:action:(/:arg)?)?)? (all parameters not required. Valid are /, /home, /home/index/val, but not /home/, /home/index/)

Parameter name must match regex [a-zA-Z_0-9]+.
By default :parameter match regex [^\/]+, but you can use your own filter:

new Route('/:arg(\d+)?', // arg not required and can contains only numerics
	['controller' => 'home', 'action' => 'index', 'arg' => null], // default values
)

If you need to use ( to match group, but not to filter parameter, use trailing : in parameter name: /:controller:(postfix1|postfix2) will match /homepostfix1 with controller = 'home'.

Built-in simple dependency injection container

You can use built-in dependency injection container to split app code into services (which will be loaded via autoload) and simply use it in controller's actions:

class ControllerHome {
	public function index($arg, Request $request, DatabaseService $db){
		// ...
	}
}

Services constructors can use dependency injection too and require another services via same syntax.

Class SampleContainer impletents Psr\Container\ContainerInterface.

use Iassasin\Easyroute\Router;

$router = new Router();
/** @var SimpleContainer $container */
$container = $router->getContainer(); // get default container

// Instantiate and add services by hand
$container->setService(Database::class, new Database('login', 'password'));
// Disable automatic instantiation for services
$container->setAutowireEnabled(false);

Also you can use another dependency injection container:

use Iassasin\Easyroute\Router;
use Iassasin\Easyroute\Http\Request;

$router = new Router();
$request = Request::createFromGlobals();

// some implementation of ContainerInterface
$container = new MyContainer();
// Router don't know how to register Request class in your container implementation
// You should to do it by self if you want to use Request class in controllers
// See next section for details of Request class
$container->register(Request::class, $request);

$router->setContainer($container);

Request class

Using dependency injection container you have access to Request service that provides access to request parameters.

Request has fields listed below:

  • query - $_GET array
  • request - $_POST array
  • attributes - assoc array with any data, which you can set at Request instance creation
  • cookies - $_COOKIE array
  • files - $_FILES array
  • server - $_SERVER array

Each field is instance of Parameters class and has methods:

  • get(string $name) - get parameter by it's name
  • has(string $name) - does parameter with $name exists
  • all() - get all parameters in array

Request provide some useful methods:

  • getContent() - get whole http post content as string
  • getClientIP() - returns $this->server->get('REMOTE_ADDR')
  • getScriptName() - returns $this->server->get('SCRIPT_NAME')
  • getScheme() - returns $this->server->get('REQUEST_SCHEME')
  • getHost() - returns $this->server->get('SERVER_NAME')
  • getUri() - returns $this->server->get('REQUEST_URI')
  • getMethod() - returns $this->server->get('REQUEST_METHOD')
  • getProtocol() - returns $this->server->get('SERVER_PROTOCOL')

Response class

Response class used to return data to client. Return Response instances from controller's actions instead of manual data send using echo or etc.

Built-in response classes

There is 3 built-in response classes:

  • Response - base class for all responses, has methods:
    • __construct(string $content, int $statusCode = 200, array $headers = [])
    • getStatusCode(), setStatusCode(int $code) - get/set http status code
    • getContent(), setContent(string $content) - get/set http response content
    • getHeaders(), setHeaders(array $headers) - get/set http headers
    • setHeader(string $name, string $value) - set single header
    • send() - send response to client, called from handlers
  • Response404 - extends Request for default http 404 error with:
    • __construct(string $url, array $headers = [])
    • getUrl() - get URL caused 404 error
  • Response500 - extends Request for default http 500 error. Generated if any exception thrown during route processing.
    • __construct(\Throwable $exception = null, array $headers = [])
    • getException() - get exception thrown during route processing
  • ResponseJson - extends Request for sending json responses, also set correct http Content-Type header.
    • __construct(object|array $data, int $statusCode = 200, array $headers = [])
    • getData(), setData(object|array $data) - set source data to send to client
    • Note that setContent can't be used and throws LogicException

Custom handlers for response classes

Set custom handlers for Response classes:

use Iassasin\Easyroute\Http\Responses\Response404;

$router->setResponseHandler(Response404::class, function(Response404 $resp){
	$resp->setContent('<html><body><h1>Custom 404 Not Found</h1> The requested url "<i>'.htmlspecialchars($resp->getUrl()).'</i>" not found!');
	$resp->send();
	return true; // do not call other handlers
});

And custom handlers for any http status code:

use Iassasin\Easyroute\Http\Response;

$router->setStatusHandler(302, function(Response $resp){
	$resp->setContent('You have redirected');
	$resp->send();
	return true; // do not call other handlers
});

Note 1: you can use both handlers set, but response handlers will be called first (and can stop calling status handlers).

Note 2: you can set handler for parent response class to match all childs, child handlers will be always called first: from most child to first parent. So, you can match all responses setting handler for Response::class.

Subdirectories for controllers

Separate zones with subdirectories:

(new Route('/admin/:controller/:action?', ['action' => 'index']))
	->setControllersSubpath('zones/admin')
	// '/admin/home/index' will match 'controllers/zones/admin/home.php'
	// and class 'ControllerHome'

Filtering access

Use RouteFilter to prevent access to some routes:

use Iassasin\Easyroute\RouteFilter;

class RouteFilterAdmin extends RouteFilter {
	public function preRoute($path, $controller, $action, $args){
		if (!isCurrentUserAdmin()){
			(new Response('Access denied!', 403))->send();
			return Router::COMPLETED; // Do not call controller's action
		}

		return Router::CONTINUE; // Call controller's action
	}
}
//...
(new Route('/admin/:controller/:action?', ['action' => 'index']))
	->setFilter(new RouteFilterAdmin())

Custom controller class name prefix

Set custom controller class name prefix (default - Controller):

$router->setControllerClassPrefix('TheController');

iassasin/easyroute 适用场景与选型建议

iassasin/easyroute 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 52 次下载、GitHub Stars 达 0, 最近一次更新时间为 2017 年 08 月 19 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「route」 「mvc」 「controller」 「router」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 iassasin/easyroute 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 iassasin/easyroute 我们能提供哪些服务?
定制开发 / 二次开发

基于 iassasin/easyroute 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 52
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2017-08-19