spiechu/lazy-pimple

此包已被废弃,不再维护。未建议替代包。

为Pimple DI容器提供懒加载服务定义。

0.7 2019-04-27 11:13 UTC

This package is auto-updated.

Last update: 2022-02-05 13:00:04 UTC


README

Pimple DI容器提供懒加载服务定义。

Travis构建状态:构建状态

其他徽章: Scrutinizer Code Quality Code Coverage

简介

在使用Pimple DIC时,有时需要懒加载服务,并且只在需要时实例化它。此外,还有可能懒加载事件订阅者。(现在你会明白为什么 \Symfony\Component\EventDispatcher\EventSubscriberInterface 有静态接口)。

在底层,这个库使用 Proxy Manager。首先生成对象的代理。在需要实例方法调用之前,使用代理。这意味着即使是静态调用,也不需要对象的实例,而是通过代理来调用。

安装

最简单的方法是将 "spiechu/lazy-pimple": "~0.1" 添加到您的 composer.json

为了使懒加载工作,需要在Pimple中添加两个定义的最小配置

<?php

$pimpleContainer['lazy_loading_value_holder_factory_factory'] = function(Container $container) {
  return (new \Spiechu\LazyPimple\Factory\LazyLoadingValueHolderFactoryFactory())
    ->getFactory();
};

$pimpleContainer['lazy_service_factory'] = function(Container $container) {
  return new \Spiechu\LazyPimple\Factory\LazyServiceFactory($container['lazy_loading_value_holder_factory_factory']);
};

为了使用ProxyManager代理缓存,LazyLoadingValueHolderFactoryFactory->getFactory() 接受写入空间的路径,其中它可以转储生成的代理类定义。您可以在页面底部的完整列表中查看如何操作。

用法

懒加载服务

使用此库,您可以轻松地懒加载Pimple服务定义,直到需要它们。

<?php

// imgine awesome service is expensive and should be lazy loaded
$pimpleContainer['awesome_service'] = function(Container $container) {
  return $container['lazy_service_factory']->getLazyServiceDefinition(AwesomeService::class, function() {
    return new AwesomeService();
  });
};

懒加载事件订阅者

我们从典型的事件订阅者定义开始。

<?php

$pimpleContainer['first_subscriber'] = function(Container $container) {
  // subscriber has no idea it will be lazy loaded
  return new FirstSubscriber($container['awesome_service']);
};

现在,通过使用 \Pimple\ServiceProviderInterface 服务提供者,我们可以将订阅者转换为懒加载。

<?php

$pimpleContainer->register(new LazyEventSubscriberServiceProvider(
  $pimpleContainer['lazy_service_factory'],
    // we're defining which service resolves to EventDispatcher
    'event_dispatcher',
    [
      // we're defining subscribers
      'first_subscriber' => FirstSubscriber::class,
    ]
));

这样,只有在事件实际发生时,订阅者才会被实例化,并且调用事件处理方法。

示例Pimple服务定义(摘自我的“测试”)。

<?php

use Pimple\Container;
use Spiechu\LazyPimple\DependencyInjection\LazyEventSubscriberServiceProvider;
use Spiechu\LazyPimple\Factory\LazyLoadingValueHolderFactoryFactory;
use Spiechu\LazyPimple\Factory\LazyServiceFactory;
use Spiechu\LazyPimple\FirstSubscriber;
use Spiechu\LazyPimple\Service\AnotherService;
use Spiechu\LazyPimple\Service\AwesomeService;
use Spiechu\LazyPimple\Service\EventEmittingService;
use Symfony\Component\EventDispatcher\EventDispatcher;

// prevent leaking any variables into global namespace
return call_user_func(function() {
  require_once './vendor/autoload.php';

  $pimpleContainer = new Container();
    
  $pimpleContainer['proxy_manager_cache_target_dir'] = function(Container $container) {
    $targetDir = __DIR__ . '/proxy_cache_dir';

    if (!is_dir($targetDir)) {
      mkdir($targetDir, 0775, true);
    }

    return $targetDir;
  };

  $pimpleContainer['lazy_loading_value_holder_factory_factory'] = function(Container $container) {
    return (new LazyLoadingValueHolderFactoryFactory())
      ->getFactory($container['proxy_manager_cache_target_dir']);
  };
    
  $pimpleContainer['lazy_service_factory'] = function(Container $container) {
    return new LazyServiceFactory($container['lazy_loading_value_holder_factory_factory']);
  };

  $pimpleContainer['event_dispatcher'] = function(Container $container) {
    return new EventDispatcher();
  };

  // imgine awesome service is expensive and should be lazy loaded
  $pimpleContainer['awesome_service'] = function(Container $container) {
    return $container['lazy_service_factory']->getLazyServiceDefinition(AwesomeService::class, function() {
      return new AwesomeService();
    });
  };

  $pimpleContainer['another_service'] = function(Container $container) {
    // this one will receive proxy object
    return new AnotherService($container['awesome_service']);
  };

  $pimpleContainer['event_emitting_service'] = function(Container $container) {
    return new EventEmittingService($container['event_dispatcher']);
  };

  $pimpleContainer['first_subscriber'] = function(Container $container) {
    // subscriber has no idea it will be lazy loaded
    return new FirstSubscriber($container['awesome_service']);
  };

  $pimpleContainer->register(new LazyEventSubscriberServiceProvider(
    $pimpleContainer['lazy_service_factory'],
    // we're defining which service resolves to EventDispatcher
    'event_dispatcher',
    [
      // we're defining subscribers
      'first_subscriber' => FirstSubscriber::class,
    ]
  ));

  return $pimpleContainer;
});