luna-fw/djinn

1.0.0 2018-11-10 20:13 UTC

This package is not auto-updated.

Last update: 2024-09-18 15:18:29 UTC


README

Build Status Latest Stable Version Total Downloads License

Djinn 是一个功能齐全的 PHP 依赖注入容器。我们称之为 Djinn,因为依赖注入容器就像一个精灵:它给予主人(调用者)愿望(依赖项)。

安装

必须使用 composer 安装此包

composer require luna-fw/djinn

或者在您的 composer.json 依赖中包含 luna-fw/djinn

用法

此包实现了 PSR-11 接口和异常

  • Psr\Container\ContainerInterface
    • has(key) - 根据字符串键返回实例
    • get(key) - 如果给定实例存在,则返回 true
  • Psr\Container\ContainerExceptionInterface
  • Psr\Container\NotFoundExceptionInterface

有关详细信息,请参阅:https://www.php-fig.org/psr/psr-11/

我们认为 PSR-11 规范过于简单,因此我们在实现中添加了一些额外的接口(这些扩展实现不会阻止某人将其用作 PSR-11 兼容容器)。

以下是扩展接口

  • ContainerConfigContract - 包含与容器配置相关的函数。
    • bind - 配置给定键的解析
    • singleton - 配置给定键的解析,始终返回不可变实例(单例)。
    • contextual - 与 bind 相同,但解析取决于“谁”请求实例。
    • contextualSingleton - 与 contextual 相同,但始终返回不可变实例(单例)。
  • ExtendedContainerContract - 包含与 DI 注入/解析相关的函数。
    • getFor - 根据定义的配置返回所需的类或接口的实例,解析所有依赖项。允许上下文绑定。
    • run - 执行方法,解析其所有依赖项,根据定义的配置。

要使用它,您需要包含 vendor/autoload.php 文件。然后,您只需实例化 Luna\Djinn 类并开始使用它。

<?php
require 'vendor/autoload.php';

// keep the container instance available globally
$djinn = new \Luna\Djinn();

// configure the bindings
$djinn->bind(FooContract::class, function() {
    return new FooClass('paramether'); 
});

// every time you need an instance that implements FooContract, you call the get method
$foo = $djinn->get(FooContract::class);

echo get_class($foo); // prints FooClass

这是 DI 容器的最简单用法。在实际环境中,您可能希望将容器的所有配置分散在特定的文件中(例如 dependencies.php 或类似文件),并将所有对容器方法的调用推送到系统的“边缘”(可能是路由器),因为 PSR-11 建议不要将容器对象传递给其他对象。

请注意,我们在解析时始终有两个步骤

  1. 配置容器,让它知道如何解析您的依赖项。
  2. 使用容器

一些重要注意事项

  • 如果您的愿望是一个有效的类,并且在它的构造函数中不接受任何参数,它将自动实例化。
  • 如果您的愿望是一个有效的类,并且它的构造函数参数可以通过容器解析,它们将被递归解析。
  • 一个常见用法是使用接口作为愿望,并使用类名作为授权,在这种情况下,授权的类将被解析并授权。
  • 可以对同一愿望有多个绑定(即对同一接口有多个实现),根据愿望者的不同进行授权。例如,如果从不同位置调用相同的接口,您可以根据上下文得到不同的结果。
  • 在自动解析构造函数或方法的参数时,我们始终首先尝试使用变量名称解析,然后使用类型提示。
  • 我们还可以通过Djinn运行一个函数/方法,它会尝试解决所有依赖。这在构建路由器时特别有用,因为您不需要手动通过构造函数注入所有内容。
  • 我们还提供了单例绑定选项,它总是为相同的愿望返回相同的实例。

配置/绑定示例

简单绑定

<?php
$djinn->bind(FooClass::class, function() {
    return new FooClass('paramether'); 
});

$djinn->bind('barservice', function() {
    return new BarClass($djinn->get(FooClass::class)); 
});

绑定单例(相同的内容,但Djinn总是返回相同的对象)

<?php
$djinn->singleton(FooClass::class, function() {
    return new FooClass('paramether'); 
});

将接口绑定到实现

<?php
$djinn->bind(FileUploaderInterface::class, YoutubeUploader::class);

上下文绑定(比如说,您想要上传照片到谷歌照片,视频到YouTube)

<?php
$djinn->contextual(PhotoContoller::class, FileUploaderInterface::class, GooglePhotosUploader::class);
$djinn->contextual(VideoController::class, FileUploaderInterface::class, YoutubeUploader::class);

绑定原始数据类型(并运行一个方法)

<?php
$djinn->contextual(FooClass::class.':sum', '$value1', 3);
$djinn->contextual(FooClass::class.':sum', '$value2', 7);

$djinn->run('sum', $djinn->get(FooClass::class)); // returns 10 

要了解更多关于此容器使用的示例,请参阅tests文件夹下的测试。

测试

要在包上运行测试,首先运行composer install,然后转到根目录,并运行以下命令之一

在Linux/Unix上

./vendor/bin/phpunit

在Windows上

.\vendor\bin\phpunit.bat

或者在任何平台上

php ./vendor/phpunit/phpunit/phpunit

您可以使用所有phpunit选项。

贡献

Luna框架仍然是一个非常初期的项目。我刚刚开始,到目前为止我一个人在做。

如果您想贡献,请通过[email protected]联系我,我们可以讨论您如何提供帮助。

目前,我们还没有定义任何关于拉取请求的过程,所以您可以帮助我定义这个过程,并成为其中的一员。