iuravic / duktig-skeleton-web-app
基于Duktig MVC微型Web框架的PHP 7.1骨架Web应用程序
Requires
- php: ^7.1
- http-interop/http-factory: dev-master
- http-interop/http-middleware: ^0.4.1
- iuravic/duktig-core: dev-master
- iuravic/duktig-http-factory-guzzle-adapter: dev-master
- iuravic/duktig-middleman-adapter: dev-master
- iuravic/duktig-symfony-event-dispatcher-adapter: dev-master
- iuravic/duktig-symfony-router-adapter: dev-master
- iuravic/duktig-twig-adapter: dev-master
- monolog/monolog: ^1.22
- psr/http-message: ^1.0
- psr/log: ^1.0
Requires (Dev)
- mockery/mockery: ^1.0
- phpunit/phpunit: ^6.1
This package is not auto-updated.
Last update: 2024-09-29 02:58:31 UTC
README
duktig-skeleton-web-app
这是一个使用Duktig微型MVC Web框架和基于PHP 7.1编写的库 iuravic/duktig-core
制作的骨架Web应用程序。
目录
关于
duktig-skeleton-web-app
是使用Duktig框架开发自己应用的起点。它基于 duktig-core
包,并提供所有必要的依赖。骨架应用程序还包含Duktig框架主要功能的示例。
duktig-core
包
建议您也查看 duktig-core
文档,它描述了Duktig框架的目的和功能,并解释了其基本元素和功能。
包设计
Duktig的核心服务大多数都与 duktig-core
包完全解耦。 duktig-core
通过定义其接口来描述它们,并且每个接口都作为独立包以适配器形式实现,针对现成的开源项目。这种方法提供了高度的灵活性、可重用性,并且通常被认为是良好的包设计。
依赖项
duktig-skeleton-web-app
通过使用流行和经过测试的开源包来组合完整的Duktig Web应用程序框架。适配器包用于简单地适配外部包的API以符合核心接口,从而使它们可以通过 duktig-core
使用。
以下项目和使用到的包用于为Duktig框架提供完整的功能
核心服务
services.php
文件显示了这些包是如何实现和配置以提供核心功能的。
安装
以下命令通过Composer创建新项目
$ composer create-project -s dev iuravic/duktig-skeleton-web-app {$PROJECT_PATH}
Duktig包的仓库目前尚未标记为相应版本,对此我深表歉意,但此命令仍将正确解析和获取所有依赖项,并创建您的项目。
使用和应用流程
让我们查看一个完整的请求到响应的生命周期,以及其中的一些关键元素,按照命令链中的顺序。
index.php
典型的index.php文件可能如下所示
<?php require __DIR__.'/../vendor/autoload.php'; $app = (new \Duktig\Core\AppFactory)->make( __DIR__.'/../src/Config/config.php', \Duktig\Core\App::class ); $app->run();
我们发现该应用程序是由 Duktig\Core\AppFactory
创建的,它通过提供自定义配置文件和应用程序类来实现。
AppFactory
Duktig\Core\AppFactory
通过以下方式创建应用程序实例:
- 将用户配置与核心配置合并,
- 通过使用
Duktig\Core\DI\ContainerFactory
实例化和配置 DI 容器, - 解析应用程序及其依赖项。
请求处理和 App
类
Duktig\Core\App
是框架的主要类,其 run()
方法是请求的入口点。框架通过完整的应用程序堆栈“运行”请求。它在其核心使用 HTTP 中间件,并组成一个由以下组成的中间件堆栈:
- 应用程序中间件,
- 路由中间件,
- 控制器响应中间件。
Duktig 中存在两种中间件:应用程序中间件——它用于每个请求,以及特定于路由的中间件——它可以被分配到特定的路由。
在中间件堆栈的末尾是 ControllerResponder 中间件。它负责解析控制器/路由处理程序,并将响应对象从它返回到堆栈。
处理完响应后,框架将其发送到浏览器并终止应用程序业务。
示例项目功能
在此包中,一些功能被实现为简单的示例。这些可以作为“如何做”,它们可以被修改,或者简单地从您的项目中删除。基本上,它们应该有助于快速了解如何使用 Duktig 框架构建应用程序。
以下是一个功能列表的快速列表。
核心服务
'Config/services.php'
定义并注册了所有 核心服务,通过使用外部包来实现。
路由
参见路由配置 Config/routes.php
。
控制器
参见控制器目录 Controller/
。
DuktigSkeleton\Controller\IndexController
特点
- 扩展
BaseController
类 - 构造函数参数解析
- 使用外部服务
- 响应定义
- 模板渲染
- 重定向
- URI 路径参数
- 查询参数
中间件
以下中间件实现了它们对应的功能
- 应用程序范围中间件
ExampleAppMiddleware
- 在配置文件
'Config/middlewares.php'
中注册 - 修改响应体
- 在配置文件
- 路由特定中间件
ExampleGetIPRouteMiddleware
- 分配给路由
'example-route-w-controller'
- 通过依赖注入使用外部服务
- 通过向其添加属性来修改应用程序请求
- 分配给路由
事件
事件 EventIPInRange
是一个简单的事件对象,展示了如何
- 扩展
EventAbstract
类 - 使用外部服务
- 为其监听器提供上下文数据
EventIPInRange
有一个监听器通过配置文件 Config/events.php
注册,名为 ListenerReportIP
,演示了如何
- 实现
ListenerInterface
- 使用外部服务
- 处理事件对象并执行任务
服务
ExampleIPService
是一个简单的服务,实现了一些基本功能
ExampleIPService
本身是通过容器自动配置功能解析的(注意,它没有在Config/services.php
中显式注册,因为Auryn实现了这个功能)- 依赖注入
- 访问配置服务和配置参数
配置
在骨架项目中实现了以下配置设置
- 基础配置文件
'Config/config.php'
及其设置 - 在
'Config/params.php'
中设置自定义配置参数 - 在
'Config/middlewares.php'
中注册应用程序中间件 - 在
'Config/events.php'
中注册事件和监听器
配置
在进行最终步骤并查看配置之前,请花点时间也看看 duktig-core
的文档。
配置文件
Duktig 的配置包含在 Config
目录中简单的 .php
配置文件 中。您的应用程序的 Config
文件夹 应该与 duktig-core
的配置内容相匹配。核心和您的应用程序的配置在运行时完全合并,并且您应用程序中定义的所有配置值都会覆盖核心的配置值。唯一的例外是 services.php
文件,其内容不会被覆盖,而是与您的应用程序的 services.php
合并。要跳过核心的服务配置,可以使用配置参数 'skipCoreServices'
。
配置服务
配置服务用于访问配置参数和值,即 config.php
文件的内容。它实现了由 Duktig\Core\Config\ConfigInterface
提供的简单 API。
它可以通过依赖注入访问,其中它被类型提示为 ConfigInterface
,这将解析为其位置上的 Duktig\Core\Config\Config
服务。
配置服务是一个共享服务,这意味着其实例化不会返回一个空实例,而是一个已配置的值对象。
实现duktig-core的要求
duktig-core
包有一些 要求,必须实现并提供以创建一个完整的功能应用程序环境。这些要求需要实现,并且需要与容器 注册。 duktig-skeleton-web-app
包已经实现了所有这些要求;它们是分别打包的(见章节 依赖关系),并且已经作为项目的 要求 解决。
注册服务
服务在您的应用程序目录中的 Config/services.php
文件中注册。该文件必须返回一个闭包,它将容器作为参数,并在配置后返回它
<?php return function($container) { // ... return $container; };
中间件
Duktig 使用“单遍”兼容 PSR-15 中间件及其调度系统。框架内部存在两种不同的中间件类型。
应用程序中间件
应用程序中间件是每次请求都会运行的中间件。它是全局中间件,在您的应用程序目录中的 Config/middlewares.php
配置文件中定义。以下示例显示了如何分配两个应用程序中间件
<?php return [ \MyProject\Middleware\ExampleAppMiddleware1::class, \MyProject\Middleware\ExampleAppMiddleware2::class, ];
路由中间件
路由中间件分配给特定的路由,并且只有在解析该路由时才会运行。路由中间件通过使用应用程序的 Config/routes.php
文件中的 'middlewares'
路由配置参数来定义。以下简短摘录显示了如何将一个特定路由的中间件分配给 'example-route'
路由
<?php return [ 'example-route' => [ // ... 'middlewares' => [ \MyProject\Middleware\ExampleRouteMiddleware::class, ], ], ];
事件
事件和监听器可以通过配置或编程方式注册。尽管两种机制都可用,但通常建议使用配置来定义事件及其监听器,而不是编程方法,因为配置和代码的分离通常会导致代码的更好分解。但是,这种编程实践应根据具体情况评估。
通过配置文件注册
要注册事件及其监听器,请使用应用程序目录中的 Config/events.php
文件。以下示例显示了如何将两个事件及其各自的监听器进行注册
<?php return [ \MyProject\Event\EventIPInRange::class => [ \MyProject\Event\ListenerReportIP::class, ], 'custom-event-name' => [ function($event) { // ... $event->getName(); }, ], ];
第一个事件作为一个独立的类存在,并使用其完全限定类名作为事件名称。其监听器 ListenerReportIP
也作为一个独立的类定义。所有此类具有自己类的独立事件都必须扩展 Duktig\Core\Event\EventAbstract
类。所有此类监听器都必须实现 Duktig\Core\Event\ListenerInterface
。事件和监听器都由容器解决,并注入其构造函数依赖项。
第二个事件通过自定义名称定义,并分配一个闭包类型的监听器。闭包类型的监听器可以分配给任何事件,无论是独立的类还是自定义名称的事件。此监听器只能接受一个参数,即事件,并且不由容器解决。
如果事件仅由其唯一的名称确定,并且没有为其监听器提供特定的上下文信息,则它可以作为特殊的 Duktig\Core\Event\EventSimple
类分发和实例化。该 EventSimple
类会根据其唯一的名称动态创建事件。
程序化配置
要程序化地附加监听器,我们使用由 Duktig\Core\Event\Dispatcher\EventDispatcherInterface
定义的事件调度器 API。以下示例演示了注册与之前示例中相同的事件和监听器,其中使用了配置文件
$eventDispatcher->addListener( \MyProject\Event\EventIPInRange::class, \MyProject\Event\ListenerReportIP::class ); $eventDispatcher->addListener( 'custom-event-name', function($event) { // ... } );
可以以相同的方式向 核心事件 添加自定义监听器,因此可以访问框架的内部检查点。
路由
路由在 Config/route.php
文件中定义。由于 Duktig 的 路由模型 受到 Symfony 路由模型的影响很大,因此其元素与之非常相似。
以下是一个路由示例,它接受一个名为 myParam
的 URI 路径参数。该参数作为参数传递给 IndexController::exampleAction
。在以下示例中,路由被分配了一个 ExampleRouteMiddleware
。
<?php return [ 'example-route-w-controller' => [ 'path' => '/example/{myParam}', 'params_requirements' => ['myParam' => '.*'], 'handler' => \MyProject\Controller\IndexController::class, 'handler_method' => 'exampleAction', 'methods' => ['GET'], 'middlewares' => [\MyProject\Middleware\ExampleRouteMiddleware::class], ], ];
让我们看看另一个示例,其中一个路由在末尾有一个可选的后缀斜杠,并使用闭包类型处理程序。这种路由处理程序也会由容器解决,其参数将得到解决并注入。
<?php return [ 'example-route-with-callable-handler' => [ 'path' => '/example-callable-handler{trailingSlash}', 'params_requirements' => ['trailingSlash' => '/?'], 'handler' => function (\Interop\Http\Factory\ResponseFactoryInterface $responseFactory) { $response = $responseFactory->createResponse(); $response->getBody()->write('Response set by a callable route handler'); return $response; }, 'handler_method' => null, 'methods' => ['GET'], ] ];
完整的路由配置参数列表可以在 ´duktig-core´ 的 Config/routes.php
文件中找到。
测试
此软件包使用 PHPUnit 和 Mockery 实现了高代码覆盖率。要在命令行中运行其测试,请将软件包作为具有完整开发需求的新项目安装,然后在项目目录中运行命令
$ vendor/bin/phpunit -c phpunit.xml.dist
这将还在项目目录中的 coverage
目录中生成覆盖率报告。
这些测试涵盖了项目的 功能元素,而所有其他在项目中使用的包都分别进行了完全的单元测试。