承接 aeris/zf-di-config 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

aeris/zf-di-config

Composer 安装命令:

composer require aeris/zf-di-config

包简介

Configurable dependency injection for the ZF2 ServiceManager

README 文档

README

Configurable dependency injection for the ZF2 ServiceManager.

Installation

You can install ZfDiConfig using composer:

composer require aeris/zf-di-config

Then add the module to your application config:

// config/application.config.php
return [
	'modules' => [
    	'ZfDiConfig',
    	// ...
    ],
    // ...
];

Basic Usage

ZfDiConfig allows you to configure services, instead of using service factories. For example:

// module.config.php
return [
	'my_app' => [
    	'foo' => [
        	'bar' => 'qux'
        ]
    ],
    'service_manager' => [
    	// Config for ZfDiConfig
    	'di' => [
        	'SomeService' => '\MyApp\SomeService',
            'FooService' => [
            	'class' => '\MyApp\FooService',
                'args' => ['@SomeService'],
                'setters' => [
                	'bar' => '%my_app.foo.bar'
                ]
            ]
        ]
    ]
];

In this example, we:

  • Created a service called "SomeService" which is an instance of \MyApp\SomeService
  • Created a service called "FooService" which is an instance of \MyApp\FooService
  • Injected SomeService into FooService as a constructor argument
  • Set the configured value of bar, using FooService::setBar()

Compare this to a typical ZF2 approach for creating services:

// module.config.php
return [
	'my_app' => [
    	'foo' => [
        	'bar' => 'qux'
        ]
    ],
	'service_manager' => [
    	'invokables' => [
        	'SomeService' => '\MyApp\SomeService',
        ]
        'factories' =>" [
        	'FooService' => '\MyApp\Factory\FooServiceFactory.php'
        ]
    ]
];

// MyApp/Factory/FooServiceFactory.php
namespace MyApp\Factory;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class FooServiceFactory implements FactoryInterface {
	public function createService(ServiceLocatorInterface $serviceLocator) {
    	$someService = $serviceLocator->get('SomeService');
        
        // Inject SomeService into FooService
    	$fooService = new \MyApp\FooService($someService);
        
        // Set the a parameter from the module config
        // onto FooService
        $config = $serviceLocator->get('config');
        $bar = $config['my_app']['foo']['bar'];
        $fooService->setBar($bar);
        
        return $fooService;
    }
}

This approach works, but it can become very verbose, and it makes it difficult to see at a glance how your services are wired together.

ZfDiConfig takes a different approach, by allowing you to configure how your services are wired together:

Plugins

ZfDiConfig uses plugins to resolve configured references. A few plugins are provided to cover basic usage, though you can easily add your own plugins, too.

Most plugins allow either a short or long form of configuration. For example, the ServiceResolverPlugin can be referenced as $service or using the @ prefix:

[
	'FooService' => [
    	'class' => '\MyApp\FooService',
        'args' => [
        	// these two arguments are equivalent
        	'@BarService',
           	[
            	'$service' => [
                	'name' => 'BarService'
                ]
            ]
        ]
    ]
]

Default Plugin

By default, ZfDiConfig uses the $factory plugin for configuring services, so that:

[
	'FooService' => '\App\Service\Foo'
]

...is the same as...

[
	'FooService' => [
		'$factory' => '\App\Service\Foo'
	]
]

If you do not want to define your service using the $factory plugin, there are a couple of options. For one, you can just use a different plugin, and DiConfig will be smart enough to figure it out.

[
	'FooConfig' => '%my_app.options.foo'  // DiConfig won't try to use $factory here
]

You can also override the global default plugin, in the zf_di_config module config:

[
	'zf_di_config' => [
		'default_plugin' => '$myAwesomePlugin',
		'plugins' => [...]
	]
]

FactoryPlugin

This is the default plugin used when configuring a service. It allows you to create configured objects instances. You have already seen how this plugin is used in the basic usage examples.

One cool thing is that you can actually use this plugin 'inline' from within other plugin configuration. Let me demonstrate:

[
	'FooService' => [
    	'class' => '\MyApp\FooService',
        'args' => [
        	// Inject a BarService instance "on the fly"
            [ $factory' => '\MyApp\BarService' ]
        ]
    ]
]

Configuration Reference

The FactoryPlugin can accept the following configurations:

Short Form:
[
	'$factory' => '\MyApp\FooService'
]
Really Short Form:
[
	'$factory:\MyApp\FooService'
]
Long Form:
[
	'$factory' => [
    	// Object class (required)
    	'class' => '\MyApp\FooService',
        // services to inject in constructor (optional)
        'args' => ['@SomeService'],
        // Service to inject using setters
        'setters' => [	
        	// This will inject 'SomeService'
            // using the FooService::setBar() method
        	'bar' => '@SomeService'
        ]
    ]
]

ServiceResolverPlugin

The service resolver plugin resolves references to existing services.

Configuration Reference
Short Form:
[
	'@NameOfService`, 		// resolves to $serviceLocator->get('NameOfService')
    '@NameOfService::foo' 	// resolves to $serviceLocator->get('NameOfService')->getFoo()
]
Long Form:
[
	'$service' => [
    	'name' => 'NameOfService',
        // optional
        'getter' => 'foo'
    ]
]

ConfigParamPlugin

The ConfigParamPlugin allows you to access raw values from you application config.

Configuration Reference

Short Form
[
	// resolves to $serviceLocator->get('config')['foo']['bar']['faz']
	'%foo.bar.faz'
]
Long Form
[
	'$param' => [
    	'path' => 'foo.bar.faz',
        'default' => 'qux'
    ]
]

ServiceManagerPlugin

The ServiceManagerPlugin allows you to create a service manager plugin on the fly. The created service manager may be configured with ZfDiConfig, just like your top level service manager.

Configuration reference

[
	'$serviceManager' => [
		// Will validate all services of this service manager as belonging
		// to SomeInterface
		'service_type' => '\MyApp\SomeInterface',
		'config' => [
			'invokables' => [
				'Foo' => '\MyApp\Foo'
			],
			// You can use ZfDiConfig here, too!
			'di' => [
				'Bar' => [
					'class' => '\Bar',
					'args' => ['%my_app.bar']
				]
			]
		],
		// or, you could use a config reference
		// 'config' => '%my_app.custom_manager'
	]
]

Extending ZfDiConfig

You can extend ZfDiConfig using custom plugins. Plugins must implement \Aeris\ZfDiConfig\ServiceManager\ConfigPlugin\ConfigPluginInterface, and be registered in your module config.

Example

Let's say you want to create a plugin to resolve Doctrine EntityRepository objects. We want to be able to use it like so:

// module.config.php
return [
	'service_manager' => [
    	'di' => [
        	'FooService' => [
            	'class' => 'MyApp\FooService',
                'setters' => [
                	'barRepo' => '$repo:MyApp\Entity\Bar'
                ]
            ]
        ]
    ]
];

First we implement the plugin logic:

namespace MyApp\ServiceManager\ConfigPlugin;

use Aeris\ZfDiConfig\ServiceManager\ConfigPlugin\AbstractConfigPlugin;

class DoctrineRepositoryPlugin extends AbstractConfigPlugin {

	public function resolve($pluginConfig) {
    	// Grab the Doctrine EntityManager from the service locator
        $entityManager = $this->serviceLocator->get('entity_manager');
        
        // Return the configured repository
        return $entityManager->get($pluginConfig['entity_class']);
    }
    
    public function configFromString($string) {
    	// Convert a short-form config into an array
        return [
        	'entity_class' => $string;
        ]
    }

}

Now we just need to register the plugin

/// module.config.php
return [
	'zf_di_config' => [
    	'plugins' => [
        	[
            	'class' => 'MyApp\ServiceManager\ConfigPlugin\DoctrineRepositoryPlugin',
                'name' => '$repo',
                'short_name' => '$repo:'
            ]
        ]
    ]
];

And you're ready to go!

aeris/zf-di-config 适用场景与选型建议

aeris/zf-di-config 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.98k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2015 年 05 月 18 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「dependency injection」 「zf2」 「zend framework 2」 「servicemanager」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 aeris/zf-di-config 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 aeris/zf-di-config 我们能提供哪些服务?
定制开发 / 二次开发

基于 aeris/zf-di-config 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3.98k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 21
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 6
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: Unknown
  • 更新时间: 2015-05-18