darkorsa/cordo

基于分层架构和使用CQRS、分层架构、事件、队列等设计的微框架,旨在高效地开发REST API。

0.21.1 2022-11-04 14:20 UTC

This package is auto-updated.

Last update: 2024-09-17 14:07:49 UTC


README

Cordo是一个微框架,旨在通过使用分层架构、CQRS(命令查询责任分离)等原则,高效地开发REST API。

  • 分层架构
  • CQRS(命令查询责任分离)
  • 事件调度器
  • 仓库模式
  • 队列
  • OAuth2
  • UUIDs
  • 按功能打包
  • 最小化配置方法

它符合PSRs: PSR-1PSR-2PSR-3PSR-4PSR-7PSR-11PSR-15PSR-18

创建此框架的主要目标是创建一个高效的工具,用于构建具有良好架构基础和尽可能少的“魔法”和配置的API应用程序。

注意: Cordo仍在开发中。一些基本功能已实现,但测试仍在进行中。请记住这一点。

要求

  • PHP 8.1或更高版本
  • Apache/Nginx

可选要求

  • MySql 5.7(默认数据库驱动程序)
  • PHP Redis扩展(队列的驱动程序)

安装

要创建新项目,请转到项目文件夹,并在该文件夹内键入

$ composer create-project darkorsa/cordo ./ -s dev

然后复制.env_example文件,并将其重命名为.env。然后填写您的配置数据。

可选地,您可以运行控制台命令

$ php cordo core:init --withOAuth --withUuid

它将创建

  • OAuth2所需的所有必要数据库表
  • UUID数据库帮助函数

仍然缺少

工作原理

Cordo并没有重新发明轮子。它基本上是一系列流行的PHP库的组合,并按顺序配置,以创建一个符合现代PHP良好编程实践的单 giản 框架。

一些使用的库

本文档不会详细说明如何处理路由、命令总线、依赖注入容器、查询数据库等,有关这些,请参阅相关库的文档。

还鼓励您自己查找内部的工作原理,查看Cordo Core库,其中包含抽象类和接口。

如果您想了解如何在所有层中组织代码,如何利用CQRSRepository PatternEventsQueues等,请查看Users Bundle。查看安装说明此处

入口点

应用程序的入口点

Web

HTTP请求的入口点是public/index.php。您的apache/nginx配置应指向public文件夹。

控制台

使用Symfony Console组件处理命令行命令。

您可以通过命令行使用以下命令来执行命令:

php cordo [command_name]

列出当前已注册的命令

php cordo list

全局命令应通过在应用对象中添加它们的方式注册到 ./cordo 文件中

$application->add(new SecurityCheckerCommand(new SecurityChecker()));

功能命令应注册到 app/[Context]/[PackageName]/UI/Console/commands.php 文件。

return [
    YourConsoleCommand::class,
    AnotherConsoleCommand::class
];

注册新包

本框架使用按功能划分的包方法。这意味着您将代码组织在 app/ 文件夹中的包中。

只需将您的包文件夹名称添加到 app/Register.php

protected static $register = [
    'Shop\Users',
    // add you packages here
];

一旦您的包被注册,框架将能够访问定义的路由、依赖注入容器定义、配置、命令等。

包结构

用户包默认包含实现的基本 CRUD 操作。

以下是代码的组织方式

app/Shop/Users/
.
├── Application
│   ├── Acl
│   │   └── UsersAcl.php
│   ├── Command
│   │   ├── CreateNewUser.php
│   │   ├── DeleteUser.php
│   │   ├── Handler
│   │   │   ├── CreateNewUserHandler.php
│   │   │   ├── DeleteUserHandler.php
│   │   │   ├── SendUserWelcomeMessageHandler.php
│   │   │   └── UpdateUserHandler.php
│   │   ├── SendUserWelcomeMessage.php
│   │   └── UpdateUser.php
│   ├── Event
│   │   ├── Listener
│   │   │   └── UserCreatedListener.php
│   │   └── Register
│   │       └── UsersListeners.php
│   ├── Query
│   │   ├── UserFilter.php
│   │   ├── UserQuery.php
│   │   └── UserView.php
│   ├── Service
│   │   └── UserQueryService.php
│   ├── config
│   │   └── users.php
│   ├── definitions.php
│   └── handlers.php
├── Domain
│   ├── Event
│   │   └── UserCreated.php
│   ├── User.php
│   ├── UserActive.php
│   ├── UserEmail.php
│   ├── UserId.php
│   ├── UserPassword.php
│   ├── UserPasswordHash.php
│   └── UserRepository.php
├── Infrastructure
│   └── Persistance
│       └── Doctrine
│           ├── ORM
│           │   ├── Metadata
│           │   │   └── App.Shop.Users.Domain.User.dcm.xml
│           │   └── UserDoctrineRepository.php
│           └── Query
│               ├── UserDoctrineFilter.php
│               └── UserDoctrineQuery.php
├── UI
│   ├── Console
│   │   ├── Command
│   │   │   └── CreateNewUserConsoleCommand.php
│   │   └── commands.php
│   ├── Http
│   │   ├── Auth
│   │   │   └── OAuth2UserCredentials.php
│   │   ├── Controller
│   │   │   ├── UserCommandsController.php
│   │   │   └── UserQueriesController.php
│   │   ├── Middleware
│   │   │   └── OAuthMiddleware.php
│   │   └── Route
│   │       ├── OAuthRoutes.php
│   │       └── UsersRoutes.php
│   ├── Transformer
│   │   └── UserTransformer.php
│   ├── Validator
│   │   ├── EmailExistsValidation.php
│   │   ├── NewUserValidator.php
│   │   └── UpdateUserValidator.php
│   ├── trans
│   │   ├── mail.en.yaml
│   │   ├── mail.es.yaml
│   │   └── mail.pl.yaml
│   └── views
│       └── mail
│           └── new-user-welcome.php
└── UsersInit.php

此结构由以下层组成:用户界面应用领域基础设施

重要!

如果您想快速生成新模块的样板代码,有一个相应的命令

php cordo core:module-builder <context> <module_name> [module_archive_file]

您可以在 app/resources/module 中找到预先准备好的存档。

这将为您节省大量时间,因为它将生成典型 CRUD 的整个文件夹和文件结构。

路由

路由定义应位于 app/[Context]/[PackageName]/UI/Http/Route/[PackageName]Routes.php 文件中。路由加载类应继承自抽象类 Cordo\Core\Application\Service\Register\RoutesRegister

使用 FastRoute 进行路由,但进行了修改,允许使用按路由 中间件

生成 API 文档的最佳方式是使用 ApiDoc,但可以根据个人偏好进行更改。

依赖注入容器

DI 容器定义应放置在 app/[Context]/[PackageName]/Application/definitions.php

Cordo 使用 PHP-ID 作为 DI 容器,如需了解详细信息,请参阅 文档

配置

全局配置文件应位于 config/ 目录中,而功能配置的位置应为:app/[Context]/[PackageName]/Application/config/

配置文件应返回 PHP 关联数组。支持多维数组。

用法

$limit = $config->get('users.limit');

其中 "users" 是配置文件的名称,以下段是数组的关联键。

数据库

数据库配置位于 bootstrap/db.php 文件中。框架使用 Doctrine 进行数据库存储和对象映射。

根据 CQRS 方法,首选使用 Doctrine ORM 进行存储,以及使用 Doctrine DBAL 进行查询。

Doctrine 已预先配置以支持 UUID

也支持 XML 映射,因此您可以直接将领域模型与数据库表进行映射。您应将映射放置在 app/[Context]/[PackageName]/Infrastructure/Doctrine/ORM/Metadata/

当您的映射准备就绪后,您可以直接从 composer 创建/更新/删除模式。

composer schema-create
composer schema-update
composer schema-drop

邮件发送器

对于邮件,使用 Laminas Mail。目前有两个邮件传输驱动程序:log(用于开发)和 smtp。您可以在 config/mail.php 文件中定义您的邮件驱动程序和凭据。

要添加/更改驱动程序,只需在 bootstrap/app.php 中替换 MailerFactory 类即可。

国际化

翻译由Symfony 翻译处理。默认的文件格式为 Yaml

您应将翻译文件放在 app/[上下文]/[包名]/UI/trans/ 文件夹或子文件夹中。命名约定为:[域].[语言].yaml,例如:mail.en.yaml

用法

$translator->trans('hello', [], 'mail', 'en')

您可以通过在请求 URI 中添加 &lang 参数或运行控制台命令时添加 --lang 标志来设置每个请求的语言。

翻译配置文件位于 config/trans.php

视图

Plates 被用作模板引擎。将您的视图文件放在 app/[上下文]/[包名]/UI/views/ 文件夹或子文件夹中。

用法

$templates->render('[context].[module]::[subfolder]/[template_name]', [
    // data you want to pass to the template file
]);

命令总线

Cordo 使用 Tactician 命令总线来实现 命令模式

您的命令 -> 处理器映射应放在:app/[上下文]/[包名]/Application/handlers.php 文件中。

命令总线被配置为在每个单独的事务中锁定每个处理器,它还支持事件、队列、命令日志。请查看 bootstrap/command_bus.phpTactician 文档以获取详细信息。

事件

与命令 -> 处理器映射不同,其中对于每个 命令 只能有一个 处理器,您可以为单个发出的事件有多个监听器。

您的监听器定义应位于:app/[上下文]/[包名]/Event/Loader/[包名]Listeners.php。事件加载器类应扩展 Cordo\Core\Application\Service\Register\ListenersRegister

以下是发出事件的示例

/**
 * @var League\Event\EmitterInterface
 */
$emitter->emit('users.created', new UserCreated($command->email()));

app/[上下文]/[包名]/Application/events.php 文件中定义您的监听器(请参阅用户模块中的示例)

$emitter->addListener(
    'users.created',
    static function ($event, UserCreated $userCreated) use ($container) {
        $listener = new UserCreatedListener($container);
        $listener->handle($userCreated);
    }
);

队列

对于后台处理,使用 Bernard 库。

当前支持的驱动程序有

  • Flatfile
  • Redis 扩展

队列的配置文件位于此处,您可以指定在应用程序中使用的驱动程序:config/queue.php

如果您想使您的命令排队,只需实现 Cordo\Core\Application\Queue\MessageInterface 接口或扩展 Cordo\Core\Application\Queue\AbstractMessage 类。

要启动后台进程处理队列中的命令,请在控制台中运行

php queue-worker &

要更好地了解如何处理事件,请查看 Users Bundle 模块,并查看如何为新创建的用户发送欢迎信息。

注意:如果您想使用队列的 Redis 驱动程序,请确保您已安装 PHP 的 Redis 扩展。您可以从 PECL 仓库安装它。

$ sudo pecl install redis
$ sudo service php7.4-fpm restart

OAuth2

此框架默认使用 OAuth2 作为授权方法。OAuth2 服务器配置位于:app/config/auth.php

有关真实生活中的 OAuth2 实现,请查看 Users Bundle)

ACL

为了授权的目的,使用了 Zend ACL。ACL 角色、资源、权限可以在每个包的 app/[上下文]/[包名]/Application/Acl/[包名]Acl.php 中单独定义,该文件应扩展 Cordo\Core\Application\Service\Register\AclRegister

在随 Users Bundle 一起提供的 Auth 包中,已经为用户 ACL 规则准备了 CRUD 操作。

错误

默认情况下,所有错误都记录到 storage/logs/error.log 文件中。

此外,在dev环境中,错误将以美观格式通过Whoops显示在屏幕上。控制台中的错误也将进行美观格式化。在production环境中,错误堆栈跟踪将被发送到在config/error.php中定义的地址。

如果您想更改这些行为,可以在bootstrap/error.php文件中实现。

致谢

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件