I'm trying to figure out the best practices for dependency injection in PHP.
Question: Do I have to inject all dependencies of a subclass into the parent class? I use the terms 'parent' and 'child' in terms of a composition relationship.
My hesitation is because I find myself giving the parent class all kinds of dependencies so that it can just pass them down to dependent child classes.
Edit:
Below is a more concrete example of what I'm talking about. MyClassA does not need the database connection object or the logger. DoSomething does need these objects, however. What is the best way to get the database connection and logger to the DoSomething instance? I don't want to use singleton objects or global objects for the sake of unit testing. Also, this example only uses to classes. What if there are 3 or 4 and the 3rd or 4th needs some object instance but the first 2 or 3 don't? Does MyClassA just pass the object to the next, and so on?
class MyClassA {
protected $_doSomethingObject;
public function doSomething()
{
return $this->_doSomethingObject()->doSomethingElse();
}
public function setDoSomethingObject($doSomethingObject)
{
$this->_doSomethingObject = $doSomethingObject;
}
}
class DoSomething {
protected $_logger;
protected $_db;
public function doSomethingElse()
{
$this->_logger->info('Doing Something');
$result = $this->_db->getSomeDataById();
return $results;
}
public function setLogger($logger)
{
$this->_logger = $logger;
}
public function setDBConection($db)
{
$this->_db = $db;
}
}
Is the best way the example I show below? If so, then the best way is to work backwards so to speak...?
$logger = new Logger();
$db = new DBConnection();
$doSomething = new DoSomething();
$doSomething->setLogger($logger);
$doSomething->setDBConnection($db);
$a = new MyClassA();
$a->setDoSomething($doSomething);
If so, then the best way is to work backwards so to speak...?
Yes. As I mentioned in the comment, you set up the inner most objects first.
If an object create another object internally that isn't exposed, then it could pass along its injected objects if appropriate. For example:
class DoSomething {
// ...
public function foo() {
$foo = new Foo();
$foo->setLogger($this->_logger);
return $foo->bar();
}
}
However, if that secret Foo object needed references to other things that DoSomething didn't have, then you've got design issues. If that happens you need to do whatever is appropriate:
Inject a foo object into the parent object prior to calling foo().
Inject that dependency into the parent object prior to calling foo().
Add the dependency as a function argument.
Refactor code into a better design that doesn't create that problem.
You need only include the dependancies in the classes that are going to directly need them. Since the required/included files will be loaded whenever the base class loads, they will automatically be available to any child classes.
Related
Can we create an object of a class inside another class in php?I hav made a small application in php,now I am trying to convert the entire code in a class-methods-object fashion.I m now Confused.
You you can do that, but whether you should depends on the lifetime of the two classes and their relation to each other. Basically, you have the choice between Composition and Aggregation.
Composition
You use Composition when the created object has a lifetime equal or less than the object that will use it, e.g.
class A
{
private $belongsToAOnly;
public function __construct()
{
$this->belongsToAOnly = new IBelongToA;
}
}
In this case A "owns" IBelongToA. When A is destroyed, IBelongToA is destroyed too. It cannot live on it's own and is likely just an implementation detail of A. It could be a ValueObject like Money or some other Data Type.
From Craig Larman's "Applying UML and Patterns":
the composite is responsible for creation and deletion of it's parts - either by itself creating/deleting the parts, or by collaborating with other objects. Related to this constraint is that if the composite is destroyed, its parts must be destroyed, or attached to another composite"
Aggregation
You use Aggregation when the lifetime of the created object is longer:
class A
{
private $dbAdapter;
public function __construct(DbAdapter $dbAdapter)
{
$this->dbAdapter = $dbAdapter;
}
}
Unlike with Composition, there is no implication of ownership here. A uses DbAdapter but when A is destroyed DBAdapter lives on. It's a "uses" relationship instead of an "owns" relationship.
Creator Pattern (GRASP)
A good heuristic to decide when an object may create another object at runtime can be found in the Creator Pattern in GRASP which states that objects may create other objects when
Instances of B contains or compositely aggregates instances of A
Instances of B record instances of A
Instances of B closely use instances of A
Instances of B have the initializing information for instances of A and pass it on creation.
Alternatively, you can create Factories whenever you need to create instances of something and aggregate the factory instances, which will give you a cleaner separation of collaborators and creators.
Testability
An issue stemming from creating objects within objects is that they are difficult to test. When you do unit-testing, you usually do not want to recreate and bootstrap the entire system environment but concentrate on testing just that particular class in isolation. To do that, you swap out dependencies of that class with Mock Objects. You cannot do that when you use Composition.
So depending on what the collaborators of a class do, you might want to decide to always use Aggregation, because then you are effectively doing Dependency Injection all the way, which will allow you to swap out collaborators of a class easily, for instance to replace them with Mocks.
Yes you can, but that increases code coupling and makes testing harder.
I'd suggest creating it outside the class and pass it as an argument (it is called Dependency Injection).
class Foo
{
}
class Bar
{
public function __construct(Foo $foo)
{
$this->foo = $foo;
}
}
$foo = new Foo();
$bar = new Bar($foo);
yes you can do it ..
here is one example..
a.php
<?php
class a{
public function function_1(){
echo "b";
}
}
?>
b.php
<?php
include_once ("a.php");
class b{
public function function_b(){
$a = new a;
$a->function_1();
}
}
$b= new b;
$b->function_b();
?>
Yes, you can create an object from a specific class from inside another class.
class SomeClass{
}
class SomeOtherClass {
function hello(){
$o = new SomeClass;
}
}
Yes, you can also define a function in a class. You can do everything in a class in php, please post your code where you confused.
Examples:
Object in a class.
class Foo
{
public $bar; // another object!
public __construct()
{
$this->bar = new Bar();
}
}
(global)Function in a class
<?php
class Foo
{
public function __construct()
{
function __construct()
{
echo "Yes, I'm a global function!";
}
}
}
new Foo();
__construct();
?>
I'm trying to get my head around Dependency Injection and I understand it, for the most part.
However, say if, for some reason, one of my classes was dependent on several classes, instead of passing all of these to this one class in the constructor, is there a better, more sensible method?
I've heard about DI Containers, is this how I would go about solving this problem? Where should I start with this solution? Do I pass the dependencies to my DIC, and then pass this to the class that needs these dependencies?
Any help that would point me in the right direction would be fantastic.
Dependency Injection !== DIC
People should really stop confusing them. Dependency Injection is idea that comes from Dependency Inversion principle.
The DIC is "magic cure", which promises to let you use dependency injection, but in PHP is usually implemented by breaking every other principle of object oriented programming. The worst implementations tend to also attach it all to global state, via static Registry or Singleton.
Anyway, if your class depends on too many other classes, then in general , it signifies a design flaw in the class itself. You basically have a class with too many reasons to change, thus, breaking the Single Responsibility principle.
In this case, then dependency injection container will only hide the underlaying design issues.
If you want to learn more about Dependency Injection, i would recommend for you to watch the "Clean Code Talks" on youtube:
The Clean Code Talks - Don't Look For Things!
The Clean Code Talks - "Global State and Singletons"
If you have several dependencies to deal with, then yes a DI container can be the solution.
The DI container can be an object or array constructed of the various dependent object you need, which gets passed to the constructor and unpacked.
Suppose you needed a config object, a database connection, and a client info object passed to each of your classes. You can create an array which holds them:
// Assume each is created or accessed as a singleton, however needed...
// This may be created globally at the top of your script, and passed into each newly
// instantiated class
$di_container = array(
'config' = new Config(),
'db' = new DB($user, $pass, $db, $whatever),
'client' = new ClientInfo($clientid)
);
And your class constructors accept the DI container as a parameter:
class SomeClass {
private $config;
private $db;
private $client;
public function __construct(&$di_container) {
$this->config = $di_container['config'];
$this->db = $di_container['db'];
$this->client = $di_container['client'];
}
}
Instead of an array as I did above (which is simple), you might also create the DI container as an class itself and instantiate it with the component classes injected into it individually. One benefit to using an object instead of an array is that by default it will be passed by reference into the classes using it, while an array is passed by value (though objects inside the array are still references).
Edit
There are some ways in which an object is more flexible than an array, although more complicated to code initially.
The container object may also create/instantiate the contained classes in its constructor as well (rather than creating them outside and passing them in). This can save you some coding on each script that uses it, as you only need to instantiate one object (which itself instantiates several others).
Class DIContainer {
public $config;
public $db;
public $client;
// The DI container can build its own member objects
public function __construct($params....) {
$this->config = new Config();
// These vars might be passed in the constructor, or could be constants, or something else
$this->db = new DB($user, $pass, $db, $whatever);
// Same here - the var may come from the constructor, $_SESSION, or somewhere else
$this->client = new ClientInfo($clientid);
}
}
I've wrote an article about this problem.
The ideea is to use a combination of abstract factory and dependency injection to achieve transparent dependency resolving of (possible nested) dependencies. I will copy/paste here the main code snippets:
namespace Gica\Interfaces\Dependency;
interface AbstractFactory
{
public function createObject($objectClass, $constructorArguments = []);
}
The abstract factory implementation is:
namespace Gica\Dependency;
class AbstractFactory implements \Gica\Interfaces\Dependency\AbstractFactory, \Gica\Interfaces\Dependency\WithDependencyInjector
{
use WithDependencyInjector;
/**
* #param string $objectClass
* #param array $constructorArguments
* #return object instanceof $class
*/
public function createObject($objectClass, $constructorArguments = [])
{
$instance = new $objectClass(...$constructorArguments);
$this->getDependencyInjector()->resolveDependencies($instance);
return $instance;
}
}
The dependency injector is this:
namespace Gica\Dependency;
class DependencyInjector implements \Gica\Interfaces\Dependency\DependencyInjector
{
use \Gica\Traits\WithDependencyContainer;
public function resolveDependencies($instance)
{
$sm = $this->getDependencyInjectionContainer();
if ($instance instanceof \Gica\Interfaces\WithAuthenticator) {
$instance->setAuthenticator($sm->get(\Gica\Interfaces\Authentication\Authenticator::class));
}
if ($instance instanceof \Gica\Interfaces\WithPdo) {
$instance->setPdo($sm->get(\Gica\SqlQuery\Connection::class));
}
if ($instance instanceof \Gica\Interfaces\Dependency\WithAbstractFactory) {
$instance->setAbstractFactory($sm->get(\Gica\Interfaces\Dependency\AbstractFactory::class));
}
//... all the dependency declaring interfaces go below
}
}
The dependency container is the standard one.
The client code could look something like this:
$abstractFactory = $container->get(\Gica\Interfaces\Dependency\AbstractFactory::class);
$someHelper = $abstractFactory->createObject(\Web\Helper\SomeHelper::class);
echo $someHelper->helpAction();
Notice that dependencies are hidden, and we can focus on the main bussiness. My client code doesn't care or know that $someHelper need an Authenticator or that helpAction need an SomeObject to do its work;
In the background a lot of things happen, a lot of dependencies are detected, resolved and injected.
Notice that I don't use the new operator to create $someObject. The responsability of actual creation of the object is passed to the AbstractFactory
P.S. Gica is my nickname :)
I recommend you to use Singltones or Mutlitones. In these cases you will be always able to get objects via static class' methods.
The other way (couldn't find a correct pattern name, but it could be Registry) is to use one global static object to store multiple objects' instances. E.g. (simplified code, without any checks):
class Registry {
private static $instances = array();
public static function add($k, $v) {
$this->instances[$k] = $v;
}
public static function get($k) {
return $this->instances[$k];
}
}
class MyClass {
public function __construct() {
Registry::add('myclass', $this);
}
}
To be clear, I don't want to instantiate the same class multiple times. I only want to instantiate it once, and keep track of any changes made to that instance via some reference. Is this possible, and if so how can it be done? Thanks!
You can use the Singleton pattern for this. The PHP manual has a good example and description:
The Singleton ensures that there can be only one instance of a Class and provides a global access point to that instance.
Class:
<?php
class Example
{
private static $instance;
private function __construct() {
}
public static function singleton() {
if (!isset(self::$instance)) {
echo 'Creating new instance.';
$className = __CLASS__;
self::$instance = new $className;
}
return self::$instance;
}
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Unserializing is not allowed.', E_USER_ERROR);
}
}
Usage:
$singleton = Example::singleton();
It is worth also noting these objections to the singleton pattern from the PHP manual:
The Singleton pattern is one of the more controversial patterns. Critics argue that
Singletons introduce Global State into an application and tightly
couple the Singleton and its consuming classes. This leads to hidden
dependencies and unexpected side-effects, which in turn leads to code
that is harder to test and maintain.
Critics further argue that it is pointless to use a Singleton in a
Shared Nothing Architecture like PHP where objects are unique within
the Request only anyways. It is easier and cleaner to create
collaborator object graphs by using Builders and Factory patterns once
at the beginning of the Request.
Singletons also violate several of the "SOLID" OOP design principles
and the Law of Demeter. Singletons cannot be serialized. They cannot
be subtyped (before PHP 5.3) and won't be Garbage Collected because of
the instance being stored as a static attribute of the Singleton.
See as well: Who needs singletons?
You can create Singleton pattern
class Something {
private static $instance;
private function __construct() {
}
public static function getInstance() {
if(Something::$instance == null) {
Something::$instance = new Something();
}
return Something::$instance;
}
public function someMethod() {
return "abc";
}
}
When you want to use it you call Something::getInstance()->someMethod()
Read more about singleton pattern.
To be clear, I don't want to instantiate the same class multiple times. I only want to instantiate it once, and keep track of any changes made to that instance via some reference. Is this possible, and if so how can it be done? Thanks!
Sure this is possible. You can do this literally:
First of all, as you don't want to instantiate the class multiple times, just instantiate it once:
$instance = new Class();
Then you want to keep track of changes made to that instance. I don't specifically know what you mean. Probably you mean to only keep that one instance. You just can do so, as you have only instantiated once, you can refer to that instance with the $instance variable.
Additionally you can "reference" that $instance as well in some other variable:
$reference = $instance;
You can now access the single instance of Class with the $instance and the $reference variable.
If you need to monitor the instance, I suggest you create a Decorator that does the job:
$decorator = new ClassDecorator(new Class());
The decorator can then work as an interceptor before anything reaches Class.
To find out if the inner state of a class has changed or not, you can make use of the serialize and unserialize functions as well:
$instance = new Class();
$snapshot = serialize($instance);
...
# more code, $instance is changed or not, we don't know
...
$changed = $snapshot != serialize($instance);
Hope this is helpful.
What you are trying to do is called the Singleton Pattern .. See http://en.wikipedia.org/wiki/Singleton_pattern
This article is similar to my needs, but I'm more curious about a specific solution to it, and if it's a good or bad idea to do it. Sharing objects between PHP classes
Say, like in the link above, I have an object I want to pass to multiple classes, say a $db object.
Instead of using dependency injection and passing it to each method's constructor, is it ever a good idea to let all the classes extend a Base class, that stores the $db object as a property?
For example:
abstract class Base {
protected static $_db;
public function setDatabase( Database $db ) {
$this->_db = $db;
}
public function getDatabase() {
return $this->_db;
}
}
class SomeClass extends Base {
public function doStuff() {
$result = $this->getDatabase()->query(.....);
}
}
Which would mean all classes that extend Base need not worry about grabbing/checking/setting the $db themselves, as they'd already have that object as a property as soon as the class is defined.
I know dependency injection is the usual way to go, but is this ever a viable solution?
Thanks!
You still have to set the db on each instance of the class - setting it on one instance doesnt set it on all instances... unless of course its a static property.
That is perfectly fine. I have used it before and never ran into any issues.
An ethical question here.
I'm planning on using several manager classes in my new project that will be performing various tasks across the whole project. These classes are singletons, but require construction based on parameters.
As to when/where this construction has to happen, I have mixed feelings. I have these options so far:
Option A
It's easy to just pass these parameters to the getInstance method while having a default null value. On the very first call the parameters will be used, and any additional calls completely ignore them.
While this works, doing so feels rather unlogical, for the following reasons:
It makes documentation unclear. getInstance' first parameter must be of type Collection, but can be null... what's going on here?
You can argue that writing a line about this in the description will clear it up, but I'd prefer clarification to be unneccesary.
It feels faulty to pass getInstance any construction parameters. This is due to the fact that the method name does not explicity hint towards construction, making it unclear it will happen.
Option B
I'm thinking about a setup method. This method takes all parameters, calls the class constructor, and changes the internal class state to initialized.
When calling the getInstance method prior to setup, it will throw a NotInitializedException. After setup has been called, any additional calls to setup will result in a PreviouslyInitializedException.
After setup has been called, getInstance becomes available.
Personally, this option appeals more to me. But it feels excessive.
What option do you prefer? And why?
I would probably try and ditch the singleton approach and pass manager classes around to whatever needs them.
$manager = new Manager( $collection, $var, $var2 );
$other_class = New OtherClass( $manager );
//or
$other_class = New OtherClass;
$other_class->manager = $manager;
//or
$other_class = New OtherClass;
$other_class->setManager( $manager );
Use dependency injection to pass the Manager object around. Don't use Singleton pattern. It's a common consensus that using it creates a global state and makes your API deceptive.
PHP Global in functions (jump to answer)
Singletons are pathological liars
Inject the Manager instance to any class that needs it via the constructor. Each class should not try to instantiate Manager by themselves, the only way the classes get an instance of the Manager is by getting it from constructor.
class NeedsManager
{
protected $manager;
public function __construct(Manager $manager)
{
$this->manager = $manager;
}
}
You don't need to enforce one instance of Manager. Just don't instantiate it more than once. If all of your classes that need an instance of Manager get what they need from the constructor and never tries to instantiate it on their own, it will assure that there's just going to be one instance in your application.
How about option 3. If they are true singletons, set up properties files for their parameters for use with a no-arg getInstance.
If that doesn't fit, you might be misusing the singleton pattern.
You are looking at using a Factory design pattern. Factories are objects that act as fancy constructors for other objects. In your case, you will move setup and getInstance to the factory. The wiki article's pretty good- http://en.wikipedia.org/wiki/Factory_method_pattern
class SingletonFoo {
//properties, etc
static $singleton = NULL;
private function __constructor(){}
static function getInstance(){
if(NULL === self::$singleton) {
self::$singleton = new SingletonFoo();
}
return self::$singleton;
}
}
class FooFactory {
static $SingletonFoo = null;
static function setup($args){
if( !(NULL === self::$SingletonFoo)){
throw new AlreadyInstantiatedException();
}
self::$SingletonFoo = SingletonFoo::getInstance();
//Do stuff with $args to build SingletonFoo
return self::$SingletonFoo;
}
static function getInstance(){
if(NULL === self::$SingletonFoo) {
throw new NotInstantiatedException();
}
return self::$SingletonFoo;
}
}
Don't use Singleton, use Resources Manager (or Service Container, or DI Container):
class ResourceManager
{
protected static $resource;
public static function setResource($resource)
{
if (!empty(self::$resource)) //resource should not be overwritten
{
if ($resource!=self::$resource) return false;
else return true;
}
self::$resource = $resource;
return true;
}
public static function getResource()
{
return self::$resource;
}
}
Resource Manager allows you to set any custom classes for unit-testing (like dependency injection), you can just get needed resources without requesting them in constructor (I like DI, but sometimes it's just more handy to use empty constructors).
Ready-to-use variant: http://symfony.com/doc/current/book/service_container.html (I don't like to move logic from code to configs, but in stand-alone module it looks acceptable).