mkuettel / codeigniter4-services
CodeIgniter 4 服务层库
Requires
- php: ^8.3
- codeigniter4/framework: ^4.5
Requires (Dev)
- ext-sqlite3: *
- codeigniter/coding-standard: ^1.7
- codeigniter/phpstan-codeigniter: ^1.4
- fakerphp/faker: ^1.23
- friendsofphp/php-cs-fixer: ^3.54
- mikey179/vfsstream: ^1.6
- mockery/mockery: ^1.6
- phpunit/phpunit: ^10.0
- prewk/result: ^3.3
- squizlabs/php_codesniffer: 3.*
This package is auto-updated.
Last update: 2024-09-29 01:23:44 UTC
README
这个库应该使为CodeIgniter4应用程序提供服务层变得更加容易。此外,还有一些工具可以与模型层交互,特别是这个库包含一个服务,用于提供更优雅和更可靠的数据库事务语法。
安装
您可以使用composer将此库添加到您的项目中。
composer require mkuettel/codeigniter4-services
就这么多,但您可能想更改一些配置,如下一节所述。
配置
在src/Config目录中提供了多个配置文件。您可以将这些文件复制到您的项目中,并从类扩展以覆盖默认配置。
(未来将添加发布脚本以将这些文件复制到您的项目中)
服务接口
此库提供接口\MKU\Services\ServiceInterface
。
想法是通过定义另一个接口来扩展此接口,以实现您自己的服务。在此接口中,您定义服务将具有的所有方法
use \MKU\Services\ServiceInterface;
interface MyBusinessService extends ServiceInterface {
public function placeOrder(Order $order): Result;
public function sendOrderConfirmationMail(Order $order): Result;
// ...
}
然后,通过您自己的服务类实现此接口。
class SimpleBusinessService extends MyBusinessService {
private OrderModel $orderModel;
private MailService $mailService;
public function __construct(OrderModel $orderModel, MailService $mail) { /* ... */ }
public function shortname(): string { return 'simple_business'; }
public function placeOrder(Order $order): Result { /* */ }
public function sendOrderConfirmationMail(Order $order): Result { /* */ }
// ...
}
您还需要实现shortname(): string
方法,该方法返回此服务实现的唯一标识符。
shortname将后来用于使用以下方式获取或创建实现服务类的实例
service('<shortname>');
\Config\Services::shortname();
但为了使其工作,您必须现在按照以下方式注册它
class Services extends BaseService {
// ....
// use the same parameters as required by the constructor of the service class,
// but make them null by default.
public function business_simple() (
OrderModel $orderModel = null,
MailService $mail = null,
bool $getShared = true // add extra parameter to reuse past instance if available (e.g. a singleton instance)
): SimpleBusinessService {
if ($getShared) return self::getSharedInstance('simple_business', $config, $db);
return new SimpleBusinessService(
$orderModel ?? model(OrderModel::class);
$mail ?? self::mail_service(),
);
}
// use the interface as return type here
public function business(): MyBusinessService {
// change which service class to use for the MyBusinessService interface here
return self::business_simple();
}
// ....
}
TODO(因此,这不应手动完成):将ServiceContainer作为\Config\Services的基础类添加,它根据其构造函数类型或注释自动配置服务,并在\Config\Services中创建构建方法。
事务服务
此库提供TransactionService,允许您在数据库事务期间执行自定义函数
// PHP 7.4+ using arrow functions
service('transaction')->transact(fn() => do_database_operation())
// Using anonymous function (or any Closure)
service('transaction')->transact(function() use ($db) {
$db->insert( /* update */ ); ...
$db->update( /* ... */); ...
});
以这种方式使用,事务服务在执行给定的闭包之前开始事务。如果在事务期间发生异常,则事务将回滚。
嵌套事务
如果底层数据库驱动程序和数据库支持,则事务可以嵌套。目前,这些驱动程序并未对所有驱动程序完全实现,但此存储库提供了一个替代方案,它通过使用保存点扩展了CI4数据库驱动程序SQLite & MySQLi,以支持嵌套事务。
您可以通过设置.env文件或数据库配置中的DBDriver
选项来使用它们
# .env
# ...
# use mysqli driver with support for nested transactions
database.default.DBDriver = '\MKU\Services\Database\Transactional\MySQLi'
# ...
# use SQLite3 driver with support for nested transactions
database.tests.DBDriver = '\MKU\Services\Database\Transactional\SQLite3'
此外,不同的驱动程序和数据库可能具有不同的事务保证和隔离级别。还要注意自动提交行为,这在某些数据库系统中可能是默认启用的。
DataProvider
和PersistenceService
此库还提供DataProvider
接口和PersistenceService
接口。这些接口旨在在服务层中用于与模型层交互。想法是通过仅返回实体对象而不是数据库连接句柄、查询结果对象或其他数据库特定对象,将数据访问层(模型、CodeIgniter数据库内容)与业务逻辑层(控制器)分开。
为了使持久化服务能够正确识别和处理实体,用作数据提供程序或持久化服务参数的实体类必须实现ServiceEntity
接口,这迫使您定义主键(或者声明实体没有主键)。如果您有一个扩展自CodeIgniter实体(这不是必需的)类的实体类,您可以使用CodeIgniterServiceEntityTrait
来使用定义的$primaryKey
属性。
数据提供程序是查询并作为实体对象提供数据的服务,但本身不修改数据。DataProvider
接口提供了以下三个基本方法:
interface DataProvider {
public function get($id): ?ServiceEntity;
public function refresh(ServiceEntity $id): ?bool;
public function exists($id): bool;
}
$id
是要查询的实体的主键,这也可以是多个属性的数组。您可以通过在实体类中实现ServiceEntity来定义此属性。
持久化服务是数据提供程序的扩展,也需要实现修改它们提供的数据的方法。以下提供了一些附加方法:
interface PersistenceService extends DataProvider {
public function save(ServiceEntity $entity): Result;
public function delete($id): ServiceEntity|bool;
}
可配置服务
目前只有一个名为MKU\Services\Library\Config\Configurable
的接口和同一命名空间下的ConfigurableTrait
,简化了前者的实现。
想法是您使用Trait并在服务中实现applyConfig()方法,使用您自己的自定义CodeIgniter配置类进行配置。
这个特性尚未完全构思,非常实验性,可能会发生变化。
贡献
如果您想为此项目做出贡献,请给我发消息。我很高兴收到反馈和建议。
欢迎在我的GitHub仓库提交拉取请求和错误报告