drmyersii / klein
一款针对 PHP 的闪电般快速的路由器
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/php-code-coverage: 1.2.x
- phpunit/phpunit: 3.7.x
- squizlabs/php_codesniffer: 1.4.8
This package is not auto-updated.
Last update: 2024-09-20 17:37:49 UTC
README
klein.php 是一个快速且灵活的 PHP 5.3+ 路由器
- 灵活的正则表达式路由(灵感来自 Sinatra)
- 一组用于快速构建 Web 应用程序的样板方法
- 几乎没有开销 => 2500+ 请求/秒
入门指南
Composer 安装
- 获取 Composer
- 使用
php composer.phar require klein/klein
安装 Klein - 将以下内容添加到您的应用程序主 PHP 文件中:
require 'vendor/autoload.php';
示例
Hello World - 必要的 Hello World 示例
<?php require_once __DIR__ . '/vendor/autoload.php'; $klein = new \Klein\Klein(); $klein->respond('GET', '/hello-world', function () { return 'Hello World!'; }); $klein->dispatch();
示例 1 - 响应所有请求
$klein->respond(function () { return 'All the things'; });
示例 2 - 命名参数
$klein->respond('/[:name]', function ($request) { return 'Hello ' . $request->name; });
示例 3 - So RESTful
$klein->respond('GET', '/posts', $callback); $klein->respond('POST', '/posts', $callback); $klein->respond('PUT', '/posts/[i:id]', $callback); $klein->respond('DELETE', '/posts/[i:id]', $callback); $klein->respond('OPTIONS', null, $callback); // To match multiple request methods: $klein->respond(array('POST','GET'), $route, $callback); // Or you might want to handle the requests in the same place $klein->respond('/posts/[create|edit:action]?/[i:id]?', function ($request, $response) { switch ($request->action) { // } });
示例 4 - 发送对象/文件
$klein->respond(function ($request, $response, $service) { $service->xml = function ($object) { // Custom xml output function } $service->csv = function ($object) { // Custom csv output function } }); $klein->respond('/report.[xml|csv|json:format]?', function ($request, $response, $service) { // Get the format or fallback to JSON as the default $send = $request->param('format', 'json'); $response->$send($report); }); $klein->respond('/report/latest', function ($request, $response, $service) { $response->file('/tmp/cached_report.zip'); });
示例 5 - 全部组合
$klein->respond(function ($request, $response, $service, $app) use ($klein) { // Handle exceptions => flash the message and redirect to the referrer $klein->onError(function ($klein, $err_msg) { $klein->service()->flash($err_msg); $klein->service()->back(); }); // The fourth parameter can be used to share scope and global objects $app->db = new PDO(...); // $app also can store lazy services, e.g. if you don't want to // instantiate a database connection on every response $app->register('db', function() { return new PDO(...); }); }); $klein->respond('POST', '/users/[i:id]/edit', function ($request, $response, $service, $app) { // Quickly validate input parameters $service->validateParam('username', 'Please enter a valid username')->isLen(5, 64)->isChars('a-zA-Z0-9-'); $service->validateParam('password')->notNull(); $app->db->query(...); // etc. // Add view properties and helper methods $service->title = 'foo'; $service->escape = function ($str) { return htmlentities($str); // Assign view helpers }; $service->render('myview.phtml'); }); // myview.phtml: <title><?php echo $this->escape($this->title) ?></title>
路由命名空间
$klein->with('/users', function () use ($klein) { $klein->respond('GET', '/?', function ($request, $response) { // Show all users }); $klein->respond('GET', '/[:id]', function ($request, $response) { // Show a single user }); }); foreach(array('projects', 'posts') as $controller) { // Include all routes defined in a file under a given namespace $klein->with("/$controller", "controllers/$controller.php"); }
包含的文件在 Klein 的作用域内运行($klein
),因此可以使用 $this
访问所有 Klein 方法/属性
示例文件: "controllers/projects.php"
// Routes to "/projects/?" $this->respond('GET', '/?', function ($request, $response) { // Show all projects });
懒加载服务
可以将服务存储为 懒加载,这意味着它们仅在首次使用时才实例化。
<?php $klein->respond(function ($request, $response, $service, $app) { $app->register('lazyDb', function() { $db = new stdClass(); $db->name = 'foo'; return $db; }); }); //Later $klein->respond('GET', '/posts', function ($request, $response, $service, $app) { // $db is initialised on first request // all subsequent calls will use the same instance return $app->lazyDb->name; });
验证器
要添加自定义验证器,请使用 addValidator($method, $callback)
$service->addValidator('hex', function ($str) { return preg_match('/^[0-9a-f]++$/i', $str); });
您可以使用 is<$method>()
或 not<$method>()
验证参数,例如。
$service->validateParam('key')->isHex();
或者,您可以使用相同的流程验证任何字符串。
$service->validate($username)->isLen(4,16);
验证方法是可以链式的,并且可以指定自定义异常消息,以在验证失败时使用
$service->validateParam('key', 'The key was invalid')->isHex()->isLen(32);
路由
[ match_type : param_name ]
一些示例
* // Match all request URIs
[i] // Match an integer
[i:id] // Match an integer as 'id'
[a:action] // Match alphanumeric characters as 'action'
[h:key] // Match hexadecimal characters as 'key'
[:action] // Match anything up to the next / or end of the URI as 'action'
[create|edit:action] // Match either 'create' or 'edit' as 'action'
[*] // Catch all (lazy)
[*:trailing] // Catch all as 'trailing' (lazy)
[**:trailing] // Catch all (possessive - will match the rest of the URI)
.[:format]? // Match an optional parameter 'format' - a / or . before the block is also optional
更多复杂示例
/posts/[*:title][i:id] // Matches "/posts/this-is-a-title-123"
/output.[xml|json:format]? // Matches "/output", "output.xml", "output.json"
/[:controller]?/[:action]? // Matches the typical /controller/action format
注意 - 所有 与请求 URI 匹配的路由都会被调用 - 这允许您整合复杂的条件逻辑,如用户身份验证或视图布局。例如,以下代码将包装其他路由的标题和页脚
$klein->respond('*', function ($request, $response, $service) { $service->render('header.phtml'); }); //other routes $klein->respond('*', function ($request, $response, $service) { $service->render('footer.phtml'); });
路由自动匹配整个请求 URI。如果您需要匹配请求 URI 的部分或使用自定义正则表达式,请使用 @
操作符。如果您需要否定路由,请使用 !
操作符
// Match all requests that end with '.json' or '.csv' $klein->respond('@\.(json|csv)$', ... // Match all requests that _don't_ start with /admin $klein->respond('!@^/admin/', ...
视图
您可以通过将它们分配给 $service
对象或将它们作为 $service->render()
的第二个参数传递,将属性或助手发送到视图
$service->escape = function ($str) { return htmlentities($str); }; $service->render('myview.phtml', array('title' => 'My View')); // Or just: $service->title = 'My View';
myview.phtml
<title><?php echo $this->escape($this->title) ?></title>
视图在 $service
的作用域内编译和运行,因此可以使用 $this
访问所有服务方法
$this->render('partial.html') // Render partials $this->sharedData()->get('myvar') // Access stored service variables echo $this->query(array('page' => 2)) // Modify the current query string
API
以下列出了您最有可能使用的常用类中的公共方法。有关更正式的类/方法文档,请参阅 PHPdoc 生成的文档。
$request-> id($hash = true) // Get a unique ID for the request paramsGet() // Return the GET parameter collection paramsPost() // Return the POST parameter collection paramsNamed() // Return the named parameter collection cookies() // Return the cookies collection server() // Return the server collection headers() // Return the headers collection files() // Return the files collection body() // Get the request body params() // Return all parameters params($mask = null) // Return all parameters that match the mask array - extract() friendly param($key, $default = null) // Get a request parameter (get, post, named) isSecure() // Was the request sent via HTTPS? ip() // Get the request IP userAgent() // Get the request user agent uri() // Get the request URI pathname() // Get the request pathname method() // Get the request method method($method) // Check if the request method is $method, i.e. method('post') => true query($key, $value = null) // Get, add to, or modify the current query string <param> // Get / Set (if assigned a value) a request parameter $response-> protocolVersion($protocol_version = null) // Get the protocol version, or set it to the passed value body($body = null) // Get the response body's content, or set it to the passed value status() // Get the response's status object headers() // Return the headers collection cookies() // Return the cookies collection code($code = null) // Return the HTTP response code, or set it to the passed value prepend($content) // Prepend a string to the response body append($content) // Append a string to the response body isLocked() // Check if the response is locked requireUnlocked() // Require that a response is unlocked lock() // Lock the response from further modification unlock() // Unlock the response sendHeaders($override = false) // Send the HTTP response headers sendCookies($override = false) // Send the HTTP response cookies sendBody() // Send the response body's content send() // Send the response and lock it isSent() // Check if the response has been sent chunk($str = null) // Enable response chunking (see the wiki) header($key, $value = null) // Set a response header cookie($key, $value = null, $expiry = null) // Set a cookie cookie($key, null) // Remove a cookie noCache() // Tell the browser not to cache the response redirect($url, $code = 302) // Redirect to the specified URL dump($obj) // Dump an object file($path, $filename = null) // Send a file json($object, $jsonp_prefix = null) // Send an object as JSON or JSONP by providing padding prefix $service-> sharedData() // Return the shared data collection startSession() // Start a session and return its ID flash($msg, $type = 'info', $params = array() // Set a flash message flashes($type = null) // Retrieve and clears all flashes of $type markdown($str, $args, ...) // Return a string formatted with markdown escape($str) // Escape a string refresh() // Redirect to the current URL back() // Redirect to the referer query($key, $value = null) // Modify the current query string query($arr) layout($layout) // Set the view layout yieldView() // Call inside the layout to render the view content render($view, $data = array()) // Render a view or partial (in the scope of $response) partial($view, $data = array()) // Render a partial without a layout (in the scope of $response) addValidator($method, $callback) // Add a custom validator method validate($string, $err = null) // Validate a string (with a custom error message) validateParam($param, $err = null) // Validate a param <callback>($arg1, ...) // Call a user-defined helper <property> // Get a user-defined property $app-> <callback>($arg1, ...) //Call a user-defined helper $validator-> notNull() // The string must not be null isLen($length) // The string must be the exact length isLen($min, $max) // The string must be between $min and $max length (inclusive) isInt() // Check for a valid integer isFloat() // Check for a valid float/decimal isEmail() // Check for a valid email isUrl() // Check for a valid URL isIp() // Check for a valid IP isAlpha() // Check for a-z (case insensitive) isAlnum() // Check for alphanumeric characters contains($needle) // Check if the string contains $needle isChars($chars) // Validate against a character list isRegex($pattern, $modifiers = '') // Validate against a regular expression notRegex($pattern, $modifiers ='') is<Validator>() // Validate against a custom validator not<Validator>() // The validator can't match <Validator>() // Alias for is<Validator>()
单元测试
单元测试是开发像Klein这样的路由引擎的重要组成部分。增加的功能或错误修复可能在没有大量测试的情况下产生难以发现的不利影响,因此单元测试的重要性。
本项目使用PHPUnit作为其单元测试框架。
所有测试都位于/tests
目录中,每个测试都扩展了一个抽象类AbstractKleinTest
要测试项目,只需运行php composer.phar install --dev
以使用composer下载PHPUnit的通用版本,然后从主目录使用./vendor/bin/phpunit
运行测试
贡献
有关更多信息,请参阅贡献指南
更多信息
有关更多信息,请参阅wiki
贡献者
许可证
(MIT许可证)
版权(c)2010 Chris O'Hara cohara87@gmail.com
特此授予任何人免费获得此软件及其相关文档文件(“软件”)副本的权限,用于无限制地处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售软件副本,并允许向软件提供的人士从事此类活动,前提是遵守以下条件
上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。
软件按“原样”提供,不提供任何明示或暗示的保证,包括但不限于适销性、适用于特定目的和无侵权性的保证。在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论该责任是基于合同、侵权或其他原因,是否因软件或软件的使用或其他方式产生。