cevantime / sherpa-core
Sherpa Core
Requires
- php: >=7.2
- doctrine/cache: ~1.4
- php-di/php-di: ^6.0
- psr/http-message: ~1.0
- psr/http-server-handler: ~1.0
- psr/http-server-middleware: ~1.0
- symfony/event-dispatcher: ^4.0
- zendframework/zend-diactoros: ~1.0
Requires (Dev)
- codeception/codeception: ^2.4
- phpunit/phpunit: ~7.0
This package is auto-updated.
Last update: 2024-09-29 05:02:00 UTC
README
一个基本的内核类,用于轻松构建psr兼容的应用程序。代码是故意最简的。要获得更集成的体验,请参阅Sherpa Framework。
安装
Sherpa Core可以通过composer进行安装
composer require cevantime/sherpa
入门指南
Sherpa使用psr-7进行HTTP消息。您可以在索引文件中使用Zend Diactoros实现来构建请求。
// index.php use Zend\Diactoros\ServerRequestFactory; $request = ServerRequestFactory::fromGlobals();
现在,您可以初始化Sherpa内核
use Sherpa\Kernel\Kernel; // ... $app = new Kernel();
现在,您可以添加一些中间件来显示简单的“Hello Sherpa”
use Zend\Diactoros\Response\HtmlResponse; // ... $app->pipe(function(){ return new HtmlResponse("Hello Sherpa !"); });
内核将处理请求的响应
$response = $app->handle($request);
当响应准备好时,需要将其发出!
use Zend\Diactoros\Response\SapiEmitter; // ... (new SapiEmitter())->emit($response);
这就完成了!现在访问您的索引文件。您应该看到“Hello Sherpa!”
中间件
Sherpa Core尽可能符合psr7和psr-15建议。这些建议介绍了使用消息接口和中间件。在内核中管道中间件非常简单
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface; $kernel->pipe(function(ServerRequestInterface $request, RequestHandlerInterface $handler) { // ... });
根据规范,中间件必须返回一个Psr\Http\Message\ResponseInterface
实例。它可以通过以下方式做到:
- 通过调用
$handler->handle($request)
将响应创建委托给下一个中间件,并最终修改响应。 - 生成自己的响应并绕过下一个中间件。
这里有一个(虚构的)示例,检查我们是否正在访问admin uri,并阻止非管理员用户进入!
$kernel->pipe(function(ServerRequestInterface $request, RequestHandlerInterface $handler) { // check if user tries to access an admin page and check if he is admin if(preg_match($request->getUri()->getPath(), '~^/admin~') && ! $request->getAttribute('user')->isAdmin()) { // if not, send an error return (new Response('php://memory')) ->withStatus(403, 'You are not allowed to enter !'; } // otherwise, let the process continue and the next middleware proceed return $handler->handle($request); });
可选地(但值得注意),可以提供一个整数作为第二个参数,以设置中间件的优先级(较高的在前面)。
$kernel->pipe(function(){ return new Response(...); }, 50);
容器和自动装配
Sherpa Core使用PHP DI Container作为依赖容器和依赖注入器。这个包允许您用最少的配置注入项目中的任何类(甚至是vendor)。所有类型提示的参数都可以注入。您只需配置无法通过类型提示猜测的参数。使用类/接口名称作为键定义的类将变为可注入
use function DI\get; use function DI\create; use Psr\Log\LoggerInterface; use Monolog\Logger; use Monolog\Handler\StreamHandler; use Psr\Container\ContainerInterface; //... $builder = $kernel->getContainerBuilder(); $builder->addDefinitions([ // create definition directly... 'log.folder' => 'var/log', // ... or using a callback function... StreamHandler::class => function(ContainerInterface $container) { return new StreamHandler($container->get('log.folder'); }, // ... or using configuration methods that come with php di LoggerInterface::class => create(Logger::class) ->constructor('mylogger') ->method('pushHandler', get(StreamHandler::class)) ]);
现在,一个日志记录器在任何地方都是可注入的,包括类中间件
use App\UserRepository; use Psr\Log\LoggerInterface; use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Server\RequestHandlerInterface as Handler; use Psr\Http\Message\ResponseInterface as Response; class UserMiddleware implements MiddlewareInterface { protected $userRepository; protected $logger; /** * @param UserRepository $userRepository is auto-injected ! * @param LoggerInterface $logger hase been configure to inject an instance of Logger * / public function __construct(UserRepository $userRepository, LoggerInterface $logger) { $this->userRepository = $userRepository; $this->logger = $logger; } public function process(Request $request, Handler $handler): Response { $user = $this->userRepository->findBy(['id' => $_SESSION['user_id'] ?? 0]); if($user) { $request->setAttribute('user', $user); } else { $this->logger->log('info', 'No user found in session'); } return $handler->handle($request); } }
内核将使用di容器将中间件注入到中间件堆栈中。因此,您只需提供它们的类名即可管道中间件。
$kernel->pipe(UserMiddleware::class);
结论
这个内核相当简洁,但它是构建完全psr兼容的出色应用程序的一个很好的起点。Sherpa Framework是使用此内核的一个示例。