lucinda / mvc
PHP应用程序中通过MVC模式处理请求到响应的超高性能API
Requires
- php: ^8.1
- ext-simplexml: *
- lucinda/abstract_mvc: ^2.0
Requires (Dev)
- lucinda/unit-testing: ^2.0
- dev-master
- v4.1.5
- v4.1.4
- v4.1.3
- v4.1.2
- v4.1.1
- v4.1.0
- v4.0.x-dev
- v4.0.3
- v4.0.2
- v4.0.1
- v4.0.0
- v3.2.6
- v3.2.5
- v3.2.4
- v3.2.3
- v3.2.2
- v3.2.1
- v3.2.0
- v3.1.0
- v3.0.x-dev
- v3.0.9.1
- v3.0.9
- v3.0.8
- v3.0.7
- v3.0.6.2
- v3.0.6.1
- v3.0.6
- v3.0.5
- v3.0.4
- v3.0.3
- v3.0.2
- v3.0.1
- v3.0.0.7
- v3.0.0.6
- v3.0.0.5
- v3.0.0.4
- v3.0.0.3
- v3.0.0.2
- v3.0.0.1
- v3.0.0
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.8.2
- v2.1.8.1
- v2.1.8
- v2.1.7
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0.2
- v2.1.0.1
- v2.1.0
- v2.0.x-dev
- v2.0.9
- v2.0.8
- v2.0.7
- v2.0.6
- v2.0.5
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.4.4.4
- v1.4.4.3
- v1.4.4.2
- v1.4.4.1
- v1.4.4
- v1.4.3.1
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.0
- v1.0.x-dev
- v1.0.1
- v1.0.0
This package is auto-updated.
Last update: 2024-09-07 11:43:02 UTC
README
目录
关于
此API是一个(需要开发者绑定)的框架(用于高效处理Web请求到服务器响应),其中视图和模型应该是独立的,而控制器基于用户请求在两者之间进行调解。它以模块化、效率和简单为基础,既面向对象也面向事件:类似于JavaScript,它允许开发者在处理过程中绑定在预定义事件达到时将执行的逻辑。
API仅执行标准MVC逻辑,因此在实际生活中,它期望在顶部构建一个Web框架以添加更多功能(例如:数据库连接)。为了使用它,开发者需要执行以下步骤
- 配置:设置一个XML文件,其中包含此API的配置
- 绑定点:将用户在XML/代码中定义的组件绑定到API原型中,以获得必要的功能
- 初始化:实例化FrontController,一个Runnable,可以在处理过程中根据上述内容处理请求到响应
- 绑定事件:设置将在处理过程中达到预定义事件时实例化和运行的Runnable类
- 配置共享变量:扩展Attributes类,以封装特定于项目的变量,以便在事件监听器和控制器之间共享
- 处理:在FrontController上调用run方法,最终处理请求到响应,触发上述事件(如果有任何)
API完全符合PSR-4标准,仅需要抽象MVC API来执行基本MVC逻辑,PHP8.1+解释器和SimpleXML扩展。要快速了解其工作原理,请查看
- 安装:根据上述步骤,描述如何在您的计算机上安装API
- 参考指南:描述了所有与开发人员相关的API类、方法和字段
- 单元测试:API具有100%的单元测试覆盖率,使用UnitTest API代替PHPUnit以获得更大的灵活性
- 示例:基于FrontController单元测试的API功能深入示例
内部所有类都属于 Lucinda\STDOUT 命名空间!
配置
要配置此API,您必须有一个包含以下标签的XML文件
- 应用:(必填)在一般基础上配置您的应用
- 解析器:(必填)配置您的应用能够解析响应的格式
- 路由:(必填)配置将请求资源绑定到控制器和视图的路由
- 会话:(可选)配置在创建会话时自动使用选项
- Cookie:(可选)配置在设置Cookie时自动使用的选项
应用
标签文档完全由继承的抽象MVC API 规范 覆盖!由于此API的STDIN由HTTP(s)请求组成,因此 default_route 属性的值必须指向 index(主页)以处理不带路由的请求。
解析器
标签文档完全由继承的抽象MVC API 规范 覆盖!
路由
此标签的最大语法是
<routes> <route id="..." controller="..." view="..." format="..." method="..."> <parameter name="..." validator="..." mandatory="..."/> ... </route> ... </routes>
大多数标签逻辑已由抽象MVC API 规范 覆盖。以下额外观察需要指出
- id:(必填)请求资源URL(不带尾随斜杠)。可以是精确的URL(例如:foo/bar)或URL模式(例如:user/(id))。如果使用模式,每个变量都必须命名并放在括号内!
- controller:(可选)用户定义的PS-4自动加载兼容类(包括命名空间)的名称,该类将基于模型缓解请求和响应
类必须是 控制器 实例! - method:(可选)持有请求资源时必须使用的单个HTTP方法。如果请求使用不同的方法,则会抛出 MethodNotAllowedException!
标签示例
<routes> <route id="index" controller="Lucinda\Project\Controllers\Homepage" view="index"/> <route id="user/(id)" controller="Lucinda\Project\Controllers\UserInfo" view="user-info"> </routes>
^ 在 应用 XML标签中,必须定义由 default_route 属性定义的路由!
如果请求没有路由,则使用 默认 路由。但是,如果请求具有不匹配 id 的路由,则抛出 PathNotFoundException!
路由参数
每个 route 标签可以包含一个或多个规则,以验证请求和路径参数的值,这些参数随请求一起发送。每个参数对应一个 parameter 标签,验证可以根据属性进行配置
- name:(必填)您想要验证的请求或路径参数的名称。示例
- foo,如果请求是GET并且带有查询字符串 ?foo=bar
- id,如果路由URL是 user/(id)
- validator:(必填) 用户自定义的PS-4自动加载兼容类(包括命名空间)的名称,该类将验证参数的值。
必须是EventListeners\Validators\ParameterValidator 实例! - mandatory:(可选) 表示参数是否必填(值可以是0或1)。如果没有指定,则默认为必填(1)!
^ 如果参数名称冲突,则路径参数优先于请求参数!
标签示例
<routes> <route id="index" controller="Lucinda\Project\Controllers\Homepage" view="index"/> <route id="user/(id)" controller="Lucinda\Project\Controllers\UserInfo" view="user-info" method="GET"> <parameter name="id" validator="Lucinda\Project\ParameterValidators\UserNameValidator"/> </route> </routes>
会话
此标签的最大语法是
<session save_path="..." name="..." expired_time="..." expired_on_close="..." https_only="..." headers_only="..." referrer_check="..." handler="..." auto_start="...">
位置
- save_path:(可选) 服务器上保存会话的绝对路径。例如:"/tmp/sessions/"
- name:(可选) 用于作为cookie名称的会话名称(默认:PHPSESSID)。例如:"SESSID"
- expired_time:(可选) 数据将被垃圾回收后的秒数。例如:"60"
- expired_on_close:(可选) 预期会话cookie在客户端浏览器关闭后存活的秒数。例如:"120"
- https_only:(可选) 将会话cookie标记为仅可通过安全的HTTPS连接访问。值:"1"
- headers_only:(可选) 将会话cookie标记为仅可通过HTTP协议访问。值:"1"
- referrer_check:(可选) 您想在每个HTTP Referer中检查的子字符串,以验证会话cookie。例如:"Chrome"
- handler:(可选) 实现了\SessionHandlerInterface 的用户自定义PS-4自动加载兼容类(包括命名空间)的名称。例如:"application/models/RedisHandler"
- auto_start:(可选) 表示会话将自动在每个请求中启动。值:"1"
标签示例
<session save_path="/tmp/sessions/" name="SESSID" expired_time="60" expired_on_close="120" https_only="1" headers_only="1" referrer_check="Chrome" handler="application/models/RedisHandler" auto_start="1">
Cookie
此标签的最大语法是
<cookies path="..." domain="..." https_only="..." headers_only="...">
位置
- path:(可选) 服务器上cookie可用的路径。例如:"/foo/"
- domain:(可选) cookie可用的(子)域名。例如:"www.example.com"
- https_only:(可选) 表示cookie应仅通过客户端的安全HTTPS连接传输。值:"1"
- headers_only:(可选) 表示cookie应仅通过HTTP协议访问。值:"1"
标签示例
<cookies path="/" domain="example.com" https_only="1" headers_only="1">
要了解在需要时如何正确设置 path 和 domain,请检查规范!
绑定点
为了保持灵活性和实现最高性能,API不假设超过绝对必要的任何内容!相反,它为开发者提供了将其原型绑定以获得一定功能的能力。
声明式绑定
它为开发者提供了通过XML 声明式地绑定到其原型类/接口的能力。
程序式绑定
它为开发者提供了通过FrontController 构造函数 程序式地绑定到其原型的能力
和addEventListener方法(请参阅绑定事件部分)!
执行
初始化
开发者为配置API的XML设置完成后,他们最终可以通过实例化FrontController 来初始化它。
除了实现Runnable 接口所需的 run 方法外,类还提供了以下公共方法
位置
- $documentDescriptor:XML 配置 文件的相对位置。例如:"configuration.xml"
- $attributes:请参阅 配置共享变量。
- $type:事件类型(参见下文的绑定事件),由枚举EventType封装。
- $className:监听器类名,包括命名空间和子文件夹,在实例化属性时定义的文件夹中找到。
示例
$handler = new FrontController("configuration.xml", new MyCustomAttributes("application/event_listeners"); $handler->run();
绑定事件
如上所述,API允许开发人员通过addEventListener方法将监听器绑定到处理生命周期事件。每个EventType对应一个抽象的Runnable类。
监听器必须扩展相应的事件类并实现必要的run方法,该方法包含在事件被触发时执行的逻辑。它们必须在run方法运行之前进行注册。
$handler = new FrontController("stdout.xml", new FrameworkAttributes("application/listeners"); $handler->addEventListener(EventType::APPLICATION, Lucinda\Project\EventListeners\Logging::class); $handler->addEventListener(EventType::REQUEST, Lucinda\Project\EventListeners\Security::class); $handler->run();
要了解如何定位事件监听器,请查看规范!
配置共享变量
API允许事件监听器设置将要提供给后续事件监听器和控制器的变量。对于每个变量都有一个
- setter:由事件监听器运行一次
- getter:由后续事件监听器和控制器运行
API附带Attributes,它包含每个站点都必须扩展以设置其自己的变量的基础。除非您的网站非常简单,否则将需要开发人员扩展此类并添加更多变量,为此必须定义setter和getter!
处理
完成上述步骤后,开发人员最终可以通过FrontController的run方法来处理请求到响应,该控制器
- 检测EventListeners\Start监听器并按注册顺序执行它们
- 将配置XML文件封装到Application对象中
- 检测EventListeners\Application监听器并按注册顺序执行它们
- 基于$_SERVER超全局变量封装请求信息到Request对象
- 基于$_SESSION超全局变量以及Session对象中可用的操作封装会话信息
- 基于$_COOKIE超全局变量以及Cookie对象中可用的操作封装cookie操作和变量
- 检测EventListeners\Request监听器并按注册顺序执行它们
- 基于从请求或XML检测到的信息初始化空的Lucinda\MVC\Response
- 基于已经检测到的信息定位Controller,如果找到,则执行它以将模型绑定到视图
- 基于已经检测到的信息定位Lucinda\MVC\ViewResolver并执行它以根据视图填充响应体
- 检测EventListeners\Response监听器并按注册顺序执行它们
- 将包含头部和正文的Lucinda\MVC\Response对象返回给调用者
- 检测EventListeners\End监听器并按照注册顺序执行
所有由开发者负责的组件(控制器、Lucinda\MVC\ViewResolver,以及事件监听器本身)都实现了Runnable接口。
安装
首先选择一个文件夹,然后在控制台该文件夹中使用以下命令
composer require lucinda/mvc
将上述文件夹重命名为DESTINATION_FOLDER,然后在其中创建一个包含以下内容的.htaccess文件
RewriteEngine on Options -Indexes ErrorDocument 404 default RewriteCond %{REQUEST_URI} !^/public RewriteRule ^(.*)$ index.php
然后在项目根目录下创建一个包含以下代码的configuration.xml配置文件和一个index.php初始化文件(参见上述初始化)
$controller = new Lucinda\STDOUT\FrontController("configuration.xml", new Attributes("application/events")); // TODO: add event listeners here $controller->run();
单元测试
有关测试和示例,请检查API源中的以下文件/文件夹
- test.php:在控制台运行单元测试
- unit-tests.xml:设置单元测试和模拟"loggers"标签
- tests:从src文件夹中的类进行的单元测试
参考指南
这些类完全由API实现
- Application:读取配置XML文件并封装内部信息
- Request:基于超全局变量$_SERVER、$_POST、$_GET中的信息封装用户请求
- Request\Client:封装从请求中检测到的客户端信息
- Request\Server:封装从请求中检测到的服务器信息
- Request\URI:封装从请求中检测到的uri信息
- Request\UploadedFiles\File:封装关于上传文件的详细信息
- Session:封装与映射到$_SESSION超全局变量的http会话操作
- Cookies:封装与映射到$_COOKIE超全局变量的http cookie操作
除了在绑定事件中提到的类之外,以下抽象类需要由开发者扩展以获得功能
- Controller:封装根据用户请求和XML信息将Request绑定到Lucinda\MVC\Response
- EventListeners\Validators\ParameterValidator:执行请求参数值的验证
Application 类
Application类封装从XML中检测到的信息,并定义了以下与开发者相关的公共方法
Request 类
类Request封装了基于超全局变量($_SERVER, $_GET, $_POST, $_FILES)检测到的用户请求信息,并为开发者定义了以下相关公共方法:
类 Request Client
类Request\Client封装了基于超全局变量$_SERVER检测到的客户端信息,并为开发者定义了以下相关公共方法:
类 Request Server
类Request\Server封装了基于超全局变量$_SERVER检测到的Web服务器信息,并为开发者定义了以下相关公共方法:
类 Request URI
类Request\URI封装了基于超全局变量$_SERVER检测到的路径信息,并为开发者定义了以下相关公共方法:
要了解这个类如何处理请求的URI,请查看规格说明!
类 Request UploadedFile
类Request\UploadedFiles\File封装了基于超全局变量$_FILES的单个上传文件信息,并为开发者定义了以下相关公共方法:
为了处理上传的文件,为开发者添加了两种方法。
要了解这个类如何处理上传的文件,请查看规格说明!
类 Session
类Session封装了通过$_SESSION超全局变量执行HTTP会话操作的方法,并为开发者定义了以下相关公共方法,所有这些都适用于开发者:
类 Session Cookie
类Session\Cookie封装了通过HTTP会话cookie执行操作的方法,并为开发者定义了以下相关公共方法,所有这些都适用于开发者:
类 Cookies
类Cookies封装了通过$_COOKIE超全局变量执行HTTP cookie操作的方法,并为开发者定义了以下相关公共方法,所有这些都适用于开发者:
接口 ParameterValidator
接口EventListeners\Validators\ParameterValidator实现了通过方法进行单个请求参数值验证的蓝图。
一个验证作为参数接收的用户名称的类的示例(例如:/user/(name)路由)
class UserNameValidator implements Lucinda\STDOUT\EventListeners\Validators\ParameterValidator { public function validate($value) { $result = DB("SELECT id FROM users WHERE name=:name", [":name"=>$value])->toValue(); return ($result?$result:null); } }
抽象类 EventListeners Start
抽象类EventListeners\Start实现了Runnable接口,并监听在读取配置 XML之前执行的事件。
开发者需要实现一个run方法,在该方法中,他们可以通过构造函数访问API注入的以下受保护字段:
START监听器的一个常见示例是设置开始时间,以便稍后基准测试处理持续时间。
class StartBenchmark extends Lucinda\STDOUT\EventListeners\Start { public function run(): void { // you will first need to extend Application and add: setStartTime, getStartTime $this->attributes->setStartTime(microtime(true)); } }
抽象类 EventListeners Application
抽象类 EventListeners\Application 实现了 Runnable) 并监听在读取 配置 XML 之后执行的的事件。
开发者需要实现一个run方法,在该方法中,他们可以通过构造函数访问API注入的以下受保护字段:
使用示例
https://github.com/aherne/lucinda-framework/blob/master/src/EventListeners/SQLDataSource.php
抽象类 EventListeners 请求
抽象类 EventListeners\Request 实现了 Runnable) 并监听在 Request、Session 和 Cookies 对象创建之后执行的事件。
开发者需要实现一个run方法,在该方法中,他们可以通过构造函数访问API注入的以下受保护字段:
使用示例
https://github.com/aherne/lucinda-framework/blob/master/src/EventListeners/Security.php
抽象类 EventListeners 响应
抽象类 EventListeners\Response 实现了 Runnable) 并监听在 Lucinda\MVC\Response 体被设置后、但在提交回调用者之前执行的事件。
开发者需要实现一个run方法,在该方法中,他们可以通过构造函数访问API注入的以下受保护字段:
使用示例
https://github.com/aherne/lucinda-framework/blob/master/src/EventListeners/HttpCaching.php
抽象类 EventListeners 结束
抽象类 EventListeners\End 实现了 Runnable) 并监听在 Lucinda\MVC\Response 被渲染回调用者之后执行的事件。
开发者需要实现一个run方法,在该方法中,他们可以通过构造函数访问API注入的以下受保护字段:
START 监听器的一个常见示例是设置结束时间,以便衡量处理持续时间。
class EndBenchmark extends Lucinda\STDOUT\EventListeners\End { public function run(): void { $benchmark = new Benchmark(); $benchmark->save($this->attributes->getStartTime(), microtime(true)); } }
抽象类 控制器
抽象类 Controller 实现了 Runnable),通过将先前检测到的信息绑定到模型来设置响应(特别是视图)。它定义了以下对开发者相关的公共方法
开发者需要为每个控制器实现 run 方法,其中他们可以访问通过构造函数由 API 注入的以下受保护字段
使用示例
要了解更多关于控制器如何被检测的信息,请查看 规范!
类属性
类 Attributes 封装了在整个请求-响应周期中收集的数据,每个对应一个 getter 和 setter,并可供后续事件监听器或控制器使用。API 已经包含了以下
收集的大部分数据都需要开发者自己设置以适应他们的项目需求,因此,在 99% 的情况下,每个项目都需要扩展此类!使用示例
https://github.com/aherne/lucinda-framework/blob/master/src/Attributes.php
规范
由于此 API 在 Abstract MVC API 规范之上工作,因此它遵循其要求并添加了一些额外的要求
如何检测响应格式
本节遵循父 API 规范,只是路由是根据 $_SERVER["REQUEST_URI"] 的值进行检测的。
如何定位视图解析器
本节完全遵循父 API 规范。
如何检测路由
本节遵循父 API 规范,只是路由是根据 $_SERVER["REQUEST_URI"] 的值进行检测的。以下是一个 XML 示例
<application default_route="index" ...> ... </application> <routes> <route id="index" .../> <route id="users" .../> <route id="user/(id)" .../> </routes>
以上将出现以下情况
如何定位控制器
本节遵循父API 规范,只是定义为 路由 标签中的 controller 属性的类必须扩展 Controller。
参数验证器是如何工作的
为了更好地理解 application XML 标签中的 validators 属性如何与 routes 标签中的 parameter 子标签一起工作,以便根据传入的请求定位要运行的验证器,让我们以这个XML为例
<routes> <route id="users/(uname)" method="GET" ...> <parameter name="uname" class="Lucinda\Project\ParameterValidators\UserName"/> </route> <route id="user/info" method="POST" ...> <parameter name="id" class="Lucinda\Project\ParameterValidators\UserId"/> <parameter name="name" class="Lucinda\Project\ParameterValidators\UserName" mandatory="0"/> </route> ... </routes>
收到对 /users/aherne 的请求时,API将
- 检测到ID为 users/(uname) 的路由和接收到的请求参数(路径参数、GET、POST)
- 检查是否使用GET方法调用路由。如果不是,将抛出 MethodNotAllowedException 异常!
- 实例化 Lucinda\Project\ParameterValidators\UserName 并在“uname”路径参数的值上运行 validate 方法。如果未发送参数或验证失败,将抛出 ValidationFailedException 异常!
收到对 /users/info 的请求时,API将
- 检测到ID为 user/info 的路由和接收到的请求参数(路径参数、GET、POST)
- 检查是否使用POST方法调用路由。如果不是,将抛出 MethodNotAllowedException 异常!
- 实例化 Lucinda\Project\ParameterValidators\UserId 并在请求参数“id”的值上运行 validate。如果未发送参数或验证失败,将抛出 ValidationFailedException 异常!
- 实例化 Lucinda\Project\ParameterValidators\UserName 并在请求参数“name”的值上运行 validate。如果发送了参数且验证失败,将抛出 ValidationFailedException 异常!
所有参数验证器都需要遵守PSR-4自动加载规范并实现 EventListeners\Validators\ParameterValidator 接口!
如何设置Cookies的路径和域名
下表显示了 cookies XML 标签中 path 属性的效果
下表显示了 cookies XML 标签中 domain 属性的效果
如何处理上传的文件
与 $_FILES 超全局变量不同,API保留了由 $_GET 或 $_POST 发送的表单结构,因此
<input type="file" name="asd[fgh]"/>
一旦发布,uploadedFiles 方法将返回
[ "asd"=>["fgh"=>object] ]
其中 object 是一个 Request\UploadedFiles\File。要检索上传的文件,请使用 Request 中的 uploadedFiles 方法!
如何处理请求的URI
API根据以下算法将请求URI(REQUEST_URI参数的值@$_SERVER)分解成相关组件
- 首先通过从DOCUMENT_ROOT中删除SCRIPT_FILENAME来检测 上下文路径。通常,上下文路径为空,因为网站部署到特定的主机名,但在某些情况下,它们直接部署在 localhost 上,因此当REQUEST_URI是 https:///mySite/foo/bar 时,上下文路径将是 mySite
- 它从REQUEST_URI中删除上下文路径和QUERY_STRING,以便检测 请求的页面。如果没有指定特定的页面,如 http://www.example.com,则假定主页,因此请求的页面将为空字符串
- 它根据QUERY_STRING参数记录查询字符串及其数组表示形式,基于@ $_SERVER。当收到非GET请求时,记录查询字符串参数的数组表示形式,而与Request类的parameters方法返回的数组表示形式分开是合理的。
示例
如何定位视图
本节完全遵循父API 规范。由于它取决于视图的解析类型,因此扩展尚未确定!