cevantime/

sherpa-core

0.0.1 2018-10-30 22:09 UTC

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是使用此内核的一个示例。