Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Zend Framework 2 Cookbook

You're reading from   Zend Framework 2 Cookbook If you are pretty handy with PHP, this book is the perfect way to access and understand the features of Zend Framework 2. You can dip into the recipes as you wish and learn at your own pace.

Arrow left icon
Product type Paperback
Published in Dec 2013
Publisher Packt
ISBN-13 9781849694841
Length 340 pages
Edition 1st Edition
Languages
Arrow right icon
Authors (2):
Arrow left icon
joseph@callaa.rs joseph@callaa.rs
Author Profile Icon joseph@callaa.rs
joseph@callaa.rs
Josephus Callaars Josephus Callaars
Author Profile Icon Josephus Callaars
Josephus Callaars
Arrow right icon
View More author details
Toc

Table of Contents (17) Chapters Close

Zend Framework 2 Cookbook
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
1. Zend Framework 2 Basics FREE CHAPTER 2. Translating and Mail Handling 3. Handling and Decorating Forms 4. Using View 5. Configuring and Using Databases 6. Modules, Models, and Services 7. Handling Authentication 8. Optimizing Performance 9. Catching Bugs Setting up the Essentials Index

Understanding dependency injection


When we talk about the dependency injection, or in short DI, we talk about the simple task of, for example, injecting data in object or methods at initialization when needed by one or other higher up classes, which either modify or dispose off the object after use. The DI is probably the most complex feature in Zend Framework 2 to understand. Unfortunately because DI's over complexity in debugging and performance and the Service Locator (explained in Chapter 6, Modules, Models and Services). However, although it is not the best tool in the shed, we must try to learn it, because when mastered it could prove to be a very powerful tool to create a very maintainable piece of code.

If we come across a situation where it is necessary for us to input a lot of parameters in classes because of objects deeper in the code are dependent on them is probably the most annoying and un-maintainable piece of code that we can find in even the most professional environment. We need to think mainly about objects that are used more than once in an application, and always required to instantiate again.

How to do it…

Let us take a look at the following example and assume that FirstClass is the only class that we will actually need further in the code:

namespace OneNamespace
{
  class FirstClass 
  {
    private $secondClass;
    public function __construct(SecondClass $secondClass)
    {
      $this->secondClass = $secondClass;  
    } 
  }

  class SecondClass 
  {
    private $thirdClass;
    private $vehicle;
    public function __construct(ThirdClass $thirdClass, $vehicle)
    {
      $this->thirdClass = $thirdClass;
      $this->vehicle = $vehicle;
    }
  }
}

namespace AnotherNamespace 
{
  class ThirdClass 
  {
    private $first_name;
    private $last_name;

    public function __construct($first_name, $last_name)
    {
      $this->first_name = $first_name;
      $this->last_name = $last_name;
    }
  }
}

// Let us now create the example through the classic 
// method.
$thirdClass = new AnotherNamespace\ThirdClass("John", "Doe");
$secondClass = new OneNamespace\SecondClass($thirdClass, 
  'Motorcycle');
$firstClass = new OneNamespace\FirstClass($secondClass);

Both the preceding examples give either variables that are only used to instantiate another class and/or add complexity in reading the code. Although they both are correct, the use of DI can, in this case, make the configuration of both the classes much easier.

Initializing the DI at call-time

Let's take a look at this DI example, considering that we have the same classes as the preceding example:

namespace OneNamespace
{
  class FirstClass 
  {
    [..] 
  }

  class SecondClass 
  {
    [..]  
  }
}

namespace AnotherNamespace 
{
  class ThirdClass 
  {
    [..]
  }
}

// Instead of configuring all the classes, we will now 
// simply configure the Di, and only instantiate the 
// class that we want to use.
$di = new \Zend\Di\Di();
$lister = $di->get(
    'OneNamespace\FirstClass',
    array(
        'first_name' => 'Jane',
        'last_name' => 'Doe',
        'vehicle' => 'Car',
    )
);

In the preceding example, we simply say to the DI that AnotherNamespace\ThirdClass has two parameters in its __construct method. The DI will then utilize Reflection to find out what parameters are present there, and will then give any class that has a first_name, vehicle, or last_name parameter in its constructor that parameter.

Of course we will see a potential flaw here, as you might need to utilize multiple instantiations, one can presume that at some point the same parameter name will be used. In our example, it would cause a problem if another class also has a $first_name parameter but requires a different input, as the DI will simply give the one that is in its list.

Tip

If we use DI to instantiate our classes and all we need the constructor for is to set our variables, we can easily remove the constructor altogether as the DI doesn't use the constructor to initialize the variables. Instead the DI will just set the properties of the values.

One good thing about this is that this can flaw only happens when we use the DI at a call-time level, and not in a global configuration level as we will see now. That is why it isn't recommended to use the DI at call-time level at all.

Initializing the DI through a Configuration object

What we also can do to create a more specific (or accurate) initialization of our object – and to make sure classes with the same property names don't conflict – is initializing the DI with a configuration object.

The idea behind this is that we first create a configuration object (or array) that defines which classes need which properties set, and then use that to initialize the DI, which in its turn finds out when it needs to initiate what.

Take a look at the following example, which shows you the exact thing we just explained:

<?php
// We are assuming that we are using the same classes as 
// in the previously shown examples.
namespace OneNamespace 
{
  class FirstClass 
  {
    [..] 
  }

  class SecondClass 
  {
    [..]  
  }
}

namespace AnotherNamespace 
{
  class ThirdClass 
  {
    [..]
  }
}

// After defining our classes we now begin to create our 
// configuration array which we will use to initialize 
// the DI.
$configuration = array(

  // We want to use this specific configuration at 
  // initialization of our class.
  'instance' => array(
    
    // We specify the class name to use here
    'SecondClass' => array(
       
      // We want to use this as a parameter
      'parameters' => array(

        // The property name to fill is vehicle.
        'vehicle' => 'Airplane'
      ),
    ),

    'FirstClass' => array(
      // Again we want to use this as a parameter
      'parameters' => array(

        // The property name to fill is first name and 
        //last name.
        'first_name' => 'Neil',
        'last_name' => 'deGrasse Tyson',
      ),
    ),
  ),
);

// We want to instantiate the Di\Configuration now.
use \Zend\Di\Configuration; 

$diConfiguration = new Configuration($configuration);

// Now instantiate the Di itself, with the configuration 
// attached.
$di = new \Zend\Di\Di($configuration);

// And to get the object we want to use, we just do the 
//same as before.
$firstClass = $di->get('OneNamespace\FirstClass');

To make everything even nicer, we would just put the Zend\Di\Configuration of the DI in the bootstrap of our module, so that we can use it easily throughout the namespace. This way we can simply put the configuration of the DI in our module.config.php and let the framework take care of it.

How it works…

The DI or dependency injector is an important, and most of the time overlooked feature of Zend Framework 2. The DI makes our lives a lot easier by automatically finding the classes we need in our application.

With all its complexity however, comes a couple of features we should be wary of.

The DI only gives out one instance of an object

This means that every get() call will result in the same instantiation over and over again. If we would like a new instance, we would need to call newInstance() as the DI implements the singleton pattern, which means that all the data persists every time we call the get() method unless we force a new instance of the DI.

Defining either all properties, or using a Fully Qualified (FQ) setter parameter

When our class has more properties than we define, we will find out that the DI will use the last value for every other property in the class. Of course this is unwanted, and if we wrote the class ourselves we should consider refactoring the configuration and/or class.

However, when there is no other way we can define the right properties only by using a Fully Qualified (FQ) setter parameter.

In our configuration we would then define a very specific property name, for example, class::method:paramPos. If we take our ThirdClass example from earlier on, this would then be ThirdClass::setFirstName:0 and ThirdClass::setLastName:0 respectively.

There's more…

There is loads more we can learn about the DI in Zend Framework 2. The following list provides a very short and compact description of other interesting DI components:

  • RuntimeDefinition (default), CompilerDefinition and ClassDefinition: These definitions are used to determine how to configure our objects. Although the default one usually does the job, it can't hurt to see what the other two Definitions do, because they all have their pros and cons.

  • InstanceManager: Used to define the configuration, specifically the Aliases, Parameters and Preferences.

You have been reading a chapter from
Zend Framework 2 Cookbook
Published in: Dec 2013
Publisher: Packt
ISBN-13: 9781849694841
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image