headio / phalcon-bootstrap
适用于Phalcon项目的灵活应用程序引导。
Requires
- php: >=8.0
- ext-mbstring: *
- ext-phalcon: >= 5.0.0
Requires (Dev)
- codeception/codeception: ^4.1.0
- codeception/module-asserts: ^1.1
- codeception/module-phalcon5: ^1.0.1
- codeception/specify: ^1.4
- codeception/verify: ^1.5
- friendsofphp/php-cs-fixer: *
- mockery/mockery: ^1.3
- phalcon/ide-stubs: ^5.0.0
- symfony/console: ^5.0.0
- vimeo/psalm: ^4.11
README
适用于基于Phalcon的项目灵活应用程序引导
描述
此库提供灵活的应用程序引导,封装了模块注册(或微应用的处理器注册),事件管理和中间件逻辑分配,适用于MVC、微和基于CLI的应用程序。一个简单的工厂实例化依赖注入容器,封装了配置设置中定义的服务依赖定义的注册。
依赖关系
- PHP >=8.0
- Phalcon >=5.0.0
有关更多详细信息,请参阅composer.json
安装
Composer
打开终端窗口并运行
composer require headio/phalcon-bootstrap
用法
微应用(API、原型或微服务)
首先在你的Phalcon项目中创建一个配置定义文件。此文件应包括配置设置、服务和中件定义以及你的处理器的路径。
为了开始,假设以下项目结构
├── public │ ├── index.php ├── src │ ├── Config │ │ │── Config.php │ │ │── Handlers.php │ │── Controller │ │── Domain │ │── Middleware │ │── Service │ │── Var │ │ │── Log ├── tests ├── vendor ├── Boot.php ├── codeception.yml ├── composer.json ├── .gitignore ├── README.md └── .travis.yml
你的PSR-4自动加载声明如下
{ "autoload": { "psr-4": { "Foo\\": "src/" } } }
在Config目录下创建一个名为Config.php的配置文件,并粘贴以下定义
<?php namespace Foo\Config; use Foo\Middleware\NotFoundMiddleware; return [ 'applicationPath' => dirname(__DIR__) . DIRECTORY_SEPARATOR, 'debug' => true, 'locale' => 'en_GB', 'logPath' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Var' . DIRECTORY_SEPARATOR . 'Log' . DIRECTORY_SEPARATOR, 'handlerPath' => __DIR__ . DIRECTORY_SEPARATOR . 'Handlers.php', 'middleware' => [ NotFoundMiddleware::class => 'before' ], 'services' => [ 'Foo\Service\EventManager', 'Foo\Service\Logger', ], 'timezone' => 'Europe\London' ];
handlerPath声明必须包括你的处理器;最佳策略是利用Phalcon集合。此文件的正文可能如下所示
<?php namespace Foo\Config; use Foo\Controller\Index; use Phalcon\Mvc\Micro\Collection; $handler = new Collection(); $handler->setHandler(Index::class, true); $handler->setPrefix('/'); $handler->get('/', 'indexAction', 'apiIndex'); $app->mount($handler);
现在,在public目录下创建一个索引文件,并粘贴以下内容
<?php declare(strict_types=1); chdir(dirname(__DIR__)); require 'Boot.php';
最后,将以下引导代码粘贴到Boot.php文件中
<?php declare(strict_types=1); use Headio\Phalcon\Bootstrap\Bootstrap; use Headio\Phalcon\Bootstrap\Di\Factory as DiFactory; use Phalcon\Config\Config; require_once __DIR__ . '/vendor/autoload.php'; // Micro example (function () { $config = new Config( require __DIR__ . '/src/Config/Config.php' ); $di = (new DiFactory($config))->createDefaultMvc(); // Environment if (extension_loaded('mbstring')) { mb_internal_encoding('UTF-8'); mb_substitute_character('none'); } set_error_handler( function ($severity, $message, $file, $line) { if (!(error_reporting() & $severity)) { // Unmasked error context return; } throw new \ErrorException($message, 0, $severity, $file, $line); } ); set_exception_handler( function (Throwable $e) use ($di) { $di->get('logger')->error($e->getMessage(), ['exception' => $e]); // Verbose exception handling for development if ($di->get('config')->debug) { } exit(1); } ); // Run the application return Bootstrap::handle($di)->run($_SERVER['REQUEST_URI'], Bootstrap::Micro); })();
MVC应用程序
在你的Phalcon项目中创建一个配置定义文件。此文件应包括你的配置设置和服务与中件定义。
假设以下MVC项目结构
├── public │ ├── index.php ├── src │ ├── Config │ │ │── Config.php │ │── Controller │ │── Domain │ │── Middleware │ │── Module │ │ │── Admin │ │ │ │── Controller │ │ │ │── Form │ │ │ │── Task │ │ │ │── View │ │ │ │── Module.php │ │── Service │ │── Var │ │ │── Log ├── tests ├── vendor ├── Boot.php ├── codeception.yml ├── composer.json ├── .gitignore ├── README.md └── .travis.yml
你的PSR-4自动加载声明如下
{ "autoload": { "psr-4": { "Foo\\": "src/" } } }
在Config目录下创建一个名为Config.php的配置文件,并粘贴以下定义
<?php namespace Foo\Config; return [ 'annotations' => [ 'adapter' => 'Apcu', 'options' => [ 'lifetime' => 3600 * 24 * 30, 'prefix' => 'annotations', ], ], 'applicationPath' => dirname(__DIR__) . DIRECTORY_SEPARATOR, 'baseUri' => '/', 'debug' => true, 'dispatcher' => [ 'defaultAction' => 'index', 'defaultController' => 'Admin', 'defaultControllerNamespace' => 'Foo\\Module\\Admin\\Controller', 'defaultModule' => 'admin' ], 'locale' => 'en_GB', 'logPath' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Var' . DIRECTORY_SEPARATOR . 'Log' . DIRECTORY_SEPARATOR, 'modules' => [ 'admin' => [ 'className' => 'Foo\\Module\\Admin\\Module', 'path' => dirname(__DIR__) . '/Module/Admin/Module.php' ], ], 'middleware' => [ 'Foo\\Middleware\\Bar' ], 'routes' => [ 'admin' => [ 'Foo\Module\Admin\Controller\Admin' => '/admin', ], ], 'services' => [ 'Foo\Service\EventManager', 'Foo\Service\Logger', 'Foo\Service\Annotation', 'Foo\Service\Router', 'Foo\Service\View' ], 'timezone' => 'Europe\London', 'useI18n' => true, 'view' => [ 'defaultPath' => dirname(__DIR__) . '/Module/Admin/View/', 'compiledPath' => dirname(__DIR__) . '/Cache/Volt/', 'compiledSeparator' => '_', ] ];
现在,在public目录下创建一个索引文件,并粘贴以下内容
<?php declare(strict_types=1); chdir(dirname(__DIR__)); require 'Boot.php';
最后,将以下引导代码粘贴到Boot.php文件中
<?php declare(strict_types=1); use Headio\Phalcon\Bootstrap\Bootstrap; use Headio\Phalcon\Bootstrap\Di\Factory as DiFactory; use Phalcon\Config\Config; require_once __DIR__ . '/vendor/autoload.php'; // Mvc example (function () { $config = new Config( require __DIR__ . '/src/Config/Config.php' ); $di = (new DiFactory($config))->createDefaultMvc(); // Environment if (extension_loaded('mbstring')) { mb_internal_encoding('UTF-8'); mb_substitute_character('none'); } set_error_handler( function ($severity, $message, $file, $line) { if (!(error_reporting() & $severity)) { // Unmasked error context return; } throw new \ErrorException($message, 0, $severity, $file, $line); } ); set_exception_handler( function (Throwable $e) use ($di) { $di->get('logger')->error($e->getMessage(), ['exception' => $e]); // Verbose exception handling for development if ($di->get('config')->debug) { } exit(1); } ); // Run the application return Bootstrap::handle($di)->run($_SERVER['REQUEST_URI']); })();
控制台应用程序
在你的Phalcon项目中创建一个配置定义文件。此文件应包括你的配置设置和服务与中件定义。
假设以下项目结构
├── src │ ├── Config │ │ │── Config.php │ │── Domain │ │── Middleware │ │── Service │ │── Task │ │── Var │ │ │── Log ├── tests ├── vendor ├── Cli.php ├── codeception.yml ├── composer.json ├── .gitignore ├── README.md └── .travis.yml
你的PSR-4自动加载声明如下
{ "autoload": { "psr-4": { "Foo\\": "src/" } } }
在Config目录下创建一个名为Config.php的配置文件,并粘贴以下定义
<?php namespace Foo\Config; return [ 'applicationPath' => dirname(__DIR__) . DIRECTORY_SEPARATOR, 'locale' => 'en_GB', 'logPath' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Var' . DIRECTORY_SEPARATOR . 'Log' . DIRECTORY_SEPARATOR, 'debug' => true, 'dispatcher' => [ 'defaultTaskNamespace' => 'Foo\\Task', ], 'middleware' => [ ], 'services' => [ 'Foo\Service\EventManager', 'Foo\Service\Logger', 'Foo\Service\ConsoleOutput', ], 'timezone' => 'Europe\London' ];
最后,将以下引导代码粘贴到Cli.php文件中
<?php declare(strict_types=1); use Headio\Phalcon\Bootstrap\Cli\Bootstrap; use Headio\Phalcon\Bootstrap\Di\Factory as DiFactory; use Phalcon\Config\Config; require_once __DIR__ . '/vendor/autoload.php'; // Cli example (function () { $config = new Config( require __DIR__ . '/src/Config/Config.php' ); $di = (new DiFactory($config))->createDefaultCli(); // Environment set_error_handler( function ($severity, $message, $file, $line) { if (!(error_reporting() & $severity)) { // Unmasked error context return; } throw new \ErrorException($message, 0, $severity, $file, $line); } ); set_exception_handler( function (Throwable $e) use ($di) { $di->get('logger')->error($e->getMessage(), ['exception' => $e]); $output = $di->get('consoleOutput'); $output->writeln('<error>' . $e->getMessage() . '</error>'); // Verbose exception handling for development if ($di->get('config')->debug) { $output->writeln(sprintf( '<error>Exception thrown in: %s at line %d.</error>', $e->getFile(), $e->getLine()) ); } exit(1); } ); // Run the application return Bootstrap::handle($di)->run($_SERVER); })();
DI容器工厂
从上面的示例中,你会注意到我们实例化了Phalcon的默认MVC或CLI容器服务。
$config = new Config( require __DIR__ . '/src/Config/Config.php' ); // Micro/Mvc $di = (new DiFactory($config))->createDefaultMvc(); // Cli $di = (new DiFactory($config))->createDefaultCli();
当然,你可以通过在配置文件中定义服务定义来覆盖工厂默认的服务
<?php namespace Foo\Config return [ 'services' => [ 'Foo\Service\Router' ] ]
然后创建相应的服务提供者并修改其行为
<?php /** * This source file is subject to the MIT License. * * For the full copyright and license information, please view * the LICENSE file that was distributed with this package. */ declare(strict_types=1); namespace Foo\Service; use Foo\Exception\OutOfRangeException; use Phalcon\Config\Config; use Phalcon\Di\ServiceProviderInterface; use Phalcon\Di\DiInterface; use Phalcon\Cli\Router as CliService; use Phalcon\Mvc\Router as MvcRouter; use Phalcon\Mvc\Router\Annotations as MvcService; class Router implements ServiceProviderInterface { /** * {@inheritDoc} */ public function register(DiInterface $di) : void { $di->setShared( 'router', function () use ($di) { $config = $di->get('config'); if ($config->get('cli')) { $service = new CliService(); $service->setDefaultModule($config->dispatcher->defaultTaskModule); return $service; } if (!$config->has('modules')) { throw new OutOfRangeException('Undefined modules'); } if (!$config->has('routes')) { throw new OutOfRangeException('Undefined routes'); } $service = new MvcService(false); $service->removeExtraSlashes(true); $service->setDefaultNamespace($config->dispatcher->defaultControllerNamespace); $service->setDefaultModule($config->dispatcher->defaultModule); $service->setDefaultController($config->dispatcher->defaultController); $service->setDefaultAction($config->dispatcher->defaultAction); foreach ($config->get('modules')->toArray() ?? [] as $module => $settings) { if (!$config->routes->get($module, false)) { continue; } foreach ($config->get('routes')->{$module}->toArray() ?? [] as $key => $val) { $service->addModuleResource($module, $key, $val); } } return $service; } ); } }
为了完全控制服务依赖的注册,或者更普遍地,容器中可用的服务,你有两个选项:首先,你可以使用Phalcon的基DI容器,它是一个空容器;或者你可以通过实现Phalcon的Phalcon\Di\DiInterface来创建自己的DI容器。以下是一个示例
use Phalcon\Di; use Foo\Bar\MyDi; $config = new Config( require __DIR__ . '/src/Config/Config.php' ); // Empty DI container $di = (new DiFactory($config))->create(new Di); // Custom DI container $di = (new DiFactory($config))->create(new MyDi);
DI工厂的create方法期望一个实例为Phalcon\Di\DiInterface。
应用程序工厂
引导工厂将自动实例化一个Phalcon应用程序并返回响应。如果你想自己引导应用程序,可以直接使用应用程序工厂。
<?php /** * This source file is subject to the MIT License. * * For the full copyright and license information, please view * the LICENSE file that was distributed with this package. */ declare(strict_types=1); use Headio\Phalcon\Bootstrap\Application\Factory as AppFactory; use Headio\Phalcon\Bootstrap\Di\Factory as DiFactory; use Phalcon\Config\Config; chdir(dirname(__DIR__)); require_once 'vendor/autoload.php'; $config = new Config( require 'src/Config/Config.php' ); try { $di = (new DiFactory($config))->createDefaultMvc(); /** @var Phalcon\Mvc\Application */ $app = (new AppFactory($di))->createForMvc(); // Do some stuff /** @var Phalcon\Mvc\ResponseInterface|bool */ $response = $app->handle($_SERVER['REQUEST_URI']); if ($response instanceof \Phalcon\Mvc\ResponseInterface) { return $response->send(); } return $response; } catch(\Throwable $e) { echo $e->getMessage(); }
测试
要查看测试,请运行
php vendor/bin/codecept run -f --coverage --coverage-text
许可证
Phalcon引导是开源的,并许可在MIT许可证下。