PHP微服务框架

大家好,我叫亚历克斯 我想向您介绍我的用于创建微服务的PHP框架。 它源于我三年前的实验,后来又发展成为一个宠物项目,后来在此框架中创建了多个生产项目。

当我开始做时,我决定做出以下决定:

  • 可以轻松地集成到现有项目中;
  • 您可以至少快速创建一些有用的东西;
  • 最简洁,最富表现力的设计;
  • 明智地使用了现代PHP的功能。

那你从哪里开始呢? 当然从源头上! 您可以在github上观看它们

好吧,为了避免冗长的争论,让我们从一个可行的例子开始。
首先,我们需要.htaccess,在其中我们将配置一些规则:

# use mod_rewrite for pretty URL support RewriteEngine on RewriteRule ^([a-z0-9A-Z_\/\.\-\@%\ :,]+)/?(.*)$ index.php?r=$1&%{QUERY_STRING} [L] RewriteRule ^/?(.*)$ index.php?r=index&%{QUERY_STRING} [L] 

然后,您可以创建您的第一个服务。 在其中,我们将创建一个端点,该端点将处理GET方法并返回一条消息,说明一切正常。 一种健康检查。
首先,我们需要连接我们的框架:

 require_once ('vendor/service/service.php'); 

然后,我们为微服务创建一个类:

 class TodoService extends ServiceBase implements ServiceBaseLogicInterface { /* class body */ } 

这里我们有:

  • ServiceBase是具有最基本,最实用的功能的基本服务类别;
  • ServiceBaseLogicInterface是任何要提供端点处理程序的类都需要实现的接口。 虽然此接口对您的班级没有任何特殊要求。 只是为了进行更严格的输入。

然后我们得到第一个端点处理程序:

 public function action_ping() { return ('I am alive!'); } 

然后,我们启动第一个微服务:

 Service::start('TodoService'); 

放在一起,我们得到:

 /** * Service class */ class TodoService extends ServiceBase implements ServiceBaseLogicInterface { /** * First endpoint */ public function action_ping() { return ('I am alive!'); } } Service::start('TodoService'); 

可能会出现一个合理的问题-该功能在哪个URL可用? 事实是,通过定义一个带有action_ <name-part>前缀的方法,就可以向服务明确表明它是URL处理程序<name-part>,即 在我们的情况下,它将类似于localhost / ping
方法名称中的下划线变为-。 即 action_hello_world方法将在localhost / hello-world中可用

我们继续前进。

就像GUI应用程序一样,最好在微服务中使用MVC(或将可视化组件和逻辑分开的其他模式)。 可以粉碎的东西最好粉碎。

即 在我们的例子中,让服务类继续执行功利函数以初始化服务并启动所需的处理程序,并将逻辑放在单独的类中。 为此,我们将代码修改如下:

 class TodoLogic extends ServiceBaseLogic { /** * First endpoint */ public function action_ping() { return ('I am alive!'); } } class TodoService extends ServiceBase { } Service::start('TodoService', 'TodoLogic'); 

然后我们得到了一个逻辑类:

 class TodoLogic extends ServiceBaseLogic 

继承自基类ServiceBaseLogic(它具有最少的功能,因此我们将在后面详细研究)。

TodoService类已停止实现ServiceBaseLogicInterface接口(实际上,它并没有消失,只是现在ServiceBaseLogic类实现了该接口)。

删除逻辑后,TodoService类原来是空的,可以安全地将其切出,从而进一步减少了代码:

 class TodoLogic extends ServiceBaseLogic { /** * First endpoint */ public function action_ping() { return ('I am alive!'); } } Service::start('ServiceBase', 'TodoLogic'); 

在这里,ServiceBase类负责启动服务,而不是我们的服务。

我们开车走得更远。

在使用我的框架的过程中,在某个时刻,具有巨大逻辑的类开始出现。 一方面引起我的美感,另一方面,Sonar感到愤慨,其三,将方法分为阅读方法和写作方法的概念(参见CQRS)尚不清楚如何实现。

因此,在某个时刻,可以根据一个或另一个属性根据不同的逻辑类别对端点处理程序进行分组,并且如有必要,可以在同一服务中运行它们,或者将它们轻松地分配到不同的服务中。

即 您可以在一项服务中执行所有CRUD逻辑。 它可以分为两种服务:

  • 一种提供阅读方法;
  • 另一个提供数据修改方法。

现在让我们在示例中添加一个实体创建方法和一个实体列表检索方法:

 class TodoSystemLogic extends ServiceBaseLogic { public function action_ping() { return ('I am alive!'); } } /** * Read logic implementation */ class TodoReadLogic extends ServiceBaseLogic { public function action_list() { return ('List!'); } } /** * Write logic implementation */ class TodoWriteLogic extends ServiceBaseLogic { public function action_create() { return ('Done!'); } } Service::start('ServiceBase', [ 'TodoSystemLogic', 'TodoReadLogic', 'TodoWriteLogic' ]); 

我们将仅涉及更改:

  • 出现了类TodoSystemLogic(系统方法),TodoReadLogic(读取方法),TodoWriteLogic(写入方法);
  • 启动服务时,我们转移的不是带有逻辑的类,而是几种。

今天就这些了。 我将在以下文章中讨论该框架的其他功能。 有很多。 同时,您可以亲眼看到那里很有趣

Source: https://habr.com/ru/post/zh-CN480828/


All Articles