diepartments-pimcore-plugin / dependency-injection
A Pimcore plugin enabling dependency injection
Installs: 1 756
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 3
Forks: 0
Open Issues: 0
Type:pimcore-plugin
Requires
- php: >=5.4.0
- doctrine/annotations: ~1.2
- doctrine/cache: ^1.6
- ocramius/proxy-manager: ~1.0
- php-di/php-di: ^5.2.0
- pimcore/installer-plugin: >=1
This package is not auto-updated.
Last update: 2024-11-09 19:45:55 UTC
README
Plugin for using the dependency injection software design pattern in Pimcore projects. It uses the amazing PHP-DI dependency injection container and enables you to use all of its injection options.
Basic Usage
class SomeController extends Action { /** * This service object gets injected automatically without any further config. * Important thing is that you add the @Inject annotation as well as the objects type (class) * * @Inject * @var \Website\Service\SomeService */ private $someService; public function indexAction() { // just use the service anywhere in your controller $this->view->some = $this->someService->doSomething(); } }
Installation
Add the following line to the require
section of your composer.json
"diepartments-pimcore-plugin/dependency-injection": "dev-master"
Run composer install
from your commandline and enable the plugin in the Pimcore Extension Manager afterwards.
For more information about how to use extensions via composer, take a look at the documentation
Advanced Usage
You can use all injection options provided by PHP-DI. The Plugins installer creates all necessary configuration files for you.
They are located at /website/var/plugins/dependency-injection
Put your service configurations in container.php
and your parameters in parameters.php
.
You can also create environment specific definitions, to override defaults. Simply create a container.ENV.php
file and put your env specific services configuration in it.
Replace ENV
by the environment you want to create specific config for, e.g. development
The Pimcore System environment.
Example
Lets configure a shopping cart. The cart should use an external system, like an ERP, to calculate shipping costs or customer specific prices. Therefore it needs a Gateway which knows how to communicate with the external System. The Gateway itself needs to know the api path its calling.
Example container.php
<?php use Website\Service\Cart as CartService; use Website\Gateway\CartInterface as CartGatewayInterface; use Website\Gateway\Cart as CartGateway; return [ // Configure the base path to our external system. Can easily be overridden e.g in container.development.php for dev environment 'api.root' => 'http://somehost/api', // Configure the Gateway for our Cart. // For this example we will create the gateway using a simple factory. Factories can have their own class for more flexibility. CartGatewayInterface::class => function() { // The factory method could create the correct instance depending on the env or any other config. // This might be helpful to create a mock gateway while in development. // For the sake of this example, we simple create the gateway and set the correct api path, based on the root api key return new CartGateway(DI\string('{api.root}/cart')); } // Configure the cart, giving it a gateway identified by the interface class 'cart' => DI\object(CartService::class) ->constructor(DI\get(CartGatewayInterface::class)) // give the service a gateway ->lazy() // make it lazy as most likely not every request needs the cart service so it only gets initialized when its needed ];
Then use the cart Service in your Controller by using Annotation with the configured container key. This also works for parameters.
class CartController extends Action { /** * @Inject("cart") * @var Cart */ protected $cart; public function someAction() { // just use your service $this->cart->someCartMethod(); } }
Learn more about the different options at http://php-di.org/doc/definition.html.
Best Practise
Use lazy injection for every service which will not be used in every request.
Accessing the Container
Built in Controller Action Helper
You can use the built in helper in your Controller to access the container at any time. This allows you to get configured container entries on demand. Be aware that you should couple your application to the container as less as possible, otherwise you loose portability. This in mind, use the action helper only if you have to.
Action Helper example usage
class MyController extends Action { public function someAction() { // get a container entry when needed $from = $this->_helper->DI->get('mail.default_sender'); } }
Zend Registry
The Container gets added to the registry and can be retrieved from there like in this example:
/** @var Interop\Container\ContainerInterface $container */ $container = \Zend_Registry::get(DependencyInjection\Plugin::CONTAINER_REGISTRY_KEY);
Event Hook
You can access the container after its initialization utilizing Pimcores Event System
\Pimcore::getEventManager()->attach(\DependencyInjection\Plugin::CONTAINER_INITIALIZED_EVENT, function(\Zend_EventManager_Event $e) { /** @var Interop\Container\ContainerInterface $container */ $container = $e->getTarget(); // access your defined services $someService = $container->get('service.key'); });
Extending the Container
You can extend the container, e.g. to add a additional definitions.php file, using Pimcores Event System. Therefore you have to attach a Listener in your own Plugin or startup.php like in the example below.
// attach a event handler to extend the container \Pimcore::getEventManager()->attach(DependencyInjection\Plugin::CONTAINER_INIT_EVENT, function(\Zend_EventManager_Event $e) { /** @var Interop\Container\ContainerInterface $container */ $container = $e->getTarget(); // add more definitions, may be from a vendor bundle or from another dir. $container->addDefinitions('path/to/definitions.php'); });
Please note that the container will be built after the mentioned event was fired and can not be extended anymore. This is due to performance optimization.
Plugin Configuration
Configuration file is located at
/plugins/dependency-injection/config.xml
This file can be edited directly by clicking on the configure
button in the Extension Manager
Configuration Options
Cache Proxies
If true
generated proxy classes for lazy injection will be written and read from file.
Defaults to true
Use definition files
Set to false
if you wont use php definition files
Defaults to true
Cache
Configure the cache driver used for annotation caching. Supported cached types are:
- Redis
- Memcached
- Apcu
- File (Default)
Some Types require additional parameters like host and port of the Cache Backend.
You have to provide them in the options
part of the cache config.
Example config.xml
<?xml version="1.0"?> <zend-config xmlns:zf="http://framework.zend.com/xml/zend-config-xml/1.0/"> <!-- cache generated proxy classes for lazy injection (should be enabled if using lazy injections) --> <cache-proxies>true</cache-proxies> <!-- whether to load definition files or not <use-definition-files>true</use-definition-files> <!-- annotation cache settings --> <cache> <!-- the cache driver to be used --> <type>redis</type> <!-- namespace for cache entries (otional) --> <namespace>MyApp</namespace> <!-- cache driver options, depends on driver type --> <options> <host>localhost</host> <port>6379</port> </options> </cache> </zend-config>
The Cache is only activated for production
environment.