a2workspace/laravel-automount

使依赖注入更简单

v1.1.0 2022-09-04 08:47 UTC

This package is auto-updated.

Last update: 2024-09-04 13:38:09 UTC


README

随着PHP 8的新特性增加,你可能已经不需要此套件了,可参考构造函数属性提升的做法



Laravel的依赖注入很棒,但我们让它更好!

关于

想想看,当你项目越来越大,一定有遇到过又臭又长的构造函数:

use A2Workspace\AutoMount\AutoMountDependencies;

class ProductController extends Controller
{
    protected ProductService $productService;

    protected ProductRepository $productRepository;

    protected ProductStockManager $productStockManager;

    public function __construct(
        ProductService $productService,
        ProductRepository $productRepository,
        ProductStockManager $productStockManager
    ) {
        $this->productService = $productService;
        $this->productRepository = $productRepository;
        $this->productStockManager = $productStockManager;
    }

    public function __invoke(Request $request)
    {
        $this->productService->doSomething();
    }
}

通过AutoMountDependencies特性自动挂载依赖,让我们省略复杂的绑定过程。

use A2Workspace\AutoMount\AutoMountDependencies;

class ProductController extends Controller
{
    use AutoMountDependencies; // Add this.

    protected ProductService $productService;

    protected ProductRepository $productRepository;

    protected ProductStockManager $productStockManager;

    // We don't need the constructor anymore...

    public function __invoke(Request $request)
    {
        $this->productService->doSomething(); // Still works!
    }
}

安装

此套件基于PHP 7.4的类型属性新功能,请确保你的PHP更新到最新版本。

composer require a2workspace/laravel-automount

如何使用

只需在目标类上使用AutoMountDependencies特性

use A2Workspace\AutoMount\AutoMountDependencies;

class PaymentService
{
    use AutoMountDependencies;
}

接下来,有类型定义的类属性就会在构造时自动进行依赖注入。

use A2Workspace\AutoMount\AutoMountDependencies;

class PaymentService
{
    use AutoMountDependencies;

    protected PaymentGatewayFactory $factory;
}

注意:考虑到继承,请避免在要被处理的属性上使用private私有。

不会被处理的属性

以下类型的属性会被忽略处理

  1. 基本类型(int, float, bool, array ...)
  2. 未定义类型的属性
  3. 定义为可空的属性
  4. 有初始值的属性
use A2Workspace\AutoMount\AutoMountDependencies;

class PaymentService
{
    use AutoMountDependencies;

    protected int $amount; // Pass.

    protected array $gateways; // Pass.

    protected $something; // Pass.

    protected ?PaymentGateway $gateway = null; // Pass.

    protected PaymentGatewayFactory $factory; // Do inject.
}

限制

覆盖构造函数

AutoMountDependencies特性中定义了在构造函数中执行依赖挂载的动作。当你需要覆盖__construct()时,记得手动调用mountDependencies()方法。

use A2Workspace\AutoMount\AutoMountDependencies;

class PaymentService
{
    use AutoMountDependencies;

    public function __construct()
    {
        $this->mountDependencies(); // Add this line.

        // ...
    }
}

避免私有属性

当类型属性被定义为私有,会导致继承后的子类,在构造时无法写入属性而造成错误。

请谨慎使用private,或将属性定义为可空

use A2Workspace\AutoMount\AutoMountDependencies;

abstract class BasePaymentGateway
{
    use AutoMountDependencies;

    private PaymentServiceProvider $service;
}

class PaymentGateway extends BasePaymentGateway
{
    // ...
}

$gateway = new PaymentGateway; // 拋出 PaymentGateway::$service 未被初始之錯誤