Learn/learn
学习
此页面是学习 Flight 的指南。它涵盖了框架的基础知识以及如何使用它。
路由
在 Flight 中,路由通过将 URL 模式与回调函数进行匹配来完成。
Flight::route('/', function(){ echo '你好,世界!'; }); 回调可以是任何可调用的对象。因此,您可以使用常规函数:
function hello(){ echo '你好,世界!'; } Flight::route('/', 'hello'); 或类方法:
class Greeting { public static function hello() { echo '你好,世界!'; } } Flight::route('/', array('Greeting','hello')); 或对象方法:
class Greeting { public function __construct() { $this->name = '约翰·多'; } public function hello() { echo "你好,{$this->name}!"; } } $greeting = new Greeting(); Flight::route('/', array($greeting, 'hello')); 路由按定义的顺序匹配。第一个匹配请求的路由将被调用。
方法路由
默认情况下,路由模式将与所有请求方法进行匹配。您可以通过在 URL 之前放置标识符来响应特定方法。
Flight::route('GET /', function(){ echo '我收到了一个 GET 请求。'; }); Flight::route('POST /', function(){ echo '我收到了一个 POST 请求。'; }); 您还可以通过使用 | 分隔符将多个方法映射到单个回调:
Flight::route('GET|POST /', function(){ echo '我收到了一个 GET 或 POST 请求。'; }); 正则表达式
您可以在路由中使用正则表达式:
Flight::route('/user/[0-9]+', function(){ // 这将匹配 /user/1234 }); 命名参数
您可以在路由中指定命名参数,这些参数将传递给回调函数。
Flight::route('/@name/@id', function($name, $id){ echo "你好, $name ($id)!"; }); 您还可以通过使用 : 分隔符包含正则表达式与命名参数:
Flight::route('/@name/@id:[0-9]{3}', function($name, $id){ // 这将匹配 /bob/123 // 但不会匹配 /bob/12345 }); 可选参数
您可以通过将片段放在括号中来指定可选参数进行匹配。
Flight::route('/blog(/@year(/@month(/@day)))', function($year, $month, $day){ // 这将匹配以下 URL: // /blog/2012/12/10 // /blog/2012/12 // /blog/2012 // /blog }); 任何未匹配的可选参数将作为 NULL 传递。
通配符
匹配仅在单个 URL 片段上进行。如果要匹配多个片段,可以使用 * 通配符。
Flight::route('/blog/*', function(){ // 这将匹配 /blog/2000/02/01 }); 要将所有请求路由到单个回调,可以这样做:
Flight::route('*', function(){ // 做一些事情 }); 继续
您可以通过在回调函数中返回 true 将执行传递给下一个匹配的路由。
Flight::route('/user/@name', function($name){ // 检查某个条件 if ($name != "Bob") { // 继续到下一个路由 return true; } }); Flight::route('/user/*', function(){ // 这将被调用 }); 路由信息
如果您想查看匹配的路由信息,可以通过将 true 作为第三个参数传递给路由方法来请求将路由对象传递给回调。路由对象将始终是传递给回调函数的最后一个参数。
Flight::route('/', function($route){ // 匹配的 HTTP 方法数组 $route->methods; // 命名参数数组 $route->params; // 匹配的正则表达式 $route->regex; // 包含 URL 模式中使用的任何 '*' 的内容 $route->splat; }, true); 路由分组
有时您可能想将相关路由分组在一起(如 /api/v1)。您可以使用 group 方法做到这一点:
Flight::group('/api/v1', function () { Flight::route('/users', function () { // 匹配 /api/v1/users }); Flight::route('/posts', function () { // 匹配 /api/v1/posts }); }); 您甚至可以嵌套分组:
Flight::group('/api', function () { Flight::group('/v1', function () { // Flight::get() 获取变量,而不是设置路由!请查看下面的对象上下文 Flight::route('GET /users', function () { // 匹配 GET /api/v1/users }); Flight::post('/posts', function () { // 匹配 POST /api/v1/posts }); Flight::put('/posts/1', function () { // 匹配 PUT /api/v1/posts }); }); Flight::group('/v2', function () { // Flight::get() 获取变量,而不是设置路由!请查看下面的对象上下文 Flight::route('GET /users', function () { // 匹配 GET /api/v2/users }); }); }); 使用对象上下文进行分组
您仍然可以使用 Engine 对象进行路由分组,如下所示:
$app = new \flight\Engine(); $app->group('/api/v1', function (Router $router) { $router->get('/users', function () { // 匹配 GET /api/v1/users }); $router->post('/posts', function () { // 匹配 POST /api/v1/posts }); }); 路由别名
您可以为路由分配别名,以便在代码中可以动态生成 URL(例如,一个模板)。
Flight::route('/users/@id', function($id) { echo '用户:'.$id; }, false, 'user_view'); // 稍后在代码的某个地方 Flight::getUrl('user_view', [ 'id' => 5 ]); // 将返回 '/users/5' 这在您的 URL 发生变化时尤其有用。在上面的示例中,假设用户被移动到了 /admin/users/@id。 有了别名,您不必更改引用别名的任何地方,因为别名将现在返回 /admin/users/5,就像上面的示例一样。
路由别名仍然在分组中有效:
Flight::group('/users', function() { Flight::route('/@id', function($id) { echo '用户:'.$id; }, false, 'user_view'); }); // 稍后在代码的某个地方 Flight::getUrl('user_view', [ 'id' => 5 ]); // 将返回 '/users/5' 扩展
Flight 旨在成为一个可扩展的框架。框架附带了一组默认的方法和组件,但它允许您映射自己的方法、注册自己的类,甚至覆盖现有的类和方法。
映射方法
要映射您自己的自定义方法,您使用 map 函数:
// 映射您的方法 Flight::map('hello', function($name){ echo "你好 $name!"; }); // 调用您的自定义方法 Flight::hello('Bob'); 注册类
要注册您自己的类,您使用 register 函数:
// 注册您的类 Flight::register('user', 'User'); // 获取您的类的实例 $user = Flight::user(); 注册方法还允许您将参数传递给类构造函数。因此,当您加载自定义类时,它将预先初始化。您可以通过传递额外的数组来定义构造函数参数。这是加载数据库连接的示例:
// 注册带有构造函数参数的类 Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','pass')); // 获取您的类的实例 // 这将使用定义的参数创建一个对象 // // new PDO('mysql:host=localhost;dbname=test','user','pass'); // $db = Flight::db(); 如果您传递额外的回调参数,它将在类构造后立即执行。这允许您为新对象执行任何设置程序。回调函数接受一个参数,即新对象的实例。
// 回调将传递构造的对象 Flight::register('db', 'PDO', array('mysql:host=localhost;dbname=test','user','pass'), function($db){ $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } ); 默认情况下,每次加载类时,您将获得一个共享实例。要获得类的新实例,只需将 false 作为参数传入:
// 类的共享实例 $shared = Flight::db(); // 类的新实例 $new = Flight::db(false); 请记住,映射的方法优先于注册的类。如果您使用相同的名称同时声明两者,则仅调用映射的方法。
重写
Flight 允许您重写其默认功能,以适应您的需求,而不必修改任何代码。
例如,当 Flight 无法将 URL 匹配到路由时,它调用 notFound 方法,并发送通用的 HTTP 404 响应。您可以通过使用 map 方法重写此行为:
Flight::map('notFound', function(){ // 显示自定义 404 页面 include 'errors/404.html'; }); Flight 还允许您替换框架的核心组件。 例如,您可以用自己的自定义类替换默认 Router 类:
// 注册您的自定义类 Flight::register('router', 'MyRouter'); // 当 Flight 加载 Router 实例时,它将加载您的类 $myrouter = Flight::router(); 然而,像 map 和 register 这样的框架方法是无法被重写的。如果您尝试这样做,将会引发错误。
过滤
Flight 允许您在调用方法之前和之后进行过滤。没有预定义的钩子需要记忆。您可以过滤任何默认框架方法以及您映射的任何自定义方法。
过滤函数如下所示:
function(&$params, &$output) { // 过滤代码 } 使用传入的变量,您可以操作输入参数和/或输出。
您可以在方法之前运行过滤:
Flight::before('start', function(&$params, &$output){ // 做一些事情 }); 您可以在方法之后运行过滤:
Flight::after('start', function(&$params, &$output){ // 做一些事情 }); 您可以向任何方法添加任意数量的过滤器。它们将按照声明的顺序被调用。
以下是过滤过程的示例:
// 映射一个自定义方法 Flight::map('hello', function($name){ return "你好, $name!"; }); // 添加一个之前的过滤器 Flight::before('hello', function(&$params, &$output){ // 操纵参数 $params[0] = 'Fred'; }); // 添加一个之后的过滤器 Flight::after('hello', function(&$params, &$output){ // 操纵输出 $output .= " 祝您有个愉快的一天!"; }); // 调用自定义方法 echo Flight::hello('Bob'); 这应该显示:
你好 Fred! 祝您有个愉快的一天! 如果您定义了多个过滤器,您可以通过在任何过滤函数中返回 false 来打破链:
Flight::before('start', function(&$params, &$output){ echo '一'; }); Flight::before('start', function(&$params, &$output){ echo '二'; // 这将结束链 return false; }); // 这将不会被调用 Flight::before('start', function(&$params, &$output){ echo '三'; }); 请注意,核心方法如 map 和 register 不能被过滤,因为它们是直接调用的,而不是动态调用的。
变量
Flight 允许您保存变量,以便在应用程序的任何地方使用。
// 保存您的变量 Flight::set('id', 123); // 在您应用程序的其他地方 $id = Flight::get('id'); 要查看变量是否已设置,您可以执行:
if (Flight::has('id')) { // 做一些事情 } 您可以通过以下方式清除变量:
// 清除 id 变量 Flight::clear('id'); // 清除所有变量 Flight::clear(); Flight 还使用变量进行配置。
Flight::set('flight.log_errors', true); 视图
Flight 默认提供一些基本的模板功能。要显示视图模板,请调用 render 方法,并传入模板文件的名称和可选的模板数据:
Flight::render('hello.php', array('name' => 'Bob')); 您传入的模板数据会自动注入到模板中,并可以像局部变量一样引用。模板文件仅是 PHP 文件。如果 hello.php 模板文件的内容为:
你好,'<?php echo $name; ?>'! 输出将是:
你好,Bob! 您还可以通过使用 set 方法手动设置视图变量:
Flight::view()->set('name', 'Bob'); 变量 name 现在可以在您所有的视图中使用。因此,您可以简单地做:
Flight::render('hello'); 请注意,当在渲染方法中指定模板的名称时,您可以省略 .php 扩展名。
默认情况下,Flight 将查找一个 views 目录来查找模板文件。您可以通过设置以下配置来指定模板的替代路径:
Flight::set('flight.views.path', '/path/to/views'); 布局
网站通常有一个单一的布局模板文件,具有互换内容。要呈现内容以在布局中使用,您可以将可选参数传递给 render 方法。
Flight::render('header', array('heading' => '你好'), 'header_content'); Flight::render('body', array('body' => '世界'), 'body_content'); 您的视图将保存名为 header_content 和 body_content 的变量。然后,您可以通过做以下操作来渲染您的布局:
Flight::render('layout', array('title' => '主页')); 如果模板文件看起来像这样:
header.php:
<h1><?php echo $heading; ?></h1> body.php:
<div><?php echo $body; ?></div> layout.php:
<html> <head> <title><?php echo $title; ?></title> </head> <body> <?php echo $header_content; ?> <?php echo $body_content; ?> </body> </html> 输出将是:
<html> <head> <title>主页</title> </head> <body> <h1>你好</h1> <div>世界</div> </body> </html> 自定义视图
Flight 允许您通过注册自己的视图类来替换默认视图引擎。以下是如何为您的视图使用 Smarty 模板引擎:
// 加载 Smarty 库 require './Smarty/libs/Smarty.class.php'; // 将 Smarty 注册为视图类 // 还传入一个回调函数以在加载时配置 Smarty Flight::register('view', 'Smarty', array(), function($smarty){ $smarty->template_dir = './templates/'; $smarty->compile_dir = './templates_c/'; $smarty->config_dir = './config/'; $smarty->cache_dir = './cache/'; }); // 分配模板数据 Flight::view()->assign('name', 'Bob'); // 显示模板 Flight::view()->display('hello.tpl'); 为了完整性,您还应该重写 Flight 的默认 render 方法:
Flight::map('render', function($template, $data){ Flight::view()->assign($data); Flight::view()->display($template); }); 错误处理
错误和异常
所有错误和异常都由 Flight 捕获并传递给 error 方法。默认行为是发送通用的 HTTP 500 内部服务器错误 响应,并附带一些错误信息。
您可以重写此行为以满足您的需求:
Flight::map('error', function(Exception $ex){ // 处理错误 echo $ex->getTraceAsString(); }); 默认情况下,错误不会记录到 Web 服务器。您可以通过更改配置来启用此操作:
Flight::set('flight.log_errors', true); 找不到
当找不到 URL 时,Flight 会调用 notFound 方法。默认行为是发送 HTTP 404 找不到 响应,并附带一条简单的消息。
您可以重写此行为以满足您的需求:
Flight::map('notFound', function(){ // 处理未找到 }); 重定向
您可以使用 redirect 方法通过传入新 URL 来重定向当前请求:
Flight::redirect('/new/location'); 默认情况下,Flight 发送 HTTP 303 状态代码。您可以选择设置自定义代码:
Flight::redirect('/new/location', 401); 请求
Flight 将 HTTP 请求封装为一个单一对象,可以通过以下方式访问:
$request = Flight::request(); 请求对象提供以下属性:
url - 请求的 URL base - URL 的父子目录 method - 请求方法 (GET, POST, PUT, DELETE) referrer - 引用 URL ip - 客户端的 IP 地址 ajax - 请求是否为 AJAX 请求 scheme - 服务器协议 (http, https) user_agent - 浏览器信息 type - 内容类型 length - 内容长度 query - 查询字符串参数 data - POST 数据或 JSON 数据 cookies - Cookie 数据 files - 上传的文件 secure - 连接是否安全 accept - HTTP 接受参数 proxy_ip - 客户端的 Proxy IP 地址 您可以将 query、data、cookies 和 files 属性作为数组或对象访问。
因此,要获取查询字符串参数,您可以执行:
$id = Flight::request()->query['id']; 或者您可以执行:
$id = Flight::request()->query->id; 原始请求体
要获取原始 HTTP 请求体,例如处理 PUT 请求时,您可以执行:
$body = Flight::request()->getBody(); JSON 输入
如果您发送一个类型为 application/json 和数据为 {"id": 123} 的请求,它将在 data 属性中可用:
$id = Flight::request()->data->id; 停止
您可以通过调用 halt 方法在任何时刻停止框架:
Flight::halt(); 您还可以指定可选的 HTTP 状态代码和消息:
Flight::halt(200, '稍后回来...'); 调用 halt 将丢弃到那时为止的任何响应内容。如果您想停止框架并输出当前响应,请使用 stop 方法:
Flight::stop(); HTTP 缓存
Flight 提供对 HTTP 级缓存的内置支持。如果满足缓存条件,Flight 将返回 HTTP 304 未修改 响应。下次客户端请求同一资源时,他们将被提示使用其本地缓存版本。
最后修改
您可以使用 lastModified 方法并传入 UNIX 时间戳来设置页面上次修改的日期和时间。客户端将继续使用其缓存,直到最后一次修改值更改。
Flight::route('/news', function(){ Flight::lastModified(1234567890); echo '此内容将被缓存。'; }); ETag
ETag 缓存类似于 Last-Modified,但您可以为资源指定任何您想要的 ID:
Flight::route('/news', function(){ Flight::etag('my-unique-id'); echo '此内容将被缓存。'; }); 请记住,调用 lastModified 或 etag 将设置并检查缓存值。如果请求之间的缓存值相同,Flight 将立即发送 HTTP 304 响应并停止处理。
JSON
Flight 提供对发送 JSON 和 JSONP 响应的支持。要发送 JSON 响应,您只需传递一些数据以进行 JSON 编码:
Flight::json(array('id' => 123)); 对于 JSONP 请求,您可以选择传入用于定义回调函数的查询参数名称:
Flight::jsonp(array('id' => 123), 'q'); 因此,当使用 ?q=my_func 发起 GET 请求时,您应该接收到以下输出:
my_func({"id":123}); 如果您没有传入查询参数名称,默认为 jsonp。
配置
您可以通过设置配置值来自定义 Flight 的某些行为,方法是通过 set 方法。
Flight::set('flight.log_errors', true); 以下是所有可用配置设置的列表:
flight.base_url - 覆盖请求的基本 URL。(默认为:null) flight.case_sensitive - 对 URL 进行大小写敏感匹配。(默认为:false) flight.handle_errors - 允许 Flight 内部处理所有错误。(默认为:true) flight.log_errors - 将错误记录到 Web 服务器的错误日志文件。(默认为:false) flight.views.path - 包含视图模板文件的目录。(默认为:./views) flight.views.extension - 视图模板文件扩展名。(默认为:.php) 框架方法
Flight 旨在易于使用和理解。以下是框架的完整方法集。它由核心方法(常规静态方法)和可扩展方法(可过滤或重写的映射方法)组成。
核心方法
Flight::map(string $name, callable $callback, bool $pass_route = false) // 创建自定义框架方法。 Flight::register(string $name, string $class, array $params = [], ?callable $callback = null) // 将类注册到框架方法。 Flight::before(string $name, callable $callback) // 在框架方法之前添加过滤器。 Flight::after(string $name, callable $callback) // 在框架方法之后添加过滤器。 Flight::path(string $path) // 添加用于自动加载类的路径。 Flight::get(string $key) // 获取变量。 Flight::set(string $key, mixed $value) // 设置变量。 Flight::has(string $key) // 检查变量是否已设置。 Flight::clear(array|string $key = []) // 清除变量。 Flight::init() // 将框架初始化为默认设置。 Flight::app() // 获取应用程序对象实例 可扩展方法
Flight::start() // 启动框架。 Flight::stop() // 停止框架并发送响应。 Flight::halt(int $code = 200, string $message = '') // 以可选状态码和消息停止框架。 Flight::route(string $pattern, callable $callback, bool $pass_route = false) // 将 URL 模式映射到回调。 Flight::group(string $pattern, callable $callback) // 创建 URL 分组,模式必须是字符串。 Flight::redirect(string $url, int $code) // 重定向到另一个 URL。 Flight::render(string $file, array $data, ?string $key = null) // 渲染模板文件。 Flight::error(Throwable $error) // 发送 HTTP 500 响应。 Flight::notFound() // 发送 HTTP 404 响应。 Flight::etag(string $id, string $type = 'string') // 执行 ETag HTTP 缓存。 Flight::lastModified(int $time) // 执行最后修改的 HTTP 缓存。 Flight::json(mixed $data, int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // 发送 JSON 响应。 Flight::jsonp(mixed $data, string $param = 'jsonp', int $code = 200, bool $encode = true, string $charset = 'utf8', int $option) // 发送 JSONP 响应。 任何使用 map 和 register 添加的自定义方法也可以被过滤。
框架实例
您可以选择以对象实例的方式运行 Flight,而不是以全局静态类的方式运行。
require 'flight/autoload.php'; use flight\Engine; $app = new Engine(); $app->route('/', function(){ echo '你好,世界!'; }); $app->start(); 因此,您将以名为 Engine 的对象调用相同名称的实例方法,而不是调用静态方法。
Install
安装
1. 下载文件。
如果您使用的是 Composer,您可以运行以下命令:
composer require flightphp/core 或者您可以直接 下载 文件并将其提取到您的 Web 目录中。
2. 配置您的 Web 服务器。
对于 Apache,用以下内容编辑您的 .htaccess 文件:
RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [QSA,L] 注意:如果您需要在子目录中使用 flight,请在
RewriteEngine On后添加一行RewriteBase /subdir/。 注意:如果您想保护所有服务器文件,比如数据库或环境文件。 请将其放入您的.htaccess文件中:
RewriteEngine On RewriteRule ^(.*)$ index.php 对于 Nginx,在您的服务器声明中添加以下内容:
server { location / { try_files $uri $uri/ /index.php; } } 3. 创建您的 index.php 文件。
首先引入框架。
require 'flight/Flight.php'; 如果您使用 Composer,请改为运行自动加载器。
require 'vendor/autoload.php'; 然后定义一个路由并分配一个函数来处理请求。
Flight::route('/', function () { echo '你好,世界!'; }); 最后,启动框架。
Flight::start();About
什么是 Flight ?
Flight 是一个快速、简单、可扩展的 PHP 框架。 Flight 使您能够快速轻松地构建 RESTful 网络应用程序。
require 'flight/Flight.php'; // 定义路由 Flight::route('/', function(){ echo 'hello world!'; }); // 启动 Flight Flight::start(); 需求
Flight 需要 PHP 7.4 或更高版本。
许可
Flight 根据 MIT 许可发布。
社区
我们在 Matrix 上!请在 #flight-php-framework:matrix.org 与我们聊天。
贡献
本网站托管在 Github 上。 欢迎更新和语言翻译。