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
Free Learning
Arrow right icon
Zend Framework 2 Cookbook
Zend Framework 2 Cookbook

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
Profile Icon joseph@callaa.rs Profile Icon Josephus Callaars
Arrow right icon
€41.99
Full star icon Full star icon Full star icon Full star icon Empty star icon 4 (4 Ratings)
Paperback Dec 2013 340 pages 1st Edition
eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m
Arrow left icon
Profile Icon joseph@callaa.rs Profile Icon Josephus Callaars
Arrow right icon
€41.99
Full star icon Full star icon Full star icon Full star icon Empty star icon 4 (4 Ratings)
Paperback Dec 2013 340 pages 1st Edition
eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m
eBook
€8.99 €32.99
Paperback
€41.99
Subscription
Free Trial
Renews at €18.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

Zend Framework 2 Cookbook

Chapter 1. Zend Framework 2 Basics

In this chapter we will cover:

  • Setting up a Zend Framework 2 project

  • Handling routines

  • Understanding dependency injection

  • Using configurations to your benefit

  • The EventManager and Bootstrap classes

Introduction


In this chapter we will go through a basic Zend Framework 2 application, from download, to setup, to running it. If you are unfamiliar with how Zend Framework 2 works, and the best way to install it, you can use this chapter as a reference. Further on in the chapter, we will get somewhat deeper in the framework by looking at the dependency injection (DI) and how it can help us code more efficiently. Lastly we will go more into the details of the configuration options, the EventManager and ModuleManager.

Setting up a Zend Framework 2 project


Nothing is more exciting than setting up a new project in our favourite framework. Every time we start a new project we begin with a clean slate.

Getting ready

Before you can set up a new Zend Framework 2 application you need to make sure you have the following items ready:

  • A web server such as Apache running PHP Version 5.3.3 or higher that you can reach from a web browser

  • Git

If you don't have everything ready as mentioned, you are best off reading the topics mentioned in the See also section of this recipe (every topic we explain in this chapter is called a recipe) before you continue reading here.

We are assuming that Zend Framework 2 will be used on a Linux-based platform running an Apache 2 web server; this means that commands might not directly work on a Windows platform. Windows users, however, can set up a virtual machine with Linux on it to make full use of the book.

To install a virtual machine on Windows, we can use an application called Oracle VM VirtualBox, which is freely available. We can go to www.virtualbox.org and download plus install the latest version of VirtualBox, we can go to VirtualBoxes (http://virtualboxes.org/images/ubuntu) and download a preconfigured virtual machine from there.

All we have to do on the VirtualBoxes website is click on the latest Ubuntu (which is a distribution of Linux) link in the list, please take note of the username and password displayed there as we will need it later to login. Once the image is downloaded, it can be made ready by following the instructions in the documentation that can be found on the VirtualBoxes site (http://virtualboxes.org/doc/register-and-load-a-downloaded-image).

Assuming the image is imported we can easily start up the virtual machine and put in our username and password that has been supplied with the downloaded virtual machine.

Once logged in to the virtual machine we need to make sure Git is installed, which can be done easily by typing in the following command (mind that the dollar sign is the command prompt, and not the command we actually need to type):

$ sudo apt-get install git

If Git wasn't installed, the system will ask you to install Git, which can be done by pressing the Y key, followed by the Enter key, on the other hand if Git was already installed, than it will not do anything and tell you it already is installed.

How to do it…

First of all, we need the Zend Framework 2 skeleton so we can easily create a new project. A skeleton is a template structure that can be used to start developing with an application, and in this case it creates a template for us to develop within Zend Framework. Fortunately doing this is relatively easy, and almost never causes any problems, and when it does, it is usually related to Git not being able to retrieve the code. When Git isn't able to retrieve the skeleton, please make sure there are no spelling mistakes in the command, and that Git has outside access (we can test this by typing ping Github.com and see whether we get a response back).

The method we are going to use to retrieve the skeleton is called cloning, through a version control system called Git. Cloning the source code will make sure we always get the latest version that the developer (in this case Zend itself) has put online.

Cloning the skeleton

We can clone the skeleton—and almost everything else on Github for that matter — through use of the following command:

$ git clone git://github.com/zendframework/
  ZendSkeletonApplication.git

Moving the skeleton

Once finished we can go into the newly created folder called ZendSkeletonApplication, and copy and paste everything in there over to our web server document root. On a Linux system this is usually /var/www (this is also the case when we use Zend Server, as described in the Appendix, Setting up the Essentials). We can do this, for example, by typing the following commands:

$ cd ZendSkeletonApplication
$ mv ./* /var/www –f
$ cd /var/www

Initializing the Composer

When everything is copied over, we are going to initialize the project by typing the following command:

$ php composer.phar install

Now the Command Line Interface (CLI) of PHP executes composer.phar, which will in this instance, download and install the Zend Framework 2 library and set up a simple project for us to be able to work in.

This command can take a long time before it is successfully executed, as Composer needs to do a lot of things before it tells you that Zend Framework 2 is ready for use, we won't go into the details of the workings of Composer here, as it is already discussed in the Appendix, Setting up the Essentials.

Once this command has been completed we need to make sure our web server document root is changed to match the layout of the skeleton. It is common practice that Zend Framework 2 uses the public folder as a main landing point for the application. The structure of the Zend Framework 2 skeleton allows us to bind the user to the public folder, while all our logic is safely outside the public area.

In essence this means we need to root or jail the web server in using the public folder first before we can actually see anything that we just installed. We want to root or jail the web server because we don't want the outside world to be able to abuse our web server more than necessary, and rooting or jailing makes sure that the web server itself has no access to any other folders than what it is jailed to, thus making our server a bit more secure.

In my personal case this means changing the Apache 2 configuration. In most Linux-based systems it will be the Apache web server that is serving our web requests.

The easiest thing that you can do is find your web server configuration (usually located in /etc/apache2 and append the DocumentRoot with /public. For me this would change the document root from /var/www' to '/var/www/public.

Tip

If you are using Apache, you need to check if the AllowOverride setting is set correctly, this can be found in the same section as your document root and should reflect the following:

AllowOverride FileInfo

Finally we need to restart the Apache web server, which can be done by the following command if you are logged in as a root user or invoke it by prepending the command with sudo, which tells the server that we want to execute it as a super user.

$ apache2ctl restart

Now we are able to check our browser and see what we have actually done. We now simply go with a web browser to the project created by typing in the URL, in my case this would be the following:

http://localhost/

This will result in the following screen:

Congratulations, you have now set up a basic Zend Framework 2 application.

How it works…

After getting the basic Zend Framework 2 skeleton working, it is the perfect time to install the ZFTool. The ZFTool is a utility module that comes in handy when we want to list the current modules in our project, or add a new module, or even set up a new project. It also contains an extremely useful class-map generator that we can use in the somewhat more advanced areas of Zend Framework 2.

We can install this utility by using the following commands:

$ cd /var/www
$ mkdir -p vendor/zftool
$ cd vendor/zftool
$ wget https://packages.zendframework.com/zftool.phar

Although we already set up our Zend Framework 2 skeleton through the composer, it might be a fun thing to show you how you can easily set up a new project through the ZFTool.


$ cd /var/www
$ php vendor/zftool/zftool.phar create project new-project

The preceding command will create a new Zend Framework 2 skeleton project in the folder /var/www/new-project. In turn this means that the document root for our new project should be set to /var/www/new-project/public.

To complete the Zend Framework 2 application in our new-project, we can simply go to the new-project directory and execute the following command:

$ cd new-project
$ php composer.phar install

Another handy command of the ZFTool is the creation and display of modules in our project. The ZFTool can easily display a list of modules that we currently use (with larger applications we tend to lose sight of the modules) and the ability to create a new skeleton module for our application. To see a list of the current modules used in our application we can use the following command:

$ php ../vendor/zftool/zftool.phar modules

To create a new module named wow-module in our project based in the directory /var/www/new-project we can use the following command:

$ php ../vendor/zftool/zftool.phar create module wow-module
  /var/www/new-project

Giving the path to the application is optional, but if we are using it with multiple projects on the same machine, it is best to make sure that we have the right path for our project.

And now for the last and probably the most useful command in the ZFTool box, the class-map generator. A class-map file is a file that has all the classes of a project with their respective paths declared, which makes it easier for the PHP auto loaders to load the class file. Normally class files are found in paths that we know of, creating a small lag because the auto loader actually needs to search for the file. With a class-map file, however, this is not the case as the auto load can immediately find the file required.

Class-mapping is a big issue in Zend Framework 2 because a bad class mapping can make a good application terribly slow, and to be completely fair Zend Framework 2 can use all the speed it can get.

What the class-map generator does is create a file that contains all the classes and paths that can be autoloaded. That way we don't have to worry about where the classes are located.

To generate a new class-map file, we can use the following command:

$ php zftool.phar classmap generate <directory> <file> -w

The command requires us to give in two different parameters:

  • <directory>: The directory that needs to have the classes indexed. For example, this can be a new library you added to the vendor directory.

  • <file>: This is the class-map file the ZFTool needs to generate. Our auto loader in Zend Framework 2 needs to pick this file up, so we need to make sure that the ZFTool can find the file. If you don't specify a file, it will create a file called autoload_classmap.php in the current working directory.

Most of the time it is necessary to append a class-map file instead of overwriting it, if you want to append it you can simply change -w with -a.

An example of a class-map file is the autoload_namespaces.php file in the vendor/composer directory, and it looks a little bit like this:

<?php
return array(
  // Every class beginning with namespace Zend\ will be 
  // searched in this specific directory
  'Zend\\' => array(
    __DIR__ . '/../zendframework/zendframework/library'
  ),
  'ZendTest\\' => array(
    __DIR__ . '/../zendframework/zendframework/tests'
  ),
);

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

There's more…

There are also other ways of installing the ZFTool, some are just as easy as using the composer, so we'll cover two other methods of installing the ZFTool. That way we give ourselves the broadest options available to use.

Another method of installing ZFTool is by utilizing git, and thus cloning the source code from the repository itself. This however gets the current master version, which can be a bit buggy.

$ cd vendor
$ git clone https://github.com/zendframework/ZFTool.git
$ cd ZFTool
$ php ./zf.php

Instead of zftool.phar we have now got the zf.php file at our disposal, which can be used in exactly the same way. Now we have covered all the different options on installing ZFTool.

See also

  • The Making sure you have all that you need recipe in the Appendix, Setting up the Essentials

  • The Downloading Zend Framework 2 and finding its documentation recipe in the Appendix, Setting up the Essentials

  • The Composer and its uses within Zend Framework 2 recipe in the Appendix, Setting up the Essentials

  • Apache web server http://apache.org/

  • PHP website http://php.net

Handling routines


An important aspect (if not the most important one) is the routing within Zend Framework 2. In its most basic form routing tells the framework how the user should get from page A to page B, and what needs to be done to arrive at that destination. That is why we generally think this is the most important part to understand if you are just starting out.

How to do it…

To define a route we can simply go into one of the configuration files and add the router configuration to there.

Setting up routing

Let's look at our simple (Segment) configuration as follows (file: /module/Application/config/module.config.php):

return array(
  // Here we define our route configuration
  'routes' => array( 

    // We give this route the name 'website'
    'website' => array( 

      // The route type is of the class:
      // Zend\Mvc\Router\Http\Segment
      'type' => 'segment', 

        // Lets set the options for this route
        'options' => array( 

          /*
            The route that we want to match is /website
            where we can optionally add a controller name
            and an action name. For example:
              /website/index/index
          */ 
          'route' => '/website[/:controller[/:action]]',

          /*
            We don't want to accept everything, but this
            regex makes sure we only accept alpha-
            numeric characters and a dash and underscore.

            In our instance we want to check this for the
            action and the controller.
          */
          'constraints' => array( 
            'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
            'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
          ),

          /*
           We want to make sure that if the user only 
           types /website in the URL bar it will actually
           go somewhere. We defined that here.
          */
          'defaults' => array( 
            'controller' => 'Website\Controller\Index', 
            'action' => 'index'
          ),
        ),
      ),
    ),
  ),
);

With this basic configuration we can easily define routes in our application, and in this instance we have configured a route that responds to the /website URL. When we would go to the /website URL, we would be routed to the Website\Controller\Index::indexAction by default. If we however use the route /website/another/route, we would be routed to the Website\Controller\Another::routeAction, as we have defined that the controller and action can be parsed behind that. If we omit the route path and put in /website/another, we would be redirected to the Website\Controller\Another::indexAction, as that is used by default by the framework.

The preceding example has only one really major drawback, which is, when we decide to use anonymous function in the configuration to create more dynamic routes, we would not be able to cache the route as closures are not serializeable by the cache.

However, there is another method of declaring the route, and that is in the code. The need to create the route functionality in the code could (obviously everyone has their own reasons and requirements) arise because we want to cache the configuration in a later stage (as we cannot cache anonymous function, for example) or when we want to load up a route dynamically from a database.

Let's take a look at the /module/Application/Module.php example:

<?php

// We are working in the Application module
namespace Application;

// Our main imports that we want to use
use Zend\Mvc\ModuleRouteListener;
use Zend\Mvc\MvcEvent;

// Define our module class, this is always 'Module', but 
// needs to be specifically created by the developer.
class Module
{
  public function onBootstrap(MvcEvent $e)
  {
    // First we want to get the ServiceManager
    $sm = $e->getApplication()->getServiceManager();
    
    /*
      Say our logged in user is 'gdog' and we want
      him to be able to go to /gdog to see his profile.
    */
    $user = 'gdog';

    // Now get the router
    $router = $sm->get('router');

    // Lets add a route called 'member' to our router
    $router->addRoute('member', array(

      /*
        We want to make /$user the main end point, with 
        an optional controller and action.
      */
     'route' => '/'. $user. '[/:controller[/:action]]',

      /*
        We want a default end point (if no controller
        and action is given) to go to the index action
        of the index controller.
      */
      'defaults' => array( 
        'controller' => 'Member\Controller\Index', 
        'action' => 'index' 
      ), 

      /*
        We only want to allow alphanumeric characters
        with an exception to the dash and underscore.
      */
      'constraints' => array( 
          'controller' => '[a-zA-Z][a-zA-Z0-9_-]*', 
          'action' => '[a-zA-Z][a-zA-Z0-9_-]*' 
      ), 
    ));
  }
}

Naturally there are more ways of adding a route, but the method mentioned in the preceding code for adding a route displays a canny way of dynamically adding a route. What we created there is that whenever Gdog goes to his profile, he can simply type in http://example.ext/gdog and end up on his profile.

Even more wonderful is that if our friend Gdog wants to see his friends, he is able to do that by just typing in for example, http://example.ext/gdog/my/friends, which will resolve to the Member module and then go to the My controller, lastly executing the Friends action.

Using SimpleRouteStack

This route stack is—as the name implies—the simplest router around and is basically a list with routes that is being parsed to see which route matches, by default this type of router is not used in Zend Framework 2. The general rule of thumb is that if we want to add a route with a high priority, we give it a high index number for example, 100, or 200. If we want to give the route a very low priority, we would give it an index number of, for example, 5 or 10.

Giving priorities to routes comes in handy when we have very specific routes (which usually have a high priority) and less specific routes (low priority). If we, for example, want to make /website/url redirect to a completely different module, controller, and action, but not affect the other website routes, we need to give the /website/url route a higher priority so that when it is found, it will not search for the lower priority routes.

If we, by accident, turn the priorities around, we would find our /website/url always redirect to the route that contains all the /website routes.

SimpleRouteStack uses a Zend\Mvc\Router\PriorityList class to manage its routes priorities.

We need to consider routing before we want to start creating our application, as when the application grows we might get into trouble with our routing if we haven't considered 'how to route' beforehand. It would therefore be wise for us to 'sitemap' the application before coding the routes to make sure we have a correct route list and are not creating any conflicting routes.

The SimpleRouteStack class has a number of methods defined that are very useful for us:

  • getRoute($name) / getRoutes($name): This will retrieve the current route—if a name is provided—or routes that are defined in our SimpleRouteStack. If we are unsure about the routes we have defined, this would be a good place to check first.

addRoute($name, $route, $priority) / addRoutes($routes): We can use this to add a new route or an array of routes to our route type by simply adding it through this method. A route requires a name, route (which can be a string or an instance of RouteInterface) and if we fancy a priority, we can give that as the third parameter.

hasRoute($name): If we would want to check whether a specific route already exists, we can search using its name and find out if it does or doesn't.

  • removeRoute($name): When we are tired of a route we can simply give its name and remove it from the list. This can be particularly handy if we want for example to have a module override a certain /login when the user has logged in to route to/user.

  • SimpleRouteStack: Does not have a functionality to have multiple routes with the same priority. If there is a route with a priority already defined, it will prioritize the last route added as the route with the highest priority.

Using TreeRouteStack

Routers are not restricted to using the URI path to find out how to route a request. They can also use other information such as the query parameters, headers, methods, or hostnames to find a match.

How it works…

In Zend Framework 2, we will generally use routing that is based on a request URI, which contains path segments that should be queried. Routes are matched by a router, which utilizes RouteStack to find the match to the query made by the router. We use RouteStack because we want a decent way of managing our different routes. With Zend Framework 2 there are loads of route types provided, but only two flavorless routers namely SimpleRouteStack and TreeRouteStack.

When we are defining a router, we need to make sure we understand how it works. Although creating lists with different paths is simple enough, it is wise to remember that the Zend Framework 2 router generally works with the Last In First Out (LIFO) concept, which means that a route that would be used often would be registered last, and a route that is less common would be registered earlier in the router stack.

There's more…

Besides the two standard route types, Zend Framework 2 comes with a whole scale of route types that are more specialized to the Internet navigation or even through the console.

Namespace – Zend\Mvc\Router\Http

A wonderful set of HTTP routers can be found in the Zend\Mvc\Router\Http namespace and we will take a quick look at the different classes that reside within this namespace.

The Hostname class explained

The Zend\Mvc\Router\Http\Hostname namespace will try to match its routing against the hostname defined in the configuration. For example, if we define the route to be something.example.ext, our router will make its routing decision based on the full URL. But, if we add a single colon at the beginning of that same route, for example: :something.example.ext, the router would base its route on the something variable, which could be anything from aardvark.example.ext to zyxt.example.ext.

The Literal class explained

The Zend\Mvc\Router\Http\Literal class will literally match the path we give in. For example, if we put a route in there, which is /grouphug, the route will only resolve to that URL, and nothing else.

Methods explained

The Zend\Mvc\Router\Http\Method class is used when we want to match against an HTTP method instead of a segment or path. This could be, for example, a POST, DELETE and so on. The method is also called verb by Zend Framework 2, which means that instead of a route parameter, it requests a verb parameter when adding the route, which is an excellent way to create RESTful APIs.

The Part class explained

The Zend\Mvc\Router\Http\Part class is used to describe child_routes in our routing configuration. This means that—although never used directly—we can define that /user/profile is being redirected to use the UserController, with the profile action.

Let's consider the following configuration:

return array(
  // We begin our router configuration
  'router' => array(

    // Define our routes 
    'routes' => array(

      // We are defining a route named 'Example'
      'Example' => array(
        'type' => 'Literal',
        'options' => array(
  
           /*
            This route will resolve to /recipe 
            which will resolve to the Example 
            module's IndexController and execute 
            the IndexAction.
           */
           'route' => 'recipe',
           'defaults' => array(
             '__NAMESPACE__' => 'Example\Controller',
             'controller' => 'Index',
           ),
         ),
                
         'may_terminate' => true,

          /*
            Here we begin to define our Part route, 
            which always begins with the 
            'child_routes' configuration.
          */
          'child_routes' => array(
            'client' => array(
              'type' => 'Literal',
              'options' => array(
           
              /*
                This child route (or Part) 
                will resolve to /recipe/foo       
                and will call the fooAction in  
                the IndexController.
              */
              'route' => '/foo',
              'defaults' => array(
               'action' => 'fooAction'
              ),
            ),
          ),
        ),
      ),
    ),
  ),
);

Regex explained

The Zend\Mvc\Router\Http\Regex class would be used when we have a complex routing structure that requires us to dynamically create the route. This would, for example, come in handy when we look at News sites, where posts are built up like /archive/some-subject-2013.html. This fairly complex route (as some-subject-2013.html is dynamic in our case) would require a Regex router that can resolve the Controller, Action, and in our case also the output format.

Let's consider the following example:

// We begin our router configuration
'router' => array(

  // Define our routes 
  'routes' => array(

    // We are defining a route named 'Archive'
    'Archive' => array(
      'type' => 'Literal',
      'options' => array(

        /*
          This route will resolve to /archive 
          which will resolve to the Archive 
          module's IndexController and execute 
          the IndexAction.
        */
        'regex' => '/archive/(?<id>[a-zA-Z0-9_-
  ]+)(\.(?<format>(html|xml)))?',
        'defaults' => array(
            '__NAMESPACE__' => 'Archive\Controller',
            'controller' => 'Index',
            'action' => 'indexAction',
            'format' => 'html',
        ), 
        'spec' => '/archive/%id%.%format%',
      ),
    ),
  ),
),

In the preceding example, it is important to note that /archive/%id%.%format% tells us that we will receive two parameters in our method called indexAction that is, id and format.

The Scheme class explained

The Zend\Mvc\Router\Http\Scheme class is always using the defaults parameter and will accept only one other parameter, which is called scheme and can only contain one of the following options, that is, http, https, and mailto.

The Segment class explained

The Zend\Mvc\Router\Http\Segment class is probably one of the most-used routers that we would use, as you can dynamically define the route and controller for any module by using, for example, /:controller/:action, which is easily recognizable by the colon separation. We can define any constraints to the segment by configuring only the use of alphanumeric characters or another definition that we would like to use.

An example of Segment is given in the first example in the How to do it... section.

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.

Using configurations to your benefit


Configurations play a crucial role in the workings of Zend Framework 2, therefore it is essential to know how it works.

How to do it…

Go through the following sections to use configurations to your benefit:

Creating a global configuration

When beginning to code in Zend Framework 2 there is some misunderstanding as to what the different configuration files do. By default we have multiple configuration files, and it might not always be simple to understand where things need to go. That is why we like to apply a simple rule:

Note

Is the configuration necessary throughout all our modules? If yes, place your configuration in the config/application.config.php file. If not, place your configuration in the config/global.php file at the module where it belongs.

The configuration that we usually place in the global.php file can be, for example, the caching method and configuration, the database configuration. Normally we would like to place items in there that are environment related, but nothing that is security sensitive.

Let's take a look at a bad example of global.php:

<?php
return array(

  // We want to create a new database connection
  'db' => array(

    // The driver we want to use is the Pdo, our  
    // favorite
    'driver' => 'Pdo',

    // This is our connection url, defining a MySQL 
    // connection, with database 'somename' which is 
    // available on the localhost server.
    'dsn' => 'mysql:dbname=somename;host=localhost',

    // This is exactly what we should NOT do in this  
    // file, shame on you developer!
    'username' => 'terribleuser',
    'password' => 'evenworsepassword',
  ),

  // We need a database adapter defined as well, 
  // otherwise we can't use it at all.
  'service_manager' => array(
    'factories' => array(
      'Zend\Db\Adapter\Adapter' => 
  'Zend\Db\Adapter\AdapterServiceFactory',
    ),
  ),
);

It is terrible practice to put the username and password in the global.php file. The global.php file is to be put in our version control, and therefore should contain only configuration items that are required to globally run the application, not specific information that is relevant per environment, such as database usernames and passwords.

Creating configuration that only works for a local machine

One of the benefits of the ultra-many configuration files in Zend Framework 2, is that you are able to override your global configuration with your local configuration. This certainly comes in handy when developing and you find yourself in a position where your details are slightly different in configuration than your production environment.

Let's assume that we have the following /config/autoload/global.php configuration file:

<?php
return array(

  // We want to create a new database connection
  'db' => array(

    // The driver we want to use is the Pdo, our  
    // favorite
    'driver' => 'Pdo',

    // This is our connection url, defining a MySQL 
    // connection, with database 'somename' which is 
    // available on the localhost server.
    'dsn' => 'mysql:dbname=somename;host=localhost',
  ),

  // We need a database adapter defined as well, 
  // otherwise we can't use it at all.
  'service_manager' => array(
    'factories' => array(
      'Zend\Db\Adapter\Adapter' => 
  'Zend\Db\Adapter\AdapterServiceFactory',
    ),
  ),
);

As we can see in the preceding example, we create a nice and simple MySQL database connection to our somename database which resides on the localhost. But as good developers we have not defined our username and password in here. That is where the /config/autoload/local.php file comes in.

Let's take a look at how our local.php might look like:

<?php
return array(
  'db' => array(
    'username' => 'awesomeuser',
    'password' => 'terriblepassword',
  ),
);

If we are using a version control system (please say yes), we should not commit this file, not only for security reasons but also because this is a local configuration file and wouldn't be necessary on a live system, as we would create a new one with the right details for that environment.

Editing your application.config.php file

If we look at our default config/application.config.php file we have only a few properties set, but loads of inline comments, which really come in handy when we can't remember the exact name or description of a property any more.

The main configuration that we will be changing the most in our application as we develop is the modules property. This specific property is a simple array with the different module namespaces that we have (and want to use) in our application. At default this looks somewhat like this:

<?php 

return array(
  // This should be an array of module namespaces used 
  // in the application.
  'modules' => array(
    'Application',
  ),
[..]

When we add or remove a module, this line needs to be modified as well and one can even suggest modifying this before starting a new module or removing one. The reason for this is simple, when we forget to modify this file when removing a module it will generate a 500 – Application Error when visiting the application in our browser. And because this configuration file is read quite early in the instantiation, it can sometimes be hard for the developer to pinpoint why the application fails to load all of a sudden.

How it works…

If we look at the index.php file in the public folder, we can see that we parse our initial configuration file to the Zend Framework MVC Application with the line require 'config/application.config.php'. This then loads up the main configuration file, which in its turn defines all our properties.

A nifty property in the application.config.php file is the config_glob_paths property. Any additional configuration files are by default read by finding files in the config/autoload folder as well, using a very specific file pattern namely; *global.php and *local.php. The order in which this is defined is also very important.

When we say *global.php, we can define anything from somemodule.global.php to menu.global.php to just global.php, as the file pattern (also named GLOB_BRACE) searches for anything that matches that. The same happens for *local.php.

The order this is defined is very important as said before because we want our global configuration to be loaded before our local configuration, otherwise there would be no point in overriding our global configuration, would there?

There's more…

To summarize the configuration files:

  • config/application.config.php: Modules can be added and removed here, and very low level configuration happens here.

  • config/autoload/some-module.global.php: Used to override your default values of your module configuration. Make sure not to put sensitive information in here, but hostnames and database names should go in here.

  • config/autoload/some-module.local.php: You can put your usernames and passwords and other configuration items that are very specific to your local environment here.

  • module/SomeModule/config/module.config.php: Module specific configuration happens here, use only default values and make sure nothing too specific will be entered here.

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.

Left arrow icon Right arrow icon

Key benefits

  • Recipes to help you create, test, and optimize your applications
  • A useful guide for PHP developers wanting to broaden their horizons
  • Helps you understand how MVC works and how to make it work for you

Description

Zend Framework 2 is the latest creation of World Wide Web infrastructure company Zend Technologies Ltd. This new PHP framework comes with tons of features and an attractive way of creating applications. Not only is the overall usability of the technology much better, but it also makes your applications more testable, something that is often overlooked. "Zend Framework 2 Cookbook" will show you how applications are set up in Zend Framework 2 and how you can develop successfully in this massive framework. You will master features like Modules, Views, Controllers, and Authentication. The book also discusses the Event Manager, unit testing, and how to optimize your application. The book begins with a discussion about setting up Zend Framework 2, and you will also look at how the framework itself works. By the end of this book, you will be able to create entire secure applications on your own and make sure they are tested and optimized for performance as well. You will learn about sending and receiving e-mails, translation and localization of the application, and how to set up the framework on a Linux web server. You will also learn how to display data from the application to the user by using different display strategies and renderings. The creation of modules will also be discussed. Then, you will move on to look at how to authenticate users and make sure the developer knows how to pick the best method available. Unit testing, debugging, and enhancing the performance will also be covered in this book. "Zend Framework 2 Cookbook" is a perfect book for anyone who wants to start developing with Zend Framework 2.

Who is this book for?

Zend Framework 2 Cookbook" is for PHP developers who are fairly advanced in programming in PHP. It will also be useful for developers who have a keen interest in expanding their knowledge outside the boundaries of simply scripting pages together. As unit testing and MVC will be discussed, it is beneficial for the reader to know what these technologies are, although experience with developing applications is not necessarily essential.

What you will learn

  • Set up Zend Framework 2 on a Linux web server
  • Make your application accessible in other countries and languages
  • Choose and create custom output display renderings
  • Set up modules and use them as widgets
  • Connect and query different types of databases
  • Create the best authentication method
  • Optimize framework applications
  • Debug and test framework applications
Estimated delivery fee Deliver to Spain

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Dec 19, 2013
Length: 340 pages
Edition : 1st
Language : English
ISBN-13 : 9781849694841
Vendor :
Zend Technologies
Languages :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Spain

Premium delivery 7 - 10 business days

€17.95
(Includes tracking information)

Product Details

Publication date : Dec 19, 2013
Length: 340 pages
Edition : 1st
Language : English
ISBN-13 : 9781849694841
Vendor :
Zend Technologies
Languages :

Packt Subscriptions

See our plans and pricing
Modal Close icon
€18.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
€189.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts
€264.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just €5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total 61.98
Instant Zend Framework 2.0
€19.99
Zend Framework 2 Cookbook
€41.99
Total 61.98 Stars icon
Banner background image

Table of Contents

9 Chapters
Zend Framework 2 Basics Chevron down icon Chevron up icon
Translating and Mail Handling Chevron down icon Chevron up icon
Handling and Decorating Forms Chevron down icon Chevron up icon
Using View Chevron down icon Chevron up icon
Configuring and Using Databases Chevron down icon Chevron up icon
Modules, Models, and Services Chevron down icon Chevron up icon
Handling Authentication Chevron down icon Chevron up icon
Optimizing Performance Chevron down icon Chevron up icon
Catching Bugs Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
(4 Ratings)
5 star 50%
4 star 25%
3 star 0%
2 star 25%
1 star 0%
ovunc tukenmez Apr 02, 2014
Full star icon Full star icon Full star icon Full star icon Full star icon 5
The expectations will be very high for a cookbook since the reader would want to see a solution for every difficulty he/she faces with.When it comes to ZF2, if you are beginner, things may look strange even if you look official programmer's reference guide of Zend Framework 2.The books starts with the basics. In this chapter you see how to setup skeleton application and routing (with the explanation of different "route types"), a short explanation of DI, how to create config files, in which order they merges and why we need local and global ones. ZF2's event driven architecture is also explained with an example.In the second chapter, you see how to translate and localize your application with the I18 module. You see different ways to setup translation files (with arrays, using gettext or ini files) You will also learn how to use Poedit to translate .po files. How to select different languages identifying client language is also explained. Next you skip to the mail section where you will understand how to send email with different approaches.From chapter 3 to 7, most used zf2 components during development process are explained. Using forms to get the input from the user, validating and filter them, working with view, what are the view helpers and how to use and create them, switching to different output using view strategy/renderer, details of layout system, how to configure and connect to database, which database engines that available, why we should createStatement() function instead of query() function, CRUD operations with TableGateway, advanced select query generation, db profiling, details of modules, modules and services are explained in these chapters.In 7th chapter different authentication methods are explained. You will also learn how to setup and create auth service, how to force HTTPS protocol, certificate validation.In the next chapter, different caching mechanisms are explained in order to optimize performance.Last chapter is dedicated to error handling and unit testing.In the appendix you will learn how to set up the essentials with the Zend Server Community Edition or using phpcloud service for your development process. Basic ZF2 structure is also explained here. As a bonus, there is a flow chart diagram to understand what happens in the system after a request made.If it had the Navigation (with ACL) section, it would be better however once you get the idea how the framework components work, it becomes very easy task for you.In conclusion, it is nice to have this book for a reference even if you already familiar with ZF2 to learn new ways to do things.
Amazon Verified review Amazon
William H Scholtz Jan 20, 2014
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Believe me, since I switched to Zend framework 2, mid 2012, I have purchased and used all the manuals out there. I just wish this cookbook was available earlier. It is easy to read, the examples can not be more easier to explain, and is good for beginners right up to advanced users.I strongly recommend this book, id you need to quickly start to work, and understand, the ZF 2 API.No, let me re phrase, if you are building application in the ZF2 environment, this cookbook is a must!This book is power. Again, why was it only published now?William H Scholtz
Amazon Verified review Amazon
Lenka Krafková Apr 10, 2014
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
The book is written literally as a cookbook. However, as a cookbook doesn't make you a professional cook, this book also won't make you a professional developer. It contains number of recepies (such as "using database") that show you how to use certain parts of ZF2. This approach has some pros and some cons - it's good that you can find the part you're interested in (like the db) easily and learn how to use it. But there is one problem with this cookbook - the parts are not connected to each other. It's like a manual, but much better for beginners as it explains things in plain language in more logical order. It starts with the ZF2 basics (routing, events, DI) and slowly moves towards more complex topics such as authentication or performance optimization. I think that a user without any prior ZF2 knowledge would be happy with the book. I, as a little more advanced user, missed the more complex topics and connection between the parts.
Amazon Verified review Amazon
Brianleigh65 Aug 02, 2015
Full star icon Full star icon Empty star icon Empty star icon Empty star icon 2
Far too opaque - should be made clear this is a book for experts
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela