ellinaut / ellirpc
Requires
- php: >=8.1
- psr/http-factory: ^1.0
- psr/http-message: ^1.0|^2.0
Requires (Dev)
- symfony/filesystem: ^6.0
- symfony/mime: ^6.0
README
由 Ellinaut 提供
目录
- 简介
- 安装
- 注册定义
- 注册处理器
- 注册事务监听器
- 注册验证器
- 注册错误工厂
- 注册错误翻译器
- 配置文件处理
- 处理请求
简介
安装
您可以通过 composer 安装此库
composer req ellinaut/ellirpc
此库需要实现 PSR-7 (HTTP 消息) 标准的请求和响应对象,为此它使用了 PSR-17 (HTTP 工厂) 标准因此您需要安装任何提供这些对象的实现。
我们推荐使用 nyholm/psr7
,它提供了 PSR-7 和 PSR-17 实现
composer req ellinaut/ellirpc nyholm/psr7
如果您想使用提供的默认文件系统和内容类型猜测器,您还必须安装 symfony 组件 "symfony/filesystem" 和 "symfony/mime"
composer req symfony/filesystem symfony/mime
注册定义
要向定义处理器提供定义,您需要提供 PackageDefinitionLoaderInterface
、ProcedureDefinitionLoaderInterface
和 SchemaDefinitionLoaderInterface
的实现。
这些接口的默认实现是 ArrayDefinitionLoader
,但您也可以提供自己的实现。可以通过 "registerPackage" 方法注册每个包的定义数组。
$definitionLoader = new \Ellinaut\ElliRPC\Definition\Loader\ArrayDefinitionLoader(); $definitionLoader->registerPackage([ 'name' => 'Test', 'description' => 'Test package to demonstrate configuration.', 'procedures' => [], 'schemas' => [], 'errors' => [] ]);
注册处理器
要执行过程,每个过程都需要一个实现 ProcedureProcessorInterface
的过程处理器。
在过程处理器中,可以通过执行上下文来区分正常请求或事务的执行,执行上下文可以是 ExecutionContext::STANDALONE
或 ExecutionContext::TRANSACTION
。
如果您的应用程序只有一个过程处理器,可以直接将其传递给 RPC 处理器。否则,您必须将您的处理器注册到注册表中,并将此注册表传递给处理器。
默认注册表实现是 ProcedureProcessorRegistry
,其中处理器是通过调用 "register" 方法添加的。
$processorRegistry = new \Ellinaut\ElliRPC\Procedure\Processor\ProcedureProcessorRegistry(); $processorRegistry->register( 'Test', // package name 'test', // procedure name new TestProcessor() // procedure processor for test procedure in Test package );
注册事务监听器
在某些情况下,可能需要事务来确保所有过程的结果一起或都不成功执行。这通常与数据存储相关。为了确保所有执行的过程可以一起存储数据,使用事务管理器。
事务管理器指示事务的开始、预期的结束和错误情况下的中断。您的应用程序可以通过事务监听器监听这些更改。
事务监听器是一个实现了 TransactionListenerInterface
的 PHP 类。根据您的实现,您的过程处理器或任何其他类可以实施此接口并将其注册为管理器的监听器。
$transactionManager = new \Ellinaut\ElliRPC\Procedure\Transaction\TransactionManager(); $transactionManager->registerListener( new CustomTransactionListener() );
注册验证器
过程验证器的任务是验证过程调用中传递的数据结构,并在必要时验证传递的值,以便在实际处理之前检测错误,从而不使用无效数据启动过程的执行。
您的自定义验证器必须实现 ProcedureValidatorInterface
并添加到 ProcedureValidatorChain
的一个实例中,该实例可以传递给具体的 HTTP 处理器。
在验证错误时,应抛出 ProcedureValidationException
。
$procedureValidator = new \Ellinaut\ElliRPC\Procedure\Validator\ProcedureValidatorChain(); $procedureValidator->register( new CustomValidator() ); // validator for specific context (standalone/no transaction in this example) $procedureValidator->register( new CustomValidator(), \Ellinaut\ElliRPC\Procedure\Validator\ValidatorContext::STANDALONE );
注册错误工厂
错误工厂的任务是从 PHP 可抛出对象创建错误对象。
因此,您需要实现实现 ErrorFactoryInterface
的工厂类。
您的工厂可能创建Error
、TranslateableError
或TranslateableHttpError
的实例,或者它们创建必须扩展Error
并可能实现HttpErrorInterface
的自定义错误实例。
$errorFactory = new \Ellinaut\ElliRPC\Error\Factory\ErrorFactoryChain(); $errorFactory->register( new CustomErrorFactory() );
注册错误翻译器
错误翻译器的任务是翻译错误消息的描述文本(通常是英文)成您的应用程序使用的其他语言,以便向用户显示错误。
因此,您需要实现必须实现ErrorTranslatorInterface
的翻译器。
所有翻译器都应添加到ErrorTranslatorChain
的一个实例中,然后可以将其传递给具体的HTTP处理器。
$errorTranslator = new \Ellinaut\ElliRPC\Error\Translator\ErrorTranslatorChain(); $errorTranslator->register( new CustomErrorTranslator() );
配置文件处理
@todo 描述
$contentTypeGuesser = new \Ellinaut\ElliRPC\File\Bridge\SymfonyContentTypeGuesser( new \Symfony\Component\Mime\FileinfoMimeTypeGuesser() ); // with symfony filesystem and without custom fiel logic use: $fallbackFilesystem = new \Ellinaut\ElliRPC\File\Bridge\SymfonyFilesystem( new \Symfony\Component\Filesystem\Filesystem() ); // to disable file uploads use `\Ellinaut\ElliRPC\File\UnsupportedFilesystem` instead! $filesystem = new \Ellinaut\ElliRPC\File\FilesystemChain($fallbackFilesystem); // use "filesystem->add" to add custom filesystems which have to implement `\Ellinaut\ElliRPC\File\ChainableFilesystem` $fallbackFileLocator = new \Ellinaut\ElliRPC\File\LocalPathLocator( __DIR__.'/../files' // local file storage path ); // to use the same values for public and storage paths and disable resolving use `\Ellinaut\ElliRPC\File\UnresolvedFileLocator` instead! $fileLocator = new \Ellinaut\ElliRPC\File\FileLocatorChain($fallbackFileLocator); // use "$fileLocator->add" to add custom file locators which have to implement `\Ellinaut\ElliRPC\File\ChainableFileLocator`
处理请求
库的主要任务是处理HTTP请求并生成HTTP响应。这些任务由处理器执行。
有三种不同的处理器。一个用于文档目的(DefinitionHandler
),一个用于执行程序(RPCHandler
),一个用于处理文件(FileHandler
)。
根据您应用程序的需求,您可以使用所有这些处理器,或者用自定义逻辑替换一个或多个处理器,这些逻辑可能更适合您的应用程序或使用的框架。
对于API规范定义的每个端点,都有一个PHP方法。您的应用程序必须决定要调用哪个处理器和哪个方法,这样就可以使用自己的路由而无需任何依赖。
以下示例显示了一个无需任何框架依赖的完整实现。所有未在此片段中直接定义的给定参数已在文档的前例中定义
// initialize the factory (in this case with nyholm/psr7 installed) $psr17Factory = new \Nyholm\Psr7\Factory\Psr17Factory(); // create a request object which can be handled by the library $nyholmCreator = new \Nyholm\Psr7Server\ServerRequestCreator( $psr17Factory, // ServerRequestFactory $psr17Factory, // UriFactory $psr17Factory, // UploadedFileFactory $psr17Factory // StreamFactory ); $request = $nyholmCreator->fromGlobals(); if(substr($request->getUri()->getPath(), 0, 12) === '/definitions' && $request->getMethod() === 'GET'){ // creating the definition handler $definitionHandler = new \Ellinaut\ElliRPC\DefinitionHandler( $psr17Factory, $psr17Factory, $errorFactory, $errorTranslator, $definitionLoader, 'Example Application', // application name 'Example application contains a test package with test procedure' // description ); if($request->getUri()->getPath() === ' /definitions'){ $response = $definitionHandler->executeGetDocumentation($request); } if(substr($request->getUri()->getPath(), 0, 13) === '/definitions/'){ $response = $definitionHandler->executeGetPackageDefinition($request); } } if(substr($request->getUri()->getPath(), 0, 12) === '/procedures/' && $request->getMethod() === 'POST'){ // creating the rpc handler $rpcHandler= new \Ellinaut\ElliRPC\RPCHandler( $psr17Factory, $psr17Factory, $errorFactory, $errorTranslator, $procedureValidator, $procedureProcessorRegistry, $transactionManager ); if($request->getUri()->getPath() === ' /procedures/execute'){ $response = $rpcHandler->executeExecuteProcedure($request); } if($request->getUri()->getPath() === ' /procedures/bulk'){ $response = $rpcHandler->executeExecuteBulk($request); } if($request->getUri()->getPath() === ' /procedures/transaction'){ $response = $rpcHandler->executeExecuteTransaction($request); } } if(substr($request->getUri()->getPath(), 0, 6) === '/files'){ // creating the file handler $fileHandler = new \Ellinaut\ElliRPC\FileHandler( $psr17Factory, $psr17Factory, $errorFactory, $errorTranslator, $fileLocator, $filesystem, $contentTypeGuesser ); switch ($request->getMethod()){ case 'GET': $response = $fileHandler->executeGetFile($request); break; case 'POST': case 'PUT': $response = $fileHandler->executeUploadFile($request); break; case 'DELETE': $response = $fileHandler->executeDeleteFile($request); break; } } // your application has to send $response to client...
Ellinaut由NXI GmbH & Co. KG和BVH Bootsvermietung Hamburg GmbH提供支持。