bead/framework

一个(处于开发中的)PHP应用程序框架

0.9.12 2023-10-14 10:47 UTC

This package is auto-updated.

Last update: 2024-09-29 20:51:09 UTC


README

一个基本的PHP MVC应用程序框架。

PHP unit tests

介绍

Bead是一个简单的MVC框架,适用于PHP 8.0及其以后的版本。

WebApplication

使用bead的每个Web应用程序都必须创建这个单例类的实例。它是应用程序的核心,提供了一组有用的功能,例如访问配置细节、插件加载、请求路由、事件注册和调度、错误处理以及发送响应。在大多数情况下,你可能想要创建一个子类,并重新实现构造函数和/或exec()方法来执行应用程序特定的初始化。应用程序通过从主index.php脚本中调用exec()方法来执行。

exec()中的初始化期间,WebApplication加载应用程序的配置、插件和路由。路由通过应用程序的路由器注册,默认情况下是一个\Bead\Router的实例。你可以通过调用WebApplication::setRouter()并传入一个实现了\Bead\Contracts\Router接口的对象来提供自己的路由器,这可以在你的自定义WebApplication子类的构造函数中完成,或者在创建WebApplication实例之后(显然是在调用exec()之前)在你的index.php文件中完成。

WebApplication单例总是可以通过WebApplication::instance()静态方法访问。

路由

路由从应用程序源代码的子目录中加载的路线文件中加载,默认为/routes。每个路线文件都是一个标准的PHP文件,其目的是将路由注册到路由器。路线文件通过匿名函数沙盒加载 - 路由文件可用的唯一变量是$app,WebApplication实例(为了方便);$router,路由器实例;以及PHP超级全局变量。

默认路由器使用HTTP方法和请求路径信息来路由请求。例如,你可以调用$router->registerGet()来注册GET HTTP方法的路线,或者调用$router->registerPost()来注册POST HTTP方法的路线。默认路由器中提供了以下注册方法

  • register($path, $methods, $handler) - 为具有指定HTTP方法集的路径注册处理器
  • registerGet($path, $handler) - 仅使用GET HTTP方法为路径注册处理器
  • registerPost($path, $handler) - 仅使用POST HTTP方法为路径注册处理器
  • registerPut($path, $handler) - 仅使用PUT HTTP方法为路径注册处理器
  • registerHead($path, $handler) - 仅使用HEAD HTTP方法为路径注册处理器
  • registerDelete($path, $handler) - 仅使用DELETE HTTP方法为路径注册处理器
  • registerConnect($path, $handler) - 仅使用CONNECT HTTP方法为路径注册处理器
  • registerOptions($path, $handler) - 仅使用OPTIONS HTTP方法为路径注册处理器
  • registerPatch($path, $handler) - 仅使用PATCH HTTP方法为路径注册处理器
  • registerPatch($path, $handler) - 仅使用PATCH HTTP方法为路径注册处理器
  • registerAny($path, $handler) - 为任何HTTP方法为路径注册处理器

你可以根据项目的需要组织路线文件。你定义的路线文件数量没有人为限制。

路线处理器可以是任何可调用的。通常,你将定义控制器并使用方法作为路线处理器。如果提供一个形式的处理器

$router->registerGet("/some/path", [MyController::class, "theRequestHandler"]);

控制器必须有一个默认构造函数才能正常工作。如果您的控制器需要构造函数参数,或者您想使用控制器的特定实例,您可以这样做

$router->registerGet("/some/path", [new MyController($arg), "theRequestHandler"]);

任何其他可调用的表达式也可以使用

$router->registerGet("/", fn() => new View("home"));
$router->registerGet("/", "home_page_handler");     // home_page_handler() is a function defined by your app

默认路由器可以为您的路由处理程序提供参数。通过使用用花括号括起来的路径段,您可以从URL路径中提取部分内容,并将其作为参数传递给处理程序。路由器将匹配段名与处理程序中的参数名,并将从URL中提取的值作为该参数传递给处理程序。如果可能,它还会根据处理程序中参数的类型提示转换参数。例如,定义路由

$router->registerGet("/article/{articleId}/author/{authorId}/remove", function (int $articleId, int $authorId) {});

对于来自 /article/333/author/200/remove 的传入HTTP GET请求,将调用处理程序,并将 (int) 333 作为 $articleId 的参数,将 (int) 200 作为 $authorId 的参数。

在任何路由处理程序中,您还可以使用 \Bead\Request 类型为任何名称的参数提供类型提示,处理程序将接收传入的Request作为该参数的参数。

插件

这是用于增强应用程序功能的组件的基类。通常,插件会向 WebApplication 单例注册事件处理程序,以响应应用程序中的事件。例如,您可以使用插件来监听 "application.handlerequest.requestreceived" 事件,并在检测到请求来自被禁止的IP地址时抛出 NotAuthorisedException

您的插件目录(默认为 /app/plugins)中的所有插件都将为应用程序的每个请求加载和实例化。因此,您应该将插件构造函数保持相对简单,以避免性能下降。

请求

客户端请求的封装。通过调用 WebApplication::exec(),将根据 $_GET$_POST$_FILES$_SERVER 超全局变量构建此类的实例。可以通过调用 WebApplication 对象的 originalRequest() 方法来始终获取传入的请求。

请求类提供了对客户端请求提供的URL参数、POST数据和上传文件的访问。它还提供了对HTTP头部的访问。

视图

视图是存储在 /views 目录中的普通PHP文件。您可以按照项目需要的任何方式组织视图。使用点符号标识视图。要实例化视图,请将其名称传递给 View 构造函数 - 例如,存储在 /views/users/edit.php 的视图将使用 new View("users.edit") 实例化。注意,基本 /views 目录名称不包括在内,.php 文件扩展名也不包括在内。

您可以使用构造函数的第二个参数向视图传递数据。数据作为关联数组传递。视图将接收一个名为数组键的变量集。所有视图也接收两个便利变量:$app 是当前运行的 WebApplication 实例;$data 是传递给构造函数的视图数据数组。视图由匿名函数沙盒渲染 - 视图中不可用全局变量,只有 $app、视图数据和PHP超全局变量。

为了保持页面的一致性,每个视图都可以使用布局。布局与普通视图没有区别,但(为了有用),它们应该包含命名部分。打算用作布局的视图应该有一个或多个对View::yieldSection("section-name")的调用。每个命名部分定义了视图可以添加内容的位置。视图通过在视图开头调用View::layout("layouts.layout-name")来指示它们使用的布局,并通过在View::section("section-name")View::endSection()之间放置内容来为布局的部分提供内容。当布局提供部分时,视图放入其中的内容将被渲染。布局可以定义任意多的命名部分。布局可以存储在您的/views树中的任何位置,但为了清晰起见,建议您使用/views/layouts

您可以通过两种方式为视图构建可重用的部分:一种方式是调用View::include("view-name")直接包含另一个视图的内容;另一种是调用View::component("component-name")View::endComponent()将另一个视图的内容作为一个组件包含。使用includes和components之间只有很小的区别

  • includes继承了包含它们的视图的所有视图数据
  • components有它们自己的数据上下文,并且可以在中提供内容

通常,如果您想包含的视图片段是您页面的相对静态部分(例如,导航),并且您只是为了方便维护而对其进行了抽象,那么使用View::include()可能是最合适的。如果您包含一个需要参数的可配置组件(例如,一种用户输入控件),您可能最好使用组件。有关详细信息,请参阅View类的单独文档。

所有View都满足Response契约,因此您可以从您的处理方法中直接返回一个View实例。

数据库和模型

该框架包含一个非常简单的ORM,以便在大多数情况下轻松查询和更新应用程序数据库中的数据。Bead\Database\Connection类通过一些静态方法扩展了内置的PDO类。Model基类使创建数据库中存储的数据的代码表示变得简单。在最简单的情况下,您只需创建一个子类,将$properties静态成员填充为模型所代表的表中列的名称和类型,将$table静态成员填充为数据库表的名称。

验证

验证对使用过Laravel验证框架的人来说会感到熟悉。您通过创建一个Bead\Validation\Validator并为其提供一个要应用和要应用它们的数据的规则集来验证数据。如果数据有效,验证器将从passes()返回true。如果它返回false,它将提供一个从errors()的错误信息集。