Marking classes for dependency container injection - php

I am using a modified copy of yadif as my dependency injection framework.
Currently, I have created an abstract class called AContainerAware which is similiar to symfony2's ContainerAware:
abstract class AContainerAware{
protected $_container;
public function setContainer(Container $container){
$this->_container = $container;
}
protected function get($component){
//return a component from $this->_container;
}
}
This works well in most cases. I just have class who require the container to extend AContainerAware, and the container is automatically injected by the DI framework during object creation using setContainer(). I can then easily get components from the container.
The issue is when working with third party vendor packages. In those cases, for example writing an extension for twig requires me to extend the Twig_Extension class, which means I can't extend AContainerAware to get access to the container.
I am considering whether to turn AContainerAware into an interface IContainerAware. Since classes can implement multiple interfaces, IContainerAware should be implementable in most cases. The only issue with this approach is that one cannot write any code for setContainer() and get() in an interface, so it is repetitive to have to implement the exact code for those functions in each class that requires the container. It also poses maintainance issues if setContainer() and get() were to change in the future.
Is there a better way to mark a class for container injection?

You can use PHP traits which were introduced in PHP 5.4.
Traits enable horizontal reuse of code, whereas inheritance is vertical reuse. A class can use multiple traits, whereas you can only inherit one parent class.

Related

php - Dependency injection [duplicate]

I'm building a MVC PHP framework and I wonder which are the best practices to load what I need in my classes, be it other classes or plain configuration.
Till today I've used singletons, registry and lately a dependency injection container.
While many people claim that DI is the way to go, it seems to me like it justs moves the problem of coupling between components into another place.
Singletons introduce global state, registry introduces tight coupling and DI introduces... well, lots of complexity. I am still confused and can't find a proper way to wire my classes each other.
In the meanwhile, I came up with a custom solution. Actually it's not a solution, it just abstracts the implementation of service loading from my code.
I built an abstract class with _load_service and _load_config methods which all the components of my framework extend in order to load other services or configuration.
abstract class Base_Component {
function _load_service($service) {
// could be either
return DI_container::getInstance()->$service;
// or
$class = '\services\\'.$service;
return new $class;
// or other implementation
}
}
The implementation of loading them is now implemented in only one place, the base class, so at least I got rid of code lines like the following into my components:
$database = new Database(Registry::getInstance()->load('db_config'));
or
$database = DI_container::getInstance()->database;
Now if want a database instance I do this
$database = $this->_load_service('database');
and the implementation of service loader, container, registry or whatever can be easily changed in a single class method without having to search through all my code to change calls to whatever container implementation I was using before.
But as I said I'm not even close to sure about what method I will use for loading classes and configuration.
What are your opinions?
Why reinvent the wheel? Use Pimple as your DI container, and learn how to use it from its documentation.
Or, use Silex microframework as a base to create your own framework. It extends Pimple functionality, so you can use dependency injection.
To answer your question, this is how you use a DI without coupling your classes to it:
interface ContainerInterface {
public function getService($service_name);
public function registerService($service_name,Closure $service_definition);
}
class Application {
public function __construct(ContainerInterface $container) {
$this->container= $container;
}
public function run() {
// very simple to use!
$this->container->getService('db')->someDatabaseQuery();
}
}
$c = new My_DI_Container;
// Service definitions could be in a separate file
$c->registerService('db',function() { return new Database('some config'); });
// Then you inject your DI container into the objects that need it
$app = new Application($c);
$app->run(); // or whatever
This way, the DI container is decoupled and in the future you could use a different implementation. The only requirement is that it implements the ContainerInterface.
Note that the container object is being pushed, and not pulled. Avoid using singleton. To get/set single-instance objects, use the container (that's its responsibility). And to get the container instance, just push it through constructors.
Answer to your question; Look at PHP autoloading. Registering classes via autoloading makes it so you don't have to put require/includes everywhere, which really has a positive impact on RAD (rapid application development).
My thoughts:
Kudos for attempting such a daunting task, your approach appears to based on good practices such as singletons and factories.
I don't care for dependency injection. OOP is based on encapsulation, injecting one object into another, imo, breaks that encapsulation. When you inject an object into another object, the target object has to 'trust' that nothing regarding the injected object has changed, otherwise you may get unusual behavior.
Consider name-spacing your classes (not PHP name-spacing, but prefix your framework like Zend does, Zend_), this will help so you can register a namespace, then when a class is called the autoloader will ensure that the proper class is loaded. This is how Zend_Framework works. For specifics check out Zend_Loader_Autoloader. The Symfony framework actually takes this one step further; during the first request it will go through all known locations looking for class files, it will then build out an array of the classes and paths to the files then save the array to a file (file caching), so subsequent requests won't have the same overhead. Something to consider for your framework.
As far as config files go, Symfony uses YAML files, which I have found to be extremely flexible. You can even include PHP code for increased flexibility. Symfony has provided a stand-alone YAML parser that is easy to use. You can increase performance by adding a caching layer and caching parsed YAML files so you don't have to parse the files for every request.
I am assuming you are building your framework on top of an ORM. My recommendation would be not to any functionality specific to a version of the ORM, otherwise your framework becomes coupled with that version and you will have to upgrade both the ORM and the framework at the same time.
I would suggest looking under the hood at other frameworks and see if you can pick the best of each; resulting in a solid, easy to use framework.

How to use dependency injection correctly? Because using methods of injected class creates new dependency

I'm a self-learner, trying to become a good PHP developer and want to fully understand Dependency Injection.
I understand the broad principle, in theory dependency injection makes my classes not have tightly coupled dependencies to other classes.
But I don't understand how this can be fully implemented in practice.
Example using the PHP League Container and an Example Controller:
/***************************************************************************************
* DI Container setup
***************************************************************************************/
$container = new Container();
/***************************************************************************************
* Register Service Providers
***************************************************************************************/
$container->addServiceProvider(new \App\Providers\ConfigProvider);
/***************************************************************************************
* Register Container Class Dependencies
***************************************************************************************/
$container->share('App\Http\Controller')
->withArguments(['config']);
Now in my controller I would receive the injected dependency like this:
class Controller
{
public $config;
function __construct($config)
{
$this->config = $config;
}
function index()
{
$newConfigItem = 'domain.com';
$configDomain = $this->config->setConfig($newConfigItem);
}
}
The Controller is just an example, it could be any class, any type of class like maybe a Serviceprovider, Middleware etc.
This is more a general question regarding the correct handling of dependency injection.
Doesn't using the setConfig() method of the injected Config class creates a new tightly coupled dependency?
Even if I would use the Container to create a new Object, using the container directly in any class just created a dependency to the container method used to register / extend Objects in the Container.
Or do I need an extra layer of PHP classes that somehow wrap my dependencies to use new method names, but even then this extra layer of php classes has then dependencies that need adjusting if I need to switch out libraries/packages/components used.
Where am I going wrong in my thinking?

How do I use Doctrine from within my application, considering modern OOP practices?

Doctrine examples usually make use of Doctrine's $entityManager. Hence, whenever I need to do anything in my app with Doctrine, I need to get the entity manager into my code. But how? .... I can inject it into my class, but still I need to create manager somewhere first. I can also make it use PHP's trait which I put into my class to make it Doctrine-enabled.
What I have done in my OOP code is something like this -- I defined a class DoctrineConnector in its own namespace of DoctrineConnector, and inside the class I have a static function getEntityManager. Inside, I read Doctrine configuration, paths, parameters, and create an $entityManager, and then I return it to the caller.
Whenever I need to read or persist something in my Doctrine-unaware code, I do this:
//Pricing.php
use DoctrineConnector\DoctrineConnector;
class Pricing
{
public function getPricing()
{
$entityManager = DoctrineConnector::getEntityManager();
//further Doctrine code to read DB
}
}
DoctrineConnector is now a dependency of Pricing. Obvious answer may be "inject $entityManager into Pricing". But Pricing is called from another class, and that other class is called from another class, etc so I will have to make essentially every class I call be aware of the ORM variable. I want to avoid that.
Is what I currently have just fine or is there a better way?
How ZF2 module system does it
Out of curiosity I looked into how ZF2 manages Doctrine module and from DoctrineORMModule, it uses ServiceLocator pattern to call the inside of controller. So one of the leading framework module systems is not that far off from my implementation.
Singleton Pattern
Adapted from http://www.phptherightway.com/pages/Design-Patterns.html
namespace ABC;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
class DoctrineConnector
{
private static $instance;
public static function getEntityManager()
{
if (null === static::$instance)
{
// Doctrine Config (from Docs)
include 'config/doctrine-config.php';
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
static::$instance = EntityManager::create($dbParams, $config);
}
return static::$instance;
}
protected function __construct()
{}
private function __clone()
{}
private function __wakeup()
{}
}
//to call
$em = DoctrineConnector::getEntityManager();
//if used later in the code - calls same instance
$em = DoctrineConnector::getEntityManager();
There are a couple of popular ways to get a dependency inside the class.
make the class aware of project environment and let the class locate the dependency (what you did with DoctrineConnector)
use dependency injection (what you are trying to achieve)
In your case, your class now depends on DoctrineConnector and is going to work as long as it can find DoctrineConnector. If you port your class to another project where DoctrineConnector isn't defined, your code isn't going to work.
Normally dependency injection is a decision you make when you start your new project. If you already have a large hierarchy of classes, the injection code will bubble up your hierarchy and there is going to be a lot of work refactoring your code. You might want to think wether you really need that and wether it's going to be worth your time.
If you are writing code for one particular app and have no plans to migrate it to other projects, then you probably don't care about dependency injection. Actually, without injection your code is going to be shorter and easier (faster) to write and understand. On the other hand if you have pieces of code that you want to be independent of the app, you might use dependency injection only for those code segments.
If you haven't injected ORM yet, chances are that the rest of the code is tightly coupled with your app as well, and injecting entityManager isn't going to make your code much more portable.

How to use DI container in reusable library?

I'm building a reusable library in PHP which will be used by multiple in-house applications (some web some not). I use constructor dependency injection mostly for my classes, for example injecting my Repository classes into business logic classes:
namespace \Company\Project\BusinessLogic;
class MyComplexBusinessWorkflow
{
private $_repository;
public function __construct(IMyEntityRepository $repository)
{
$this->_repository = $repository
}
...
}
So with Dice I'd like to have something like this which inject default for the library IMyEntityRepository implementation:
$my_complex_workflow_instance = $dice->create('MyComplexBusinessWorkflow');
instead of:
$my_complex_workflow_instance = new MyComplexBusinessWorkflow(new MyEntityMySQLRepository(new MysqlConnectionWrapper()));
I'm ok with embedding particular DI container library into my library code, but not sure how to manage container instance ($dice in the code above) itself.
Didn't get an answer, so provide my "solution". I've implemented a separate Builder class for instantiating DI container.
Code that will use a library will have a dependency on the particular container, this can be absracted by an interface. Unfortunatelly different DI containers work in different way, so that's not a complete abstraction.
In comments I was pointed to this interesting initiative to unify DI containers in PHP: https://github.com/container-interop/container-interop

Where to load controller dependency classes?

I'm making my own primitive MVC framework with PHP, and I'm wondering where I should load/instantiate corresponding controller dependencies?
In the constructor of each controller (tightly coupled) or inject them (loosely coupled)?
The only part of the latter that I'm not too sure of is for the dependencies to be instantiated on bootstrap level, outside of the MVC paradigm, before being injected. Not every controller uses the exact same dependencies besides the default parent ones. I would have to instantiate them all, which would also create a lot of overhead.
I've seen some existing frameworks do it like $this->load->model('model'); // CodeIgniter in the constructor, but I have no clue on why they're doing it like that.
I would suggest you inject the dependencies, so your controllers are less coupled to your framework. This will make a switch to another framework easier.
About instantiating dependencies: I suggest you use (or implement) a dependency injection container. This container should contain factories that can instantiate services.
In an ideal situation your controllers are services too (meaning they too have factories in the dependency injection container).
This way only the controller you need for a particular request will be instantiated, and therefor only its dependencies are instantiated.
When building you own framework, this means that after the routing phase (when the correct controller is known), the framework should grab that controller from the container. The container itself will make sure all dependencies that are needed will be provided.
Have a look at Pimple for an example of a simple dependency injection container.
PS: That line from CodeIgniter looks a lot like the service locator pattern. This pattern is similar to dependency injection, but does not provide full inversion of control.
Q: Where should i load/instantiate corresponding controller dependencies?
There are multiple ways.
The load and instantiation concepts are basically "before/outside" and "after/inside".
Before and outside means, that you load the file containing a class (which you want to instantiate and pass to the controller), before you load the controller.
But how do you know, what the controller needs, before loading the controller? Uh..
Dependency Description Files
A description file comes into play, describing the wiring between your controller and it's dependencies. In other words, you can see the dependencies of your controller by looking at it's dependency description file. This concept is often used by Dependency Injection tools, which analyze the object and pull the dependencies names out automatically. It's also possible to maintain such a wiring configuration file manually. But it's tedious.
Service Locator
A Service Locator is a instantiation helper for dependencies.
Basically, it contains the same information like a dependency description file, but this time in form of a registry. The link between parts of your application becomes this registry.
Both strategies introduce overhead. It's a trade-off. When you change the perspective and look at things from an application with maybe 500+ classes, then you realize that a dependency injection tool is sometimes worth it.
Manual Injection
via Constructor Injection.
After and inside means, that you load the file containing your controller and then start to care about the dependencies.
At this point the class is not instantiated, yet, but the autoloader might do it's dirty deeds behind the scene. He evaluates the use statements at the top of your controller file. The use statements declare namespaced classes, which the autoloader resolves to actuall files and loads them. You might then start to use these classes as dependencies in your controller. This is probably the easiest way to solve your problem and i strongly suggest looking into the topics autoloading with namespaces and use-statements.
When the class is instantiated, you have the following possiblities:
use might use Setter Injection or Reference Injection to set the dependencies to the object. This requires that your Constructor Dependencies are already solved or your constructor is empty.
It's possible to combine these strategies.
Q: What does this do $this->load->model('model'); // CodeIgniter?
CodeIgniter is a legacy application framework. It was created in times, when namespaced autoloading wasn't available. $this->load is a basic class loading helper. This is the opposite of an "auto"loader, (which surprise, surprise) loads things automatically.
CodeIgniters loader class is used to load various other classes, like libraries or files from the view, helpers, models or user defined stuff. This is again the concept of a registry. Here the registry just knowns where things are in your application layout and resolves them. So $this->load->model('model'); means that the modelfunction must have some piecies of information, about the position of model files in your application.
You provide a model name and the path for the file is constructed by model.
And this is exaclty what it does (except a bit of overhead): https://github.com/EllisLab/CodeIgniter/blob/develop/system/core/Loader.php#L223.
Since I'm a Symfony developer, I can only give you a reference to Symfony.
I think you should do like they are doing in Symfony by thinking about what you need in each
Controller object.
At least, you need :
a Request object
and a Model loader object that gives you every Model you need.
Create a BaseController that implements these few functions and then extend it with custom Controllers.
You can also take a look on Silex : http://silex.sensiolabs.org/ a Micro Framework
Hope it helps.
When do you say "In the constructor" you mean to pass in the conatiner and pull the dependencies from them (in the constructor)?
<?php
class SomeController
{
public function __construct($container)
{
$this->service1 = $contanier->get('service1);
}
//...
}
I advice against that, though simpler and easier you will be coupling your controllers to the container thus using a ServiceLocator instead of truly inversion of control.
If you want your controllers to be easy unit-testable you should use inversion of control:
class SomeController
{
public function __construct($service1)
{
$this->service1 = $service1;
}
//...
}
And you can even create your controller as a service inside the container:
// this uses Pimple notation, I hope you get the point
$container['controller'] = function($c) {
return SomeController($c['service1']);
}
Use proxy services to lazy load them
Also if your controllers needs more than some services and you won't be using all of them you can:
1) Use proxy services in order to lazy load the service only when they are really needed
<?php
class ProxyService
{
/**
* #var Service1Type
*/
private $actualService;
public function __construct()
{
$this->actualService = null;
}
private function initialize()
{
$this->actualService = new Service1(); // This operation may take some time thus we deferred as long as possible
}
private function isInitialized()
{
return $this->actualService === null;
}
public function someActionOnThisService()
{
if (!$this->isInitalized()) {
$this->initalize();
}
$this->actualService->someActionOnThisService();
}
There you have a simple proxy object with lazy loading. You may want to check the fantastic Proxy Manager Library if you want to go that route
2) Split your controller
If your contoller has too many dependencies, you may want to split it.
In fact you may want to read the proposal by Paul M. Jones (lead developer of Aura Framework) about MVC-Refinement, IMHO is a good read even though you may not fully agree with it.
Even if you split your controller in order to reduce the dependencies, lazy loading your dependencies is a good idea (obviously you'll have to check weather if its doable in your context: more work in order to gain more speed).
Maybe you need to define __autoload() function before you try to load the Classes which is not loaded yet. Like:
function __autoload($className) {
require "/path/to/the/class/file/$className.php";
}
My example is very very simple to auto require the file which the class definition is in.
You can also use if-else statement or switch statement in that function to fit your own situations smartly.
The __autoload() function is called when PHP doesn't find the class definition, works for new, class_exists(), call_user_method(), etc, and absolutely for your dependences/parents classes. If there is still no class definition after __autoload() is called, PHP will generate an error.
Or you can use spl_autoload_register() function instead of __autoload() more gracefully.
For more information, you might want to see:
http://php.net/manual/en/function.autoload.php
http://php.net/manual/en/function.spl-autoload-register.php

Categories