njasm/container

此包已弃用且不再维护。未建议替换包。

PHP的依赖容器

1.2.11 2015-08-18 02:13 UTC

README

Build Status Code Coverage Scrutinizer Code Quality Total Downloads Latest Stable Version License HHVM Status

依赖容器/服务定位器

特性

  • 支持别名服务键
  • 循环依赖保护
  • 原始数据类型注册
  • 非注册服务的自动构造函数依赖解析和注入
  • 懒加载和懒实例化方法
  • 懒加载和懒实例化单例服务注册
  • 支持服务实例化后进行公共设置器注入/方法调用
  • 支持服务实例化后进行公共属性/属性注入
  • 在调用Container::get时,可以通过提供新的来覆盖现有的依赖(属性和设置器)声明
  • 支持嵌套提供者/容器
  • 符合Container-Interop接口

要求

  • PHP 5.3或更高版本。

安装

njasm\container包含到您的项目中,通过将其添加到composer.json文件中。

{
    "require": {
        "njasm/container": "~1.0"
    }
}

使用

要创建一个容器,只需实例化Container类。

use Njasm\Container\Container;

$container = new Container();

使用别名

有时您的key太长,不方便客户端代码使用,例如,当将一个interface绑定到一个implementation或使用类的FQCN作为key时。

namespace Very\Long\Name\Space;

interface SomeInterface {}

class SomeImplementation implements SomeInterface
{
    // code here
}

$container = new Njasm\Container\Container();
$container->set('Very\Long\Name\Space\SomeInterface', new SomeImplementation());
$container->alias('Some', 'Very\Long\Name\Space\SomeInterface');

$some = $container->get('Some');

定义服务

服务通过两个参数定义。一个key和一个value。您定义服务的顺序无关紧要。

定义服务 - 原始数据类型

$container->set("Username", "John");

echo $container->get("Username");

定义服务 - 绑定服务(懒加载)

您可以将一个key绑定到一个可实例化的FCQNvalue

$container->bind("MyKey", "\My\Namespace\SomeClass");

如果您想绑定一个服务,并将其注册为Singleton服务。

$container->bindSingleton("MyKey", "\My\Namespace\SomeClass");

both Container::bindContainer::bindSingleton使用懒加载方法,所以当请求MyKey时,\My\Namespace\SomeClass才会被评估/实例化。

当绑定服务时,可以声明构造函数依赖项,设置公共属性和调用带参数的方法,因此在实例化服务时进行注入/设置。

namespace \App\Actors;

class Person {
    protected $name;
    protected $age = 24;
    public genre = 'Male';
    
    public function __construct($name = 'John') {
        $this->name = $name;
    }
    
    public function getName() {
        return $this->name;
    }
    
    public function getAge() {
        return $this->age;
    }
    
    public function setAge($age) {
        $this->age = (int) $age;
    }
}

$container->bind(
    "Person",                       // key
    "\App\Actors\Person",           // FQCN
    array("Jane"),                  // constructor dependencies
    array("genre" => "Female"),     // attributes injection
    array("setAge" => array(33))    // call methods
);

// binding with chaining methods 
$container->bind("Person", '\App\Actors\Person')
    ->setConstructorArguments(array("Jane"))        // setConstructorArgument($index, $argument)
    ->setProperty("genre" => "Female")              // setProperties(array("genre" => "Female", ...) also work
    ->callMethod("setAge", array(33));              // callMethods(array('methodName' => 'methodValue', ...));
    
// retrieving the object    
$person = $container->get("Person");
echo $person->getName(); // Jane
echo $person->getAge();  // 33
echo $person->genre      // Female

// calling services and overriding declared dependencies 
$person2 = $container->get(
    "Person", 
    array("Mark"), 
    array("genre" => "Male"), 
    array("setAge" => array(55))
);
echo $person2->getName(); // Mark
echo $person2->getAge();  // 55
echo $person2->genre      // Male

定义服务 - 对象(懒加载)

$mailer = new \Namespace\For\My\MailTransport(
    "smtp.example.com", 
    "username", 
    "password", 
    25
); 

$container->set(
    "Mail.Transport", 
    $mailer, 
    array(), // constructor args 
    array(), // public properties injection
    array("withSSL" => array(false)) // calling methods
);

$mailerTransport = $container->get("Mail.Transport");

对于set定义,也可以覆盖已声明的现有依赖。

// calling methods and injecting attributes is also possible
$mailerTransportSsl = $container->get(
    "Mail.Transport", 
    array(), 
    array(), 
    array("withSSL" => array(true))
);

定义服务 - 复杂构建(懒加载)

有时候,您可能想实例化一个对象,但构建过程非常复杂,您希望控制这个过程。您可以使用匿名函数来实现。

$container->set(
    "Complex",
    function($firstName = "John", $lastName = "Doe") {
        // complex logic here
        // ...
        $theComplexObject = new Complex($firstName, $lastName);
        
        return $theComplexObject;
    }
);

$complex = $container->get("Complex");

// injecting closure dependencies is also possible
$complexJane = $container->get("Complex", array("Jane", "Fonda")); 

定义服务 - 具有嵌套依赖的复杂构建(懒加载)

嵌套依赖的创建也是可能的。您只需将容器传递给闭包即可。

$container->set(
    "Mail.Transport",
    function() use (&$container) {
        return new \Namespace\For\My\MailTransport(
            $container->get("Mail.Transport.Config")
        );
    }
);

$container->set(
    "Mail.Transport.Config",
    function() {
        return new \Namespace\For\My\MailTransportConfig(
            "smtp.example.com", 
            "username", 
            "password", 
            25
        );
    }
);

$mailer = $container->get("Mail.Transport");

定义单例服务

对于注册单例服务,您使用单例方法调用。

$container->singleton(
    "Database.Connection",
    function() {
        return new \Namespace\For\My\Database(
            "mysql:host=example.com;port=3306;dbname=your_db", 
            "username", 
            "password"
        );
    }
);

// MyDatabase is instantiated and stored, for future requests to this service, 
// and then returned.
$db = $container->get("Database.Connection");
$db2 = $container->get("Database.Connection");

// $db === $db2 TRUE

定义子/嵌套容器

只要您使用现有的容器适配器为您的应用程序现有的容器,就可以嵌套容器。适配器类必须实现 ServicesProviderInterface,更多示例请参阅 Adapter 文件夹。

$pimple; // is your instantiated pimple container
$pimple["Name"] = $pimple->factory(function() {
   return "John";
}
 
$pimpleAdapter = new \Njasm\Container\Adapter\PimpleAdapter($pimple);
$mainContainer = new \Njasm\Container\Container();
$mainContainer->provider($pimpleAdapter);
 
$mainContainer->has("Name"); // TRUE
echo $mainContainer->get("Name"); // John

服务的自动解析

当容器被请求一个未注册的服务时,它会尝试找到该类,并自动尝试解析您类的构造函数依赖项。

namespace My\Name\Space;

class Something
{
    // code
}

// without registering the Something class in the container you can...
$container = new Njasm\Container\Container();
$something = $container->get('My\Name\Space\Something');

//$something instanceof 'My\Name\Space\Something' == true

//once again you can also inject dependencies when calling get method.
$something = $container->get(
    "My\Name\Space\Something", 
    array("constructor value 1", "constructor value 2"),
    array("attributeName" => "value 1"), // attributes
    array("methodName" => array("value 1", "value 2"))
);

路线图

不分先后 - 检查里程碑以获得更有序的视图。

  • 从配置文件中加载定义
  • 优化

贡献

您想帮助开发新功能/通过重构等改进现有代码吗?或者想讨论一个功能/错误/想法?只要您遵循一些PR指南,问题和拉取请求都欢迎

拉取请求必须

  • 符合PSR-2规范。
  • 在您的拉取请求中提交测试以验证您的更改/新代码的引入。
  • 享受乐趣。