Category Archives: Zend Framework 2

Handling ZF2 FQ Dependency Setter Injections

In a previous article I showed how you could pass in a fully qualified parameter name into the Dependency Injection Container (DiC) if you needed to be specific about where you need to have something injected.  There is an alternate method here that is cleaner than what I did before.  Let’s start with a Test class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test
{
  protected $test;
 
  public function setTest($test)
  {
    $this->test = $test;
  }
 
  public function getTest()
  {
    return $this->test;
  }
}

The way I did it in the previous example was by defining the fully qualified parameter name by doing this.

1
2
3
4
5
6
7
8
9
$config = array(
  'instance' => array(
    'Test' => array( // Class name
      'parameters' => array(
        'Test::setTest:0' => 'some data';
      )
    )
  )
);

Which is fine until you you have

1
2
3
4
5
6
7
8
9
$config = array(
  'instance' => array(
    'FriggingLongNamespacedClass' => array( // Class name
      'parameters' => array(
        'FriggingLongNamespacedClass::setFriggingLongNamespacedClassMethod:0' => 'some data';
      )
    )
  )
);

It can get a little convoluted, plus I’m not entirely convinced that’s the best way of doing it.  Parameters seem to be more useful for doing constructor injection.  A better method for setters seems to be through the use of injectors.  Let’s take at an injector configuration.

1
2
3
4
5
6
7
8
9
10
11
$config = array(
  'instance' => array(
    'Test' => array( // Class name
      'injections' => array(
        'setTest' => array(
          array('test' => 'somedata')
        )
      )
    )
  )
);

Basically, rather an using the “parameter” key use “injections” and specify an array of injection methods.  Each of those methods needs an associative array of parameter names as the key with the values as the value.  Injectors seem to be much nicer and cleaner than my previous way of doing the fully qualified parameter.

ZF2 Dependency Injection – Multiple Object Instances

When you work with the ZF2 Dependency Injection Container (DiC) when you make multiple requests for an instance of an object you will get the same object back each time.

For example, with this code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Test
{
  protected $test;
 
  public function __construct($test)
  {
    $this->test = $test;
  }
 
  public function getTest()
  {
    return $this->test;
  }
}
 
use Zend\Di\Di;
$di = new Di();
 
$test = $di->get('Test', array('test' => 'some data'));
var_dump($test);
$test2 = $di->get('Test', array('test' => 'some data'));
var_dump($test2);

You will get the following output

1
2
3
4
5
6
7
8
object(Test)#9 (1) {
["test":protected]=>
string(9) "some data"
}
object(Test)#9 (1) {
["test":protected]=>
string(9) "some data"
}

If you provide a different parameter you will get a different object.

1
2
3
4
$test = $di->get('Test', array('test' => 'some data'));
var_dump($test);
$test2 = $di->get('Test', array('test' => 'some other data'));
var_dump($test2);

Produces

1
2
3
4
5
6
7
8
object(Test)#9 (1) {
["test":protected]=>
string(9) "some data"
}
object(Test)#11 (1) {
["test":protected]=>
string(15) "some other data"
}

From this we can conclude that when you are using the DiC that if you request a like object with like parameters you will get the same instance of the object.

But what if you want the injection benefits of the DiC but don’t want to share the object?  Use the DiC’s newInstance method instead with the third parameter being false.  This tells the DiC container to refrain from putting it in the shared object pool.  The get() method does not give you the option of retrieving a non-shared instance and so you will need to call the newInstance() method directly.

1
2
3
4
5
$test = $di->get('Test', array('test' => 'some data'));
var_dump($test);
 
$test2 = $di->newInstance('Test', array('test' => 'some data'), false);
var_dump($test2);

prints out

1
2
3
4
5
6
7
8
object(Test)#9 (1) {
["test":protected]=>
string(9) "some data"
}
object(Test)#11 (1) {
["test":protected]=>
string(9) "some data"
}

 

ZF2 Dependency Injection: Managing Configuration – Part 2

In my previous post about Dependency Injection Container (DiC) configuration I made mention of some more complicated scenarios that you can use to configure your objects.  Not that you need help to make it  more complicated.  One of the things I have observed is that the more familiar I am with the DiC the more complicated the configuration gets.  This is both good and bad.  It’s good because you start understanding how and why all of those frigging long example DI configuration arrays are like that.  The bad is that  long DiC configuration arrays greatly reduce the ability of a new developer to start being productive.  That’s why I think this series of blog posts are good.  They show you how to get started small which is really the only way to get started if you aren’t intimately familiar with a DiC.

Let’s take our Test class and change its behavior by adding a method that allows you to set some test data (use your imagination here before complaining in the comments that it’s not a real world example).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Test
  {
  protected $test;
  protected $data;
 
  public function setTestData($test)
  {
    $this->data = $test;
  }
 
  public function getTestData()
  {
    return $this->data;
  }
 
  public function setTest($test)
  {
    $this->test = $test;
  }
 
  public function getTest()
  {
    return $this->test;
  }
}

We dutifully set up our DiC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$config = array(
  'instance' => array(
    'Test' => array( // Class name
      'parameters' => array(
        'test' => 'some data'
      )
    )
  )
);
 
use Zend\Di\Configuration;
 
$diConfig = new Configuration($config);
$di = new Di();
$diConfig->configure($di);

And we run our test code getting our ‘some data’ parameter, right?

1
string(9) "some data"

Yep.  Hmm, but what about getTestData()?

1
var_dump($test->getTestData());

echos

1
string(9) "some data"

Hmm, that shouldn’t be happening.  We did’t tell the DiC that we wanted to inject data there, did we?  It looks like it’s injecting data into both setter methods.  But why?

Look at the names of the parameters for both setters.  They are both named “test”.  The DiC will find the first method with a matching parameter name and inject the value there (if it couldn’t find it in the constructor) .  You have a couple of options to fix this.  If it’s your own code and you don’t mind refactoring, refactor it.  However, if it’s third party code that you shouldn’t touch or code that other parts of the system are dependent on, you have a problem.

But to get around the problem you can specify the setter parameter as a fully qualified (FQ) parameter (I show another , probably better, method here).  The format is “class::method:paramPos”.  In this example it would be “Test::setTest:0″.  So let’s change our DI configuration.

1
2
3
4
5
6
7
8
9
$config = array(
  'instance' => array(
    'Test' => array( // Class name
      'parameters' => array(
        'Test::setTest:0' => 'some data'
      )
    )
  )
);

And now check the return values of both getters.

1
2
3
$test = $di->get('Test');
var_dump($test->getTest());
var_dump($test->getTestData());

Now we get

1
2
string(9) "some data"
NULL

Works.

ZF2 Dependency Injection: Managing Configuration – Part 1

Configuration is a big reason to use a Dependency Injection Container (DiC).  I’ve been doing a lot of playing around with the ZF2 DiC and one of the things that I like about it is the ability to retrieve fully configured objects in  one line of code.  I’ve been going a bit overboard lately but there’s a lot of stuff you can do that can just be downright complex to handle on your own, all the time.

In my previous blog post I showed how you could provide parameters to object that you’re pulling from a DiC and have them populated in the resulting object.  As cool as that is, it’s not a massive saving as you need to manually inject the parameters into the DiC.  You can often do the same thing by setting up the DiC ahead of time to get the object with those parameters pre-set.

Let’s start by defining a class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test
{
  protected $test;
 
  public function __construct($test)
  {
    $this->test = $test;
  }
 
  public function getTest()
  {
    return $this->test;
  }
}

What we did before was use call time parameters to set the $test variable.

1
2
3
$di = new Di();
$test = $di->get('Test', array('test' => 'some data'));
echo $test->getTest();

Running this produces

1
'some data'

What if we either don’t know what ‘test’ will be, we want to minimize our code or we want to centralize our injection requirements?  For any of those we can set up the DiC to inject that data for us.

1
2
3
4
5
6
7
8
9
$config = array(
  'instance' => array(
    'Test' => array( // Class name
      'parameters' => array(
        'test' => 'some data'
      )
    )
  )
);

The structure of the configuration is this.  The first level is the key “instance”.  This will limit the objects created to a single instance in the DiC when requested with given set of parameters, similar to a registry (someone in the ZF team can correct me if I’m wrong).  The second level of the array is the key of the class name.  Our class is called “Test” and so we call the key “Test”.  If it was “Api\Service\Account” the key would be ”Api\Service\Account”.  Next up are various options for the injection.  The only option I’m concerned with is the “parameters” one.  That is where you put in the various injections the object needs in a key/value array.

In the parameters array the keys will refer to the names of the variables you are injecting into the class.  The DiC will try to match it in two places.  The first is the named parameters in the constructor and the second are the variable names in the setters in the class.  The latter scenario may require some additional information, but we’ll look at that in a later blog post.

The first thing we need to do is take that configuration and provide it to a configuration object and then have the configuration object configure the DiC for us.

1
2
3
4
5
use Zend\Di\Configuration;
 
$diConfig = new Configuration($config);
$di = new Di();
$diConfig->configure($di);

We now have a configured DI object.  So to execute our code from earlier we change it just slightly.

1
2
$test = $di->get('Test');
echo $test->getTest();

The could echos

1
'some data'

This is now equivalent to our previous call.  Now this may seem all nice and well, but there’s more to it.  What if your object depends on an instance of another class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Test
{
  protected $test;
 
  public function __construct(Exam $test)
  {
    $this->test = $test;
  }
 
  public function getTest()
  {
    return $this->test;
  }
}
 
class Exam
{
  protected $grade;
 
  public function __construct($grade)
  {
    $this->grade = $grade;
  }
 
  public function getGrade()
  {
    return $this->grade;
  }
}

We have two classes.  One called Test and one called Exam.  Test requires Exam and so we need to define that injection requirement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$config = array(
  'instance' => array(
    'Test' => array( // Class name
      'parameters' => array(
        'test' => 'Exam'
      )
    ),
    'Exam' => array(
      'parameters' => array(
        'grade' => 'A+'
      )
    )
  )
);

We redefined our Test injection to require an instance of “Exam” and we added another instance definition for Exam which provides the grade.  Then we’ll change our code slightly.

1
2
3
$test = $di->get('Test');
echo get_class($test->getTest()) . "\n";
echo $test->getTest()->getGrade();

And when we run it we get

1
2
Exam
A+

With that you can now configure a DI Container and start providing references to various objects in and around your application.

There is more to talk about but we’ll leave this post at that.  Check back soon for more examples.

A little more advanced ZF2 EventManager usage

<note>I found out that this usage is going to be deprecated.  This feature will remain, but for the GA (and beta 4 most likely) this code may not work.  I will be updating this blog post when that happens</note>

If you look at my previous post on the ZF2 EventManager class you might be tempted to think that you are limited only to listening to events for local instances of the event manager.  But no, my friend, you would be wrong.

The event manager actually provides access to a sort of global event manager.  But it’s more than that.  This global event manager allows you to listen in on events for various targets.

So let’s say that you have an event manager for a given class in a given namespace.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace ns1 {
 
  use Zend\EventManager\EventManager;
 
  class cls1 {
 
    protected $events;
 
    public function __construct()
    {
      $this->events = new EventManager(__CLASS__);
    }
 
    public function execute()
    {
      $this->events->trigger('meesa.triggered', $this);
    }
  }
}

Take a look at the constructor.  What you are doing there is giving the event manager an identifier.  Identifiers are not needed, but if you want to allow other event manager instances to attach to its events an identifier will make it globally known.

Next up we will create a class that attaches to that event manager by calling the StaticEventManager class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace ns2 {
 
  use Zend\EventManager\Event,
  Zend\EventManager\StaticEventManager;
 
  class cls2 {
 
    public function listen(Event $e)
    {
      echo get_class($this) . ' has been called by ' . get_class($e->getTarget());
    }
  }
 
  StaticEventManager::getInstance()->attach('ns1\cls1', 'meesa.triggered', array(new cls2, 'listen'));
}

We’re not calling the class ns1\cls1 in this case, just attaching to its event.  When setting this up we attach to the identifier that we provided in the first class (often a class name), followed by the event name and them providing the  class and method name via a callback.  When the event is triggered that callback will be called and we will we will  print out the target class.

1
2
3
4
use ns1\cls1;
 
$cls = new cls1();
$cls->execute();

When we execute that code we get the following output.

ns2\cls2 has been called by ns1\cls1

So even though ns2\cls2 and ns1\cls1 had virtually no knowledge of each other (we did because we “set them up to succeed”), we were able to call code from across the codebase with great ease.

My first stab at the Dependency Injection Container in Zend Framework 2

So, let me explain… no, there is too much.  Let me sum up.

With beta 3 now being released I have started to spend some time getting used to the new MVC components and the architecture in general.  I turns out that was too much.  When I learn something new I like to start with something broken and fix it.  This forces me to understand how things work a little better.  But I ran into a problem that MVC is so dependent on other concepts in ZF2 that until I understood those concepts I would be spinning my tires trying to get an MVC-based application running without much benefit.

So since I already know how to use event managers the next most basic thing I needed to understand was Dependency Injection.

It turned out that I was actually using Dependency Injection and just didn’t know it.  You know all of those iterative addElement() calls in Zend_Form?  Dependency Injection.  Getters and Setters like setPluginLoader() or setTranslator()?  Kinda the same thing.  Basically, if you don’t call the constructor inside of an object you are likely going to be injecting functionality into that object.  Whallah!  Dependency Injection.  While that does not encompass DI, it is a good starting point.

But one of the problems with manually injecting dependencies is just that; it is manual.  Need a view object?  Create and inject it.  Need to use it 20 times?  Create it once and inject it into any object that needs it, making sure to pass it around to any component that may need it.  It’s a bit of a hassle.

Enter the Dependency Injection Container.  What this allows you to do is write a class and maintain an instance of that class in a container so rather than making sure you have injected every dependency you just inject the container.  There’s more to it, such as creating definitions, but that’s all you need to know for a starting point.

Setting up DI is actually really easy.  Let’s start with a class.

1
2
3
class Test
{
}

Now let’s create our DI container

1
$di = new Zend\Di\Di();

Now let’s get an object

1
$test = $di->get('Test');

There you have it.  You are now using a Dependency Injection Container.  Instead of passing that Test object around to everything that needs it simply pass the container and you can get it, or any other object in the container, in one place.

So what if your object actually needs some data injected into it?  Add a constructor!

1
2
3
4
5
6
7
8
9
class Test
{
  protected $test;
 
  public function __construct($test)
  {
    $this->test = $test;
  }
}

Now to get an instance with data passed in the constructor we need to add the constructor parameters to the DI call.

1
$test = $di->get('Test', array('test' => 'value'));

If we do a var_dump() on $test we will now see that the protected variable $test has the value “value” attached to it.

The last thing we will look at is calling a setter.  Setters can have a little more complexity to them but the basic usage is very much the same.

Let’s start with our class.

1
2
3
4
5
6
7
8
9
class Test
{
  protected $test;
 
  public function setTest($test)
  {
    $this->test = $test;
  }
}

Now we call our DI container

1
$test = $di->get('Test', array('test' => 'value'));

And we get the object with the setter called.  Notice something?  We didn’t change the code to call the DI container.  What happened was because the container constructor was removed the DI container tried to find a proper setter for the key “test”.  That was called setTest() and so it called the setter and the value was injected.  So what happens when we have both a constructor and a setter?  With this code they are both called twice.

With that you can see some very basic usage of a dependency injection container.  While any application of any size will have more complexity to it these examples show that to get up and running with DI and a container are actually not very complex.  But while this is simple I will be going into much more depth in subsequent blog posts to expose some of the power that comes with using a DIC.

Web Analytics