fas/di

快速且简单的依赖注入

0.4.5 2021-07-17 06:27 UTC

This package is auto-updated.

Last update: 2024-09-17 13:57:44 UTC


README

Build Status Test Coverage

Latest Stable Version Latest Unstable Version License Total Downloads

安装

composer require fas/di

使用

创建容器

// Brand new container
$container = new Container;

// Load compiled container if present
$container = Container::load('/tmp/container.php');

添加依赖

// ->set(entryName, entryName | callback | null)
// (singleton by default)
$container->set(LoggerInterface::class, 'some_container_entry');

// abstract factory
$container->set(LoggerInterface::class, 'some_container_entry')->factory();

// lazy
$container->set(LoggerInterface::class, 'some_container_entry')->lazy(LoggerInterface::class);

// lazy abstract factory
$container->set(LoggerInterface::class, 'some_container_entry')
    ->lazy(LoggerInterface::class)
    ->factory();

// shorthands
$container->singleton(LoggerInterface::class, 'some_container_entry');
$container->factory(LoggerInterface::class, 'some_container_entry');
$container->lazy(LoggerInterface::class, 'some_container_entry');

 // If entry MyLogger::class does not exist in the container,
 // The class MyLogger::class will be instantiated.
$container->singleton(LoggerInterface::class, MyLogger::class);

// Custom factory method
$container->singleton(LoggerInterface::class, function () {
    return new MyLogger;
});

// Any callable will do
$container->singleton(LoggerInterface::class, [MyLoggerFactory::class, 'create']);

抽象工厂。在每次调用 ->get() 时将解析

// ->factory(entryName, entryName | callback | null)
$container->factory(MyLogger::class); // abstract factory shorthand

$logger1 = $container->get(MyLogger::class); // will create new object
$logger2 = $container->get(MyLogger::class); // will create new object

延迟解析。在使用前不会解析。(虚拟代理)

// ->lazy(entryName, entryName | callback | null)
$container->lazy(MyLogger::class); // Lazy shorthand

// make anything lazy
$container->set('myentry', [MyFactory::class, 'create'])
    ->lazy(LoggerInterface::class);

混合匹配,任意组合

$container->factory(MyLogger::class)->lazy();

相当于

$container->lazy(MyLogger::class)->factory();

性能

// Use cached virtual proxies (lazy), and write cache if missing
$container->enableProxyCache('/tmp/proxies');

// Generate a class containing proper methods for registered entries.
// This can be used afterwards to avoid a lot of reflection when resolving entries.
$container->save('/tmp/container.php');

配方

全自动缓存容器和代理

利用缓存的简单方式。

请注意,一旦缓存被写入,必须手动删除以更新。这种设置通常在开发中不是非常有用。

$container = Container::load("/tmp/container.php");
if (!$container) {
    $container = new Container;
    $container->singleton(LoggerInterface::class, MyLogger::class);
    $container->save('/tmp/container.php');
}
$container->enableProxyCache("/tmp/proxies");

// Container ready for use

生成编译容器

这可以在构建阶段的启动过程中用于编译脚本。

$container = new Container;

// ... populate container here

$entries = $container->save("/tmp/container.php");

print "-----------------\nCompiled " . count($entries) . " entries\n-----------------\n";
print implode("\n", $entries) . "\n\n";

通用示例

使用配置、容器和路由的通用示例。

<?php

require __DIR__ . '/../vendor/autoload.php';

use App\ContainerFactory;
use App\RouterFactory;
use Fas\DI\Container;
use Fas\Configuration\DotNotation;
use Fas\Configuration\YamlLoader;
use Fas\Routing\Router;
use Laminas\Diactoros\ResponseFactory;
use Laminas\Diactoros\ServerRequestFactory;

$configFile = getenv('CONFIG_FILE') ?: '/app/config.yaml';

try {
    // Setup configuration, container and router
    $configuration = FileCache::load('/tmp/config.cache.php') ?? new DotNotation(YamlLoader::loadWithOverrides($configFile));
    $container = Container::load('/tmp/container.cache.php') ?? ContainerFactory::create($configuration);
    $router = Router::load('/tmp/router.cache.php') ?? RouterFactory::create($container);

    // Handle actual request
    $request = ServerRequestFactory::fromGlobals();
    $response = $router->handle($request);
} catch (Throwable $e) {
    $code = $e instanceof HttpException ? $e->getCode() : 500;
    $response = (new ResponseFactory)->createResponse($code, $e->getMessage());
    $response->getBody()->write('<pre>' . (string) $e . '</pre>');
} finally {
    (new SapiEmitter)->emit($response);
}

通用编译器示例

上面示例的编译器示例

<?php

require __DIR__ . '/../vendor/autoload.php';

use App\ContainerFactory;
use App\RouterFactory;
use Fas\DI\Container;
use Fas\Configuration\DotNotation;
use Fas\Configuration\YamlLoader;
use Fas\Routing\Router;
use Laminas\Diactoros\ResponseFactory;
use Laminas\Diactoros\ServerRequestFactory;

$configFile = getenv('CONFIG_FILE') ?: '/app/config.yaml';

// Compile config
$configuration = new DotNotation(YamlLoader::loadWithOverrides($configFile));
FileCache::save('/tmp/config.cache.php', $configuration);

// Compile container
$container = ContainerFactory::create($configuration);
$entries = $container->save('/tmp/container.cache.php');
print "-----------------\nBuilt " . count($entries) . " entries\n-----------------\n" . implode("\n", $entries) . "\n-----------------\n";

// Compile routes
$router = RouterFactory::create($container);
$router->save('/tmp/router.cache.php');