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

The EventManager and Bootstrap classes


We will be showing off one of the most beautiful features of Zend Framework 2: The EventManager.

How to do it…

The EventManager and Bootstrap classes are an essential part of our application, this recipe is all about how to use those two tools:

Using the bootstrap

The bootstrap is in our case the start of a module, whenever a module is requested it will use the onBootstrap() method located in the Module.php file. Although the method is not required, we usually want this method in our module as it is an easy method of making sure that some instances already exist or are configured before venturing further in our client request.

Starting a session

Sessions are a wonderful way of saving information about a user on a temporary basis. Think about saving the information of a logged-in user, or history on the pages they have been. Once we begin creating an application we find ourselves saving a lot of things in the session.

The first thing we need to do is modify the /module/Application/config/module.config.php file, and add another section called session to it. Let's assume that we have a completely empty module configuration:

<?php
return array(
  'service_manager' => array(
     // These are the factories needed by the Service 
     // Locator to load in the session manager
    'factories' => array(
      'Zend\Session\Config\ConfigInterface' => 
  'Zend\Session\Service\SessionConfigFactory',
      'Zend\Session\Storage\StorageInterface' => 
  'Zend\Session\Service\SessionStorageFactory',
      'Zend\Session\ManagerInterface' => 
  'Zend\Session\Service\SessionManagerFactory',
    ),
    'abstract_factories' => array(
  'Zend\Session\Service\ContainerAbstractFactory',
    ),
  ),
  'session_config' => array(
    // How long can the session be idle for in seconds 
    // before it is being invalidated
    'remember_me_seconds' => 3600,

    // What is the name of the session (can be anything)
    'name' => 'some_name',
  ),
  // What kind of session storage do we want to use, 
  // only SessionArrayStorage is available at the minute
  'session_storage' => array(
    'type' => 'SessionArrayStorage',
    'options' => array(), 
  ),
  // These are session containers we can use to store 
  // our information in
  'session_containers' => array(
    'ContainerOne',
    'ContainerTwo',
  ),
);

And that is it. Sessions are now useable in our controllers and models. We have now created two session containers that we can use to store our information in. We can access these containers in any Controller or Model that has a service locator available by doing the following (file: /module/Application/src/Application/Controller/IndexController.php):

<?php

namespace Application;

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractController
{
  public function indexAction()
  {
    // Every session container we define receives a 
    // SessionContainer\ prefix before the name
    $containerOne = $this->getServiceLocator()
  ->get('SessionContainer\ContainerOne');
  }
}
Using the EventManager class

The EventManager class is possibly one of the nicest features in the framework. When used properly, it can make our code a lot more dynamic and maintainable without creating spaghetti code.

What it does is relatively simple, for example; a class might have a method called MethodA. This MethodA has a list of listeners, which are interested in the outcome of that class. When MethodA executes, it just runs through its normal procedures, and when finished it just notifies the EventManager a specific event has occurred. Now the EventManager will trigger all of the interested parties that this event has taken place, and the parties in their turn will execute their code.

Got it? Don't worry if you don't, because this example code might clear things up (file: /module/Application/src/Application/Model/SwagMachine.php):

<?php
// Don't forget to add the namespace
namespace Application\Model;

// We shouldn't forget to add these!
use Zend\EventManager\EventManager;
 
class SwagMachine
{
  // This will hold our EventManager
  private $em;

  public function getEventManager() 
  {
    // If there is no EventManager, make one!
    if (!$this->em) {
      $this->em = new EventManager(__CLASS__);
    }
 
    // Return the EventManager.
    return $this->em;
  }
 
  public function findSwag($id)
  {
    // Trigger our findSwag.begin event 
    // and push our $id variable with it.
    $response = $this->getEventManager()
                     ->trigger(
           'findSwag.begin', 
           $this,
           array(
             'id' => $id
           )
    );
  
    // Make our last response, the final 
    // ID if there is a response.
    if ($response->count() > 0)
      $id = $response->last();
 
    // ********************************
    // In the meantime important code 
    // is happening...
    // ********************************
  
    // ...And that ends up with the 
    // folowing return value:
    $returnValue = 'Original Value ('. $id. ')';
    
    // Now let's trigger our last 
    // event called findSwag.end and 
    // give the returnValue as a 
    // parameter.
    $this->getEventManager()
         ->trigger(
           'findSwag.end', 
           $this, 
           array(
             'returnValue' => $returnValue
           )
    );
 
    // Now return our value.
    return $returnValue;
  }
}

As we can see we created a little class with two event triggers, findSwag.begin and findSwag.end, respectively on the beginning of the method, and one on the end of the method. The findSwag.begin event will potentially modify the $id, and the findSwag.end event only parses the returnValue object, with no modification possible to the value.

Now let's see the code that implements the triggers (file: /module/Application/src/Application/Controller/IndexController.php):

<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
  public function indexAction() 
  {
    // Get our SwagMachine
    $machine = new SwagMachine();
    
    // Let's attach our first callback, 
    // which potentially will increase 
    // the $id with 10, which would 
    // make it result in 30!
    $machine->getEventManager()
            ->attach(
        'findSwag.begin',
        function(Event $e) 
        {
          // Get the ID from our findSwag() 
          // method, and add it up with 12.
          return $e->getParam('id') + 10;
        },
        200
    );
    
    // Now attach our second callback, 
    // which potentially will increase 
    // the value of $id to 60! We give 
    // this a *higher* priority then 
    // the previous attached event 
    // trigger.
    $machine->getEventManager()
            ->attach(
        'findSwag.begin',
        function(Event $e) 
        {
        // Get the ID from our findSwag() 
        // method, and add it up with 15.
        return $e->getParam('id') + 40;
      },
      100
    );
  
    // Now create a trigger callback 
    // for the end event called findSwag.end, 
    // which has no specific priority, 
    // and will just output to the screen.
    $machine->getEventManager()
            ->attach(
        'findSwag.end',
        function(Event $e) 
        {
          echo 'We are returning: '
             . $e->getParam('returnValue');
        }
    );

    // Now after defining the triggers, 
    // simply try and find our 'Swag'.      
    echo $machine->findSwag(20);
  }
}

As we can see attaching triggers to events is pretty straightforward. And – if the events are properly documented – can come in handy when we want to, say, modify parameters going into a method (like we did with the findSwag.begin), or just outputting the results to a log (like findSwag.end).

When we look at what is on our screen, it should be something like this:

We are returning: Original Value (60)
Original Value (60)

The result consists of the top line being the output from the findSwag.end trigger, while the value 60 comes from the highest priority trigger, the one with priority 100 (as that is considered a higher priority than 200).

Changing the View output

Sometimes it is necessary that we have different View outputs, for example when we need to build ourselves a REST service or a SOAP service. Although this can be arranged much simpler by a controller plugin, it is an example on how to hook into the dispatch event, and see what is going on there.

Without further ado, let us take a look at the following code snippet:

Module.php:
namespace Application;

// We are going to use events, and because we use a MVC, 
// we need to use the MvcEvent.
use Zend\Mvc\MvcEvent;

class Module
{
  public function onBootstrap(MvcEvent $e)
  {
    // Get our SharedEventManager from the MvcEvent $e 
    // that we got from the method
    $sharedEvents = $e->getApplication()
                      ->getEventManager()
                      ->getSharedManager();

    // Also retrieve the ServiceManager of the 
    // application.
    $sm = $e->getApplication()->getServiceManager();

    // Let's propose a new ViewStrategy to our 
    // EventManager.
    $sharedEvents->attach(

        // We are attaching the event to this namespace 
        // only.
        __NAMESPACE__, 

        // We want to attach to this very specific 
        // event, the Dispatch event of our controller.
        MvcEvent::EVENT_DISPATCH, 

        // The callback function of the event, used when 
        // the event we attached to happens. In our 
        // callback we also want our local variable $sm 
        // to be available for use.
        function($e) use ($sm) 
        {
          // Get our alternate view strategy from the 
          // ServiceManager and attach the EventManager     
          // to the strategy.
          $strategy = $sm->get('ViewJsonStrategy');
          $view = $sm->get('ViewManager')->getView();
          $strategy->attach($view->getEventManager());
        }, 

        // We want to give this a priority, so this will 
        // get more priority.
        100
    );
}

As we can see it is relatively simple to attach a callback function to the EventManager object. In this example we are using McvEvent::EVENT_DISPATCH as the event we want to hook in to. So what basically happens is that whenever a controller executes the onDispatch() method, this event will be triggered as well. This means that through events we can modify the outcome of a method without actually needing to modify the code.

How it works…

The EventManager class works through a couple of different methods, namely the Observer pattern, the Aspect-Oriented Programming technique (or AOP) and the Event-Driven architecture.

The Observer pattern explained

Simply said the Observer pattern means that there are several interested parties, called listeners that want to know when the application triggers a certain event. When a specific event is triggered, the listeners will be notified so that they can take their necessary actions.

Aspect-Oriented Programming (AOP) explained

If we want to explain what AOP is, we could say that in short it stands for writing clean code that have only function and are as isolated from the rest of the code as possible.

Event-driven architecture explained

The benefit of an Event-driven architecture is that instead of creating bulks of code that need to check every condition, we can easily hook ourselves to different events, which in essence will create a more responsive application.

There's more…

The EventManager object is queried through a PriorityQueue, which tells us that an important event will generally get a lower value, while an unimportant event a higher value. For example, the highest priority might get priority -1000 while a quite low priority might get 40. The EventManager class then gets the queue through a FIFO (First In, First Out) concept, meaning the higher the priority, the lower the number.

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