Sunday, August 25, 2013

Zend Framework 2 event manager

Understanding the Zend Framework 2 event manager

The event manager is without any doubt one of the least known Zend Framework 2 component. Nevertheless, it is a very powerful component which offers a lot of flexibility when used correctly. This short article aims to help you to use it.

Why using the event manager?

The event manager allows event driven programming. It allows to flexibly connect different parts of the code to each other, without having a wrong, inverted dependency.
The event manager is extensively used internally (that’s why we said that ZF 2 is an event-driven framework). Thus, contrary to Zend Framework 1, most of MVC elements (routing, dispatching, view…) are not called one after another. Instead, framework triggers events (“dispatch”, “route”…). Other objects listen those events and, in turn, do something in response of those events. We can extract some wording:
  • Objects trigger events. Those events are named (“route”, “dispatch”, “sendTweet”…) and often contain additional parameters (for instance, an event called “sendTweet” could contain the tweet’s content).
  • Other objects listen (they are called listeners) those events to do something. In other ways, we attach objects to events.

The TweetService example

The nice thing about the event manager is that not only the framework can use them! Let’s take a simple example: we have written a TweetService class whose goal is to send a tweet thanks to the Twitter API.
namespace Tweet\Service;

class TweetService
{
    /**
     * @param string $content
     */
    public function sendTweet($content)
    {
        // Send a tweet through Twitter API...
    }
}
But this crazy marketing guy said us that it could be fun to send an email to the tweet’s author too:
namespace Tweet\Service;

class TweetService
{
    /**
     * @param string $content
     */
    public function sendTweet($content)
    {
        // Send a tweet through Twitter's API...

        // Send a mail
        $mailService->send(...);
    }
}
But it’s not enough for him, he also wants SMS:
namespace Tweet\Service;

class TweetService
{
    /**
     * @param string $content
     */
    public function sendTweet($content)
    {
        // Send a tweet through Twitter's API...

        // Send an e-mail...
        $mailService->send(...);

        // Send a SMS...
        $smsService->send(...);
    }
}
Some problems quickly arise:
  • Our TwitterService now depends on the application. This specific application requires that a mail and SMS are sent, but maybe another one will just send the tweet, while another one will add a message to a queue. This is exactly what we want to avoid when we create a “generic” module whose aim is to be a “drop-in” module.
  • Furthermore, the TweetService depends on two other services too: an email service and SMS service. This means: every time we want to use the TwitterService module, we also must download the EmailService and SMSService modules, even if we don’t use them.

How to use it

Trigger an event

A very elegant solution to this problem is directly bundled into Zend Framework 2 : the event manager. Thus, we are going to simply trigger an event to say “hey mate, a tweet has been sent” instead of hard-coding what to do. Our code is then modified this way:
namespace Tweet\Service;

use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerInterface;

class TweetService implements EventManagerAwareInterface
{
    /**
     * @var EventManagerInterface
     */
    protected $eventManager;

    /**
     * @param string $content
     */
    public function sendTweet($content)
    {
        // Send the tweet with Twitter's API...

        // Trigger an event
        $this->getEventManager()->trigger('sendTweet', null, array('content' => $content));
    }

    /**
     * @param  EventManagerInterface $eventManager
     * @return void
     */
    public function setEventManager(EventManagerInterface $eventManager)
    {
        $this->eventManager = $eventManager;
    }

    /**
     * @return EventManagerInterface
     */
    public function getEventManager()
    {
        return $this->eventManager;
    }
}
As we can see, we now only trigger an event called “sendTweet”. It’s up to the mail and/or SMS service to listen to this event to send an email/SMS.
You can also notice that this class implements the EventManagerAwareInterface interface. When we create an object that implements this interface through the service manager, Zend Framework 2 will automatically inject a new event manager for us by calling the setEventManager method.

Add listeners

Most of the time, listeners are added in the Module.php file, more precisely in the onBootstrap method. This is the easiest and recommended way. Intuitively, this is what most people do when they are first introduced to the event manager:
namespace Tweet;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $event)
    {
        $eventManager = $event->getApplication()->getEventManager();
        $eventManager->attach('sendTweet', function($e) {
            var_dump($e);
        }, 100);
    }
}
This code is pretty simple: we retrieve the application’s event manager, and add a callback (through a closure) that is called when the event sendTweet is triggered.
Unfortunately… this does not work. I know I know, you may think this is not intuitive, but there are reasons for that. Let’s introduce the shared event manager !

The shared event manager

Let’s go back to the TweetService. Earlier, I said that when a class implements the EventManagerAwareInterface, ZF 2 automatically inject a new event manager. I need to emphasize on the word new!
As a consequence, when we trigger the event sendTweet in the TweetService class, because the event manager is different (once again, it is a new event manager), the TweetService’s event manager has absolutely no knowledge about listeners that could have been added to other event managers. And this is absolutely what we were doing in the previous code snippet, as we were attaching a listener to the application’s event manager (which is different from the TwitterService’s one).
You may ask yourself why ZF 2 does not inject the same event manager everywhere. This way, the problem would be solved. But if you think about it more, this could rise even more problems. For instance, let’s imagine an event called send. Multiple objects may trigger an event called send, but for completely different purposes (send could be an event’s name used to send an email, a SMS, a HTTP request or whatever!). This would mean that listeners could receive event for things they would not be interested at all.
That’s why each object has its own event manager, with its own events.
To solve our previous example, we need to use a so-called shared event manager. A shared event manager is a manage which is unique across the application, and that is injected into each event manager (yeah I know, it’s not easy to grasp !). Let’s modify our Module.php code in order to attach the event into the shared event manager instead:
namespace Tweet;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $event)
    {
        $eventManager       = $event->getApplication()->getEventManager();
        $sharedEventManager = $eventManager->getSharedManager();

        $sharedEventManager->attach('Tweet\Service\TweetService', 'sendTweet', function($e) {
            var_dump($e);
        }, 100);
    }
}
First, we retrieve the shared event manager from the application’s event manager. Then, we attach a listener. The subtlety is the first parameter whose value is here Tweet\Service\TweetService. Indeed, currently, without this parameter, the event manager of our TweetService has no way to “get” the listeners of the event it triggers.
Thus, we need to slightly modify our setEventManager method in TweetService:
public function setEventManager(EventManagerInterface $eventManager)
{
    $eventManager->addIdentifiers(array(
        get_called_class()
    ));

    $this->eventManager = $eventManager;
}
Now, everything is linked properly. We are adding here a new identifier whose value is get_called_class() (in this case, it is equals to Tweet\Service\TweetService). When this service will trigger the event sendTweet, here is what will happen internally:
  1. The TweetService’s event manager will check if objects are listening to sendTweet, which is not the case here because the listeners have been added to the shared event manager (remember the Module.php code!).
  2. The event manager will then retrieve the shared event manager (remember it is unique !). Then, for each of its identifiers (in our case, it only has one, which is get_called_class), it will check if an event was added to the event sendTweet with the given identifier. In other words, it will check if there is a registered listener for the event sendTweet with the identifier Tweet\Service\TweetService (=== get_called_class()). This is exactly what we did in the onBootstrap method!
  3. Finally, for each listener, the callback will be executed (in our example, we simply called a var_dump($e)).
This identifier mechanism is really powerful. For instance, let’s imagine we want to trigger the event sendTweet in several services. We could add another, more generic, identifier:
public function setEventManager(EventManagerInterface $eventManager)
{
    $eventManager->addIdentifiers(array(
        'Application\Service\ServiceInterface',
        get_called_class()
    ));

    $this->eventManager = $eventManager;
}
Now, update the Module.php class:
namespace Tweet;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $event)
    {
        $eventManager       = $event->getApplication()->getEventManager();
        $sharedEventManager = $eventManager->getSharedManager();

        // This listener will be called ONLY if the sendTweet event is triggered
        // by an event manager that has the Tweet\Service\TweetService identifier !
        $sharedEventManager->attach('Tweet\Service\TweetService', 'sendTweet', function($e) {
            var_dump($e);
        }, 100);

        // This listener will be called for all events sendTweet from all event
        // manager that has the identifier Application\Service\ServiceInterface,
        // so potentially a lot
        $sharedEventManager->attach('Application\Service\ServiceInterface', 'sendTweet', function($e) {
            var_dump($e);
        }, 100);
    }
}

The special case of MVC events

I said earlier that we should use the shared event manager. But there is one specific case: the event manager we retrieve from the onBootstrap method is the MVC event manager. This means that this event manager knows the events triggered by the framework. This means that if you want to add listeners to the events of the Zend\Mvc\MvcEvent class, you can do it without using the shared event manager:
namespace Tweet;

use Zend\Mvc\MvcEvent;

class Module
{
    public function onBootstrap(MvcEvent $event)
    {
        $eventManager = $event->getApplication()->getEventManager();
        $eventManager->attach(MvcEvent::EVENT_ROUTE, function($e) {
            var_dump($e);
        }, 100);
    }
}

Let’s clean that…

In the previous example, we used a closure to define what the listeners must do. This is quick and easy, but if you have a lot of listeners, this can quickly be a mess. Furthermore, if you want to attach the same listener to multiple events, it will irremediably lead to a code duplication.
Hopefully, we can do it better by creating new classes that implement Zend\EventManager\ListenerAggregateInterface interface (starting from ZF 2.2, you can instead extend the abstract class Zend\EventManager\AbstractListenerAggregate). This interface asks you to write two methods: attach and detach. Here is the class that adds a listener to the sendTweet event:
namespace Tweet\Listener;

use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;

class SendListener implements ListenerAggregateInterface
{
    /**
     * @var \Zend\Stdlib\CallbackHandler[]
     */
    protected $listeners = array();

    /**
     * {@inheritDoc}
     */
    public function attach(EventManagerInterface $events)
    {
        $sharedEvents      = $events->getSharedManager();
        $this->listeners[] = $sharedEvents->attach('Tweet\Service\TweetService', 'sendTweet', array($this, 'onSendTweet'), 100);
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    public function onSendTweet($e)
    {
        var_dump($e);
    }
}
This way, the onBootstrap method is simplified, and allow to move logic to specific classes instead of polluting the Module.php class:
public function onBootstrap(EventInterface $e)
{
    $eventManager = $e->getTarget()->getEventManager();
    $eventManager->attach(new SendListener());
}

why Zend Framework should absolutely be your PHP framework of choice

Introduction

Whether you’re starting a new project or improving an existing one, in this article, I’ve provided ten reasons why you should use Zend Framework for your next project, and hopefully, it helps you in making an informed decision.

Reason 1. Extend Classes like There’s no Tomorrow

Zend Framework is a fully object-oriented framework, and as such, it utilizes a lot of object-oriented (OO) concepts like inheritance and interfaces. This makes most, if not all, of ZF’s components extendable to some point. It allows developers to implement their own special variations of individual components without having to hack into the ZF codebase itself. Being able to customize ZF this way allows you to create functionality that is unique to your project, but because of its object-oriented nature, you’ll be able to use this functionality in other projects as well.

Example

Zend Framework has a very extensive Validation component, which you can use to validate data coming from forms. In ZF, forms are treated as objects as well, and are represented by the Zend_Form component.
Let’s assume that you want to create a custom URL validator to restrict URL input from the user. The quickest way to do this would be to just validate the input using something like:

  1. $isValid = filter_var($submitted_url, FILTER_VALIDATE_URL);  
But this won’t adhere to the OO nature of form objects, since it’s not used within the context of the form. To solve this, we can create a new Zend_Validator class by extending the Zend_Validate_Abstract class:

  1. <?php  
  2. class Zend_Validate_Url extends Zend_Validate_Abstract  
  3. {  
  4.     const INVALID_URL = 'invalidUrl';  
  5.       
  6.     protected $_messageTemplates = array(  
  7.         self::INVALID_URL   => "'%value%' is not a valid URL.",  
  8.     );  
  9.       
  10.     public function isValid($value)  
  11.     {  
  12.         $valueString = (string) $value;  
  13.         $this->_setValue($valueString);  
  14.           
  15.         if (!Zend_Uri::check($value)) {  
  16.             $this->_error(self::INVALID_URL);  
  17.             return false;  
  18.         }  
  19.         return true;  
  20.     }  
  21. }  
This actually uses the Zend_Uri class, which already has a URL checking method we can use. But since it doesn’t extend the Zend_Validate_Abstract class, we implemented a wrapping class which does implement the needed abstract class. This lets us use the Zend_Uri URL checking function in our Zend_Form objects like so:

  1. <?php   
  2. class Form_Site extends Zend_Form   
  3. {  
  4.     public function init()  
  5.     {  
  6.         $this->setMethod('POST');  
  7.         $this->setAction('/index');  
  8.           
  9.         $site$this->createElement('text''siteurl');   
  10.         $site->setLabel('Site URL');   
  11.         $site->setRequired(true);  
  12.           
  13.         //  Adding the custom validator here!  
  14.         $site->addValidator(new Zend_Validate_Url());  
  15.         $this->addElement($site);  
  16.         $this->addElement('submit''sitesubmit'array('label' => 'Submit'));  
  17.     }  
  18.   
  19. }  
If we wanted to check that our URLs are valid YouTube video URLs, we could do something like this:

  1. <?php  
  2. class Zend_Validate_YouTubeUrl extends Zend_Validate_Abstract  
  3. {  
  4.     const INVALID_URL = 'invalidUrl';  
  5.       
  6.     protected $_messageTemplates = array(  
  7.         self::INVALID_URL   => "'%value%' is not a valid URL.",  
  8.     );  
  9.       
  10.     public function isValid($value)  
  11.     {  
  12.         $valueString = (string) $value;  
  13.         $this->_setValue($valueString);  
  14.           
  15.         if (strpos($value"http://www.youtube.com/watch?v=") !== 0) {  
  16.             $this->_error(self::INVALID_URL);  
  17.             return false;  
  18.         }  
  19.         return true;  
  20.     }  
  21. }  
If we added this to our site form object as a validator, it would ensure that all URLs submitted begin with the correct YouTube video URL prefix.

Reason 2. Object-oriented Goodness


Image courtesy of http://www.developer.com
In Zend Framework, everything is an object, as proven by our example above. This poses its own disadvantages, such as making things more complicated to code. Its main advantage, though, is the ability to make code reusable, and since nobody likes to repeat themselves, this is a very good thing.

Example

We already have our Zend_Validate_Url and Form_Site class from our example above, so let’s reuse them in this example.

  1. <?php  
  2.   
  3. class IndexController extends Zend_Controller_Action  
  4. {  
  5.   
  6.     public function indexAction()  
  7.     {  
  8.         $siteform = new Form_Site();  
  9.   
  10.         if$this->_request->isPost() && $siteform->isValid($this->_request->getPost()) ) {  
  11.             //stuff to do if the input is correct  
  12.             $this->_redirect("/index/correct");  
  13.         }  
  14.         $this->view->siteform = $siteform;  
  15.     }  
  16.   
  17.     public function correctAction()  
  18.     {  
  19.         // Yay, we're re-using our Form_Site object!  
  20.         $this->view->siteform = new Form_Site();  
  21.     }  
  22. }  
Here’s what it would look like on a browser:
If you tried to submit an invalid URL, you can see our URL validator at work:
Here, you can see what would happen if you did input a valid URL:
As you can see, we’ve never had to repeat our form object code.
“Zend_Validate classes can be used in other ways as well, not only within the context of Zend_Form classes. You simply instantiate a Zend_Validate class and call the isValid($parameter) method, passing it the value you want to validate.”

Reason 3. Use What you Need, Forget Everything Else


By design, Zend Framework is simply a collection of classes. Normally, you’ll use Zend MVC components to create a fully-functional ZF project, but in any other case, you can just load the components you need. ZF is very decoupled, which means we can take advantage of the components as individual libraries, instead of the framework as a whole.
If you’ve been looking at other framework articles, you’ve probably heard of the term glue framework. ZF, by default, is a glue framework. Its decoupled nature makes it easy to use as “glue” to your already existing application.
There’s a debate between using glue frameworks vs. full-stack frameworks. Full-stack frameworks are those that provide you everything you need to create your project, like ORM implementations, code-generation, or scaffolding. Full-stack frameworks require the least amount of effort to create a project, but fall short in terms of flexibility, since it imposes strict conventions on your project.

Example

Let’s say you need a way to retrieve information about a specific video on YouTube. Zend_Gdata_Youtube is a ZF component which allows you to access data from YouTube via the GData API. Retrieving the video information is as simple as:

  1. //Make sure you load the Zend_Gdata_Youtube class, this assume ZF is in your PHP's include_path  
  2. include_once "Zend/Gdata/Youtube.php";  
  3.   
  4. $yt = new Zend_Gdata_YouTube();  
  5. // getVideoEntry takes in the YouTube video ID, which is usually the letters at the end  
  6. // of a YouTube URL e.g. http://www.youtube.com/watch?v=usJhvgWqJY4  
  7. $videoEntry = $yt->getVideoEntry('usJhvgWqJY4'); 
  8. echo 'Video: ' . $videoEntry->getVideoTitle() . "<br />"; 
  9. echo 'Video ID: ' . $videoEntry->getVideoId() . "<br />"; 
  10. echo 'Updated: ' . $videoEntry->getUpdated() . "<br />"; 
  11. echo 'Description: ' . $videoEntry->getVideoDescription() . "<br />"; 
  12. echo 'Category: ' . $videoEntry->getVideoCategory() . "<br />"; 
  13. echo 'Tags: ' . implode(", ", $videoEntry->getVideoTags()) . "<br />"; 
  14. echo 'Watch page: ' . $videoEntry->getVideoWatchPageUrl() . "<br />"; 
  15. echo 'Flash Player Url: ' . $videoEntry->getFlashPlayerUrl() . "<br />"; 
  16. echo 'Duration: ' . $videoEntry->getVideoDuration() . "<br />"; 
  17. echo 'View count: ' . $videoEntry->getVideoViewCount() . "<br />";  

This code would output:
One thing to note here: this Zend Framework component (GData) is the official PHP library endorsed by Google to access its API. The framework’s decoupled nature allows us to use the component in any project, regardless of the framework we used to build it.

Reason 4. It lets you do a Lot of Things!

One of the things I love most about Zend Framework is that it has A LOT of components. Need a way to authenticate a user? Use Zend_Auth. Need to control access to your resources? Look up Zend_Acl. Need to create some forms? We have Zend_Form. Need to read an RSS feed? You can use Zend_Feed for that. It’s basically the Swiss Army knife of PHP classes!
Zend actually comes with some demos that show how to use its different components:
To view these, the best way is to simply download the Full Package Version of Zend Framework and test them out on your machine.
For a complete list of all the components, you can check out the Zend Framework Manual.

Reason 5. No Model Implementation – Choose your Own Adventure!


This is actually one of the reasons most developers don’t use Zend Framework – it has no Model implementation on its own. For those who don’t know what a Model is, it’s the M in MVC, which stands for “Model-View-Controller”, a programming architecture that’s used by most PHP Frameworks.

Does that mean that Zend Framework is only a “VC” Framework?

Yes, and no.
Yes, it’s a VC framework because it doesn’t have its own Model implementation. This makes it hard for some people to use ZF, especially if they’re coming from a framework which does have a Model implementation (like CakePHP, Symfony, or even Ruby on Rails).
On the other hand, no, it’s an MVC framework as well, since apart from providing the generic ways to access the database (using Zend_Db), it actually still relies on some sort of Model implementation. What it does differently is that it leaves this kind of implementation up to the developer รฑ which some say should be the case since models are actually where the business logic of the application resides, and therefore, they’re not something which can be developed as a generic component. Zend Framework Philosophy states that model implementations are unique to the projectรณit’s impossible to create an abstract implementation of it since they don’t really know what you need. They believe that models should be implemented by the developers themselves.

How is this a good thing?

Not having a Model implementation means that the developer is free to use whatever means he has to implement it, or even just integrate existing implementations. Being free of predefined restraints, the developer is then allowed to create more complex implementations, rather than just simple representations of tables, which is how usual Model implementations are created. Models contain your business logic. They should not be restrained by your database tables; rather, they should dictate the connections of these tables to one another. This lets you put most of your programming code in your Models, therefore satisfying the “Thin Controllers, Fat Models” paradigm of MVC.

So how will I use Zend Framework if I have no idea how to create my own models?

For beginners, the Zend Framework Quickstart tutorial shows us a good way to implement models. In the tutorial, they implement an ORM approach to the models, wherein you would create three filesรณthe actual Model, which is an abstract representation of your object; a Mapper, which maps data from the database to your Model; and a Database Table object, which is used by the mapper to get the data. You can check out the code in the ZF Quickstart tutorial, where they used this approach to implement the model of a simple Guestbook application.
For those asking “Why do I have to code this myself while other frameworks do the work for me?”, this is a perfect segue to my next reason…

Reason 6. Integrate with Whatever you Want!

Zend Framework’s decoupled nature makes it very easy to integrate other libraries that you want to use. Let’s say you want to use Smarty as your templating system. It can be done by simply creating a wrapping class for Zend_View_Abstract, which uses a Smarty instance to render the view.
This works both ways, as you can integrate ZF into other libraries as well. For example, you can integrate ZF into Symfony. They’re planning to do this with Symfony 2, using the Zend_Cache and Zend_Log components from ZF.

Example

For our example, we’ll try using Doctrine to implement our Model. Continuing from our site example above, say you’ve already implemented your DB table like so:

  1. CREATE TABLE  `site` (  
  2.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  
  3.   `url` varchar(100) CHARACTER SET latin1 NOT NULL,  
  4.   PRIMARY KEY (`id`)  
  5. );  
To integrate Doctrine into ZF, we’ll have to make sure that the proper settings are defined. I’ve followed this tutorial from dev.juokaz.com about using Doctrine with ZF.
Assuming everything works out, you’ll just have to generate your model files by running the doctrine-cli.php php file from the tutorial like so:
  1. php doctrine-cli.php generate-models-db  
You should see this success message:
Afterwards, you can check the folder which you set as the place to store the generate Model classes.
Then in our controller class, we can simply use our site model class.

  1. <?php  
  2.   
  3. class IndexController extends Zend_Controller_Action  
  4. {  
  5.   
  6.     public function indexAction()  
  7.     {  
  8.         $siteform = new Form_Site();  
  9.   
  10.         if$this->_request->isPost() && $siteform->isValid($this->_request->getPost()) ) {  
  11.             //stuff to do if the input is correct  
  12.             $site = new Model_Site();  
  13.             $site->url = $this->_request->getParam('siteurl');  
  14.             $site->save();  
  15.             //redirect to our success page  
  16.             $this->_redirect("/index/correct");  
  17.         }  
  18.         $this->view->siteform = $siteform;  
  19.     }  
  20.   
  21.     public function correctAction()  
  22.     {  
  23.         // Yay, we're re-using our Form_Site object!  
  24.         $this->view->siteform = new Form_Site();  
  25.     }  
  26. }  
If we check our sites table, we’ll see that our records is there
Now, every time we submit a site, our controller will use our Doctrine model implementation to save to our database. Isn’t that nice and easy? Setup may be a bit complicated, but on the plus side, our project is now able to take advantage of a tool which has been developed specifically for Model implementation. Our project now has the power of two very developed technologies behind it.

Reason 7. Guidelines and Standards

Zend Framework is developed in conjunction with a very extensive Contributor Guide, which basically states that:
  1. Every contributor for both documentation and/or code, at any level (either a few lines of code, a patch, or even a new component) must sign a Contribute License Agreement (CLA).
  2. Code MUST be tested and covered by a unit test using PHPUnit. And…
  3. Code must adhere to strict Coding Standards
These strict guidelines ensure that you only use readable, high-quality code that has been tested thoroughly.

Reason 8. All Code is Guilty Until Proven Innocent (aka Test-Driven Development)


Test-driven development is a programming technique that requires a developer to write tests for the function he is supposed to code before writing code for the function itself. By writing the tests first, it ensures that the programmer:
  1. Thinks of the possible use-cases of his code
  2. Creates a whitelist of input and output
  3. Makes it easier to refactor his code
  4. Makes it easier to pass code from one person to another

The test-driven development Cycle
Image courtesy of Wikipedia
Zend Framework makes it easy to do TDD via Zend_Test, which uses PHPUnit, a popular unit testing framework. PHPUnit lets you test not only your Controllers, but also your library and model functions. To add to this, Zend_Tool, which is Zend Framework’s scaffolding utility, already makes provisions for PHPUnit when you use it to create your project.

Integrating PHPUnit and Zend Framework

Setting up Zend Framework and PHPUnit is not that difficult. Basically, once you’re done with it, you’ll be able to use the same setup for your future projects. Just as a side note, the following steps assume that you’ve used Zend_Tool to scaffold your project structure and files, but it should be relatively simple to change for other setups.
First, we need to install PHPUnit. The best way is to install it via PEAR:
  1. pear channel-discover pear.phpunit.de  
  2. pear install phpunit/PHPUnit  
Afterward, we’ll open our phpunit.xml, an XML file generated by Zend_Tool. You’ll find it inside the tests folder in the root directory of your project. Add the following lines:

  1. <phpunit bootstrap="./TestHelper.php" colors="true">  
  2.     <testsuite name="Zend Framework Unit Testing">  
  3.         <directory>.</directory>  
  4.     </testsuite>  
  5.   
  6.     <filter>  
  7.         <whitelist>  
  8.             <directory suffix=".php">../library</directory>  
  9.             <directory suffix=".php">../application</directory>  
  10.             <exclude>  
  11.                 <directory suffix=".phtml">../application</directory>  
  12.             </exclude>  
  13.         </whitelist>  
  14.     </filter>  
  15. </phpunit>  
After saving phpunit.xml, create a new file inside the same folder as phpunit.xml called TestHelper.php. This PHP file will help us setup the environment for our tests.

  1. <?php  
  2. // start output buffering  
  3. ob_start();  
  4.   
  5. // set our app paths and environments  
  6. define('BASE_PATH'realpath(dirname(__FILE__) . '/../'));  
  7. define('APPLICATION_PATH', BASE_PATH . '/application');  
  8. define('APPLICATION_ENV''testing');  
  9.   
  10. // Include path  
  11. set_include_path(  
  12.     '.'  
  13.     . PATH_SEPARATOR . BASE_PATH . '/library'  
  14.     . PATH_SEPARATOR . get_include_path()  
  15. );  
  16.   
  17. // We wanna catch all errors en strict warnings  
  18. error_reporting(E_ALL|E_STRICT);  
  19.   
  20. require_once 'ControllerTestCase.php';  
We then create our parent Controller Test Case class, which all of our Controllers will extend. This will help implement methods which would usually be the same throughout all of the Controller test classes.

  1. <?php  
  2. require_once 'Zend/Application.php';  
  3. require_once 'Zend/Test/PHPUnit/ControllerTestCase.php';  
  4.   
  5. abstract class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase  
  6. {  
  7.     public $application;  
  8.   
  9.     public function setUp()  
  10.     {  
  11.         $this->application = new Zend_Application(  
  12.             APPLICATION_ENV,  
  13.             APPLICATION_PATH . '/configs/application.ini'  
  14.         );  
  15.   
  16.         $this->bootstrap = $this->application;  
  17.         parent::setUp();  
  18.     }  
  19.   
  20.     public function tearDown()  
  21.     {  
  22.         $this->resetRequest();  
  23.         $this->resetResponse();  
  24.         parent::tearDown();  
  25.     }  
  26. }  
Lastly, we create a controller test class:

  1. <?php  
  2. require_once realpath(dirname(__FILE__) . '/../../ControllerTestCase.php');  
  3.   
  4. class IndexControllerTest extends ControllerTestCase  
  5. {  
  6.     public function testCallingRootTriggersIndex()  
  7.     {  
  8.         $this->dispatch('/');  
  9.         $this->assertController('index');  
  10.         $this->assertAction('index');  
  11.     }  
  12.     
  13.     public function testCallingBogusTriggersError()  
  14.     {  
  15.         $this->dispatch('/bogus');  
  16.         $this->assertController('error');  
  17.         $this->assertAction('error');  
  18.         $this->assertResponseCode(404);  
  19.     }  
  20. }  
All that’s left is to run our test. Open your command prompt and go to the tests folder and type:
phpunit
Your command line should output the following:



Reason 9. Community and Documentation

Due to its multiple components, complexity, and fully object-oriented approach, Zend Framework has a very steep learning curve. It becomes easier to learn due to the comprehensiveness of its documentation and its thriving community. First of all, the Zend Framework Programmer’s Reference Guide boasts a complete guide to all ZF components, with examples, code, and usage theories.
Aside from this, there are a lot of blogs out there that share Zend Framework tips and tricks. For example, Phly, boy, phly, the blog of Matthew Weier O’Phinney, a Core Contributor to Zend Framework, provides a lot of insights, clever uses, and component explanations for Zend Framework. Zend also has a site called Zend Developer Zone, which aside from publishing tutorials for Zend Framework, has stuff like Zend Framework Webinars, podcasts, and articles about PHP in general. Another site, called Zend Casts, offers a lot of useful video tutorials on different Zend Framework components as well. Last but not least, there’s a free online book called Zend Framework: Surviving the Deep End” written by P·draic Brady, another Zend Framework contributor.
As you can see, there is no lack of support from the community, the documentation, and the developers. If you have any questions or need any clarifications, a quick search with the right keywords should almost always give you relevant results. If not, there’s still the Zend Framework Mailing Lists, the official Zend Framework Forums, the unofficial Zend Framework Forums or the unofficial Zend Framework IRC channel

Reason 10. Certifications Ahoy!

If you’re still unconvinced about learning and using Zend Framework, this reason is actually the one that I feel most distinguishes Zend Framework from all the others. Zend not only offers Zend Framework Certification, but PHP Certification as well. By offering certifications, Zend helps you use your expertise in PHP and Zend Framework to boost your portfolio or CV. The Zend Certification site lists a number of reasons to get certified, some of which are:
  1. Differentiate yourself from competitors when looking for a new job
  2. Get your resume/CV noticed
  3. Have your profile displayed in Zend’s Yellow Pages for PHP Professionals
  4. Be part of the Linkedin Group Exclusively for ZCE’s
  5. Get special discounts on Zend PHP conferences worldwide

Addendum

Just to keep things balanced, here’s a quick list of reasons why you might not want to use Zend Framework:
  1. VERY steep learning curve. It’s not very hard for advanced PHP users, but for beginners, there’s a lot to learn!
  2. Big footprint. Since Zend Framework has a lot of components, it’s total size is relatively higher than other Frameworks. For example, CodeIgniter’s system folder has a 1.5MB footprint compared to Zend Framework’s 28MB footprint.
  3. No solid scaffolding tool. Although Zend_Tool offers some functionality, it’s not much compared with the scaffolding utilities of full-stack frameworks like CakePHP or Symfony.
  4. Not shared webhosting friendly. The folder structure generated by Zend_Tool suggests that the public folder be the only directory accessible via http รณ which assumes that a user is able to create a virtual host for the project. This is something you aren’t able to do in most shared web hosting environments.
  5. Too gluey. Since everything is in separate classes, it’s sometimes hard to envision how everything works. This wouldn’t be a problem with full-stack frameworks, since they mostly take care of everything for you. Without Zend_Tool, it would be extremely difficult to set up a working project structure

Saturday, August 24, 2013

PHP ARRAY FUNCTIONS

PHP Array Functions



PHP: indicates the earliest version of PHP that supports the
function.


Function Description PHP
array() Creates an array 3
array_change_key_case() Returns an array with all keys in lowercase or uppercase 4
array_chunk() Splits an array into chunks of arrays 4
array_combine() Creates an array by using one array for keys and another for its values 5
array_count_values() Returns an array with the number of occurrences for each value 4
array_diff() Compares array values, and returns the differences 4
array_diff_assoc() Compares array keys and values, and returns the differences 4
array_diff_key() Compares array keys, and returns the differences 5
array_diff_uassoc() Compares array keys and values, with an additional user-made function check, and returns the differences 5
array_diff_ukey() Compares array keys, with an additional user-made function check, and returns the differences 5
array_fill() Fills an array with values 4
array_filter() Filters elements of an array using a user-made function 4
array_flip() Exchanges all keys with their associated values in an array 4
array_intersect() Compares array values, and returns the matches 4
array_intersect_assoc() Compares array keys and values, and returns the matches 4
array_intersect_key() Compares array keys, and returns the matches 5
array_intersect_uassoc() Compares array keys and values, with an additional user-made function check, and returns the matches 5
array_intersect_ukey() Compares array keys, with an additional user-made function check, and returns the matches 5
array_key_exists() Checks if the specified key exists in the array 4
array_keys() Returns all the keys of an array 4
array_map() Sends each value of an array to a user-made function, which returns new values 4
array_merge() Merges one or more arrays into one array 4
array_merge_recursive() Merges one or more arrays into one array 4
array_multisort() Sorts multiple or multi-dimensional arrays 4
array_pad() Inserts a specified number of items, with a specified value, to an array 4
array_pop() Deletes the last element of an array 4
array_product() Calculates the product of the values in an array 5
array_push() Inserts one or more elements to the end of an array 4
array_rand() Returns one or more random keys from an array 4
array_reduce() Returns an array as a string, using a user-defined function 4
array_reverse() Returns an array in the reverse order 4
array_search() Searches an array for a given value and returns the key 4
array_shift() Removes the first element from an array, and returns the value of the removed element 4
array_slice() Returns selected parts of an array 4
array_splice() Removes and replaces specified elements of an array 4
array_sum() Returns the sum of the values in an array 4
array_udiff() Compares array values in a user-made function and returns an array 5
array_udiff_assoc() Compares array keys, and compares array values in a user-made function, and returns an array 5
array_udiff_uassoc() Compares array keys and array values in user-made functions, and returns an array 5
array_uintersect() Compares array values in a user-made function and returns an array 5
array_uintersect_assoc() Compares array keys, and compares array values in a user-made function, and returns an array 5
array_uintersect_uassoc() Compares array keys and array values in user-made functions, and returns an array 5
array_unique() Removes duplicate values from an array 4
array_unshift() Adds one or more elements to the beginning of an array 4
array_values() Returns all the values of an array 4
array_walk() Applies a user function to every member of an array 3
array_walk_recursive() Applies a user function recursively to every member of an
array
5
arsort() Sorts an array in reverse order and maintain index
association
3
asort() Sorts an array and maintain index association 3
compact() Create array containing variables and their values 4
count() Counts elements in an array, or properties in an object 3
current() Returns the current element in an array 3
each() Returns the current key and value pair from an array 3
end() Sets the internal pointer of an array to its last element 3
extract() Imports variables into the current symbol table from an
array
3
in_array() Checks if a specified value exists in an array 4
key() Fetches a key from an array 3
krsort() Sorts an array by key in reverse order 3
ksort() Sorts an array by key 3
list() Assigns variables as if they were an array 3
natcasesort() Sorts an array using a case insensitive "natural order"
algorithm
4
natsort() Sorts an array using a "natural order" algorithm 4
next() Advance the internal array pointer of an array 3
pos() Alias of current() 3
prev() Rewinds the internal array pointer 3
range() Creates an array containing a range of elements 3
reset() Sets the internal pointer of an array to its first element 3
rsort() Sorts an array in reverse order 3
shuffle() Shuffles an array 3
sizeof() Alias of count() 3
sort() Sorts an array 3
uasort() Sorts an array with a user-defined function and
maintain index association
3
uksort() Sorts an array by keys using a user-defined function 3
usort() Sorts an array by values using a user-defined
function
3

Wednesday, August 21, 2013

How to Set Up Apache Virtual Hosts on Ubuntu 12.04 LTS

What the Red Means

The lines that the user needs to enter or customize will be in red in this tutorial!

The rest should mostly be copy-and-pastable.


About Virtual Hosts


Virtual Hosts are used to run more than one domain off of a single IP address. This is especially useful to people who need to run several sites off of one virtual private server. The sites display different information to the visitors, depending on with which the users accessed the site.There is no limit to the number of virtual hosts that can be added to a VPS.

Set Up

The steps in this tutorial require the user to have root privileges. You can see how to set that up in the here Initial Server Setup. You can implement whatever username suits you.

Additionally, you need to have apache already installed and running on your virtual server
If this is not the case, you can download it with this command:
sudo apt-get install apache2

Step One— Create a New Directory


The first step in creating a virtual host is to a create a directory where we will keep the new website’s information.

This location will be your Document Root in the Apache virtual configuration file later on. By adding a -p to the line of code, the command automatically generates all the parents for the new directory.
sudo mkdir -p /var/www/example.com/public_html

You will need to designate an actual DNS approved domain, or an IP address, to test that a virtual host is working. In this tutorial we will use example.com as a placeholder for a correct domain name.

However, should you want to use an unapproved domain name to test the process you will find information on how to make it work on your local computer in Step Seven.

Step Two—Grant Permissions


We need to grant ownership of the directory to the user, instead of just keeping it on the root system.
 sudo chown -R $USER:$USER /var/www/example.com/public_html 

Additionally, it is important to make sure that everyone will be able to read our new files.
 sudo chmod -R 755 /var/www

Now you are all done with permissions.

Step Three— Create the Page


Within our configurations directory, we need to create a new file called index.html
sudo nano /var/www/example.com/public_html/index.html

We can add some text to the file so we will have something to look at when the IP redirects to the virtual host.
<html>
  <head>
    <title>www.example.com</title>
  </head>
  <body>
    <h1>Success: You Have Set Up a Virtual Host</h1>
  </body>
</html>

Save and Exit

Step Four—Create the New Virtual Host File


The next step is to set up the apache configuration. We’re going to work off a duplicate—go ahead and make a copy of the file (naming it after your domain name) in the same directory:
 sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/example.com

Step Five—Turn on Virtual Hosts


Open up the new config file:
 sudo nano /etc/apache2/sites-available/example.com

We are going to set up a virtual host in this file.

The first step is to insert a line for the ServerName under the ServerAdmin line.
  ServerName example.com 

The ServerName specifies the domain name that the virtual host uses.

If you want to make your site accessible from more than one name (for example, with www in the URL), you can include the alternate names in your virtual host file by adding a ServerAlias Line. The beginning of your virtual host file would then look like this:
<VirtualHost *:80>
        ServerAdmin webmaster@example.com
        ServerName example.com
        ServerAlias www.example.com
  [...]

The next step is to fill in the correct Document Root. For this section, write in the extension of the new directory created in Step One. If the document root is incorrect or absent you will not be able to set up the virtual host.

The section should look like this:
 DocumentRoot /var/www/example.com/public_html 

You do not need to make any other changes to this file. Save and Exit.

The last step is to activate the host, with the built in apache shortcut:
 sudo a2ensite example.com

Step Six—Restart Apache


We’ve made a lot of the changes to the configuration, and the virtual host is set up. However none of the changes that we made will take effect until Apache is restarted. Use this command to restart apache:
 sudo service apache2 restart

You may see an error along the lines of
Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName 

The message is just a warning, and you will be able to access your virtual host without any further issues.

Optional Step Seven—Setting Up the Local Hosts


If you have pointed your domain name to your virtual private server’s IP address you can skip this step—you do not need to set up local hosts. Your virtual hosts should work. However, if want to try out your new virtual hosts without having to connect to an actual domain name, you can set up local hosts on your computer alone.

For this step, make sure you are on the computer itself, not your droplet.

To proceed with this step you need to know your computer’s administrative password, otherwise you will be required to use an actual domain name to test the virtual hosts.

If you are on a Mac or Linux, access the root user (su) on the computer and open up your hosts file:
nano /etc/hosts 

If you are on a Windows Computer, you can find the directions to alter the host file on the Microsoft site

You can add the local hosts details to this file, as seen in the example below. As long as that line is there, directing your browser toward, say, example.com will give you all the virtual host details for the corresponding IP address.
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost

#Virtual Hosts 
12.34.56.789    example.com

However, it may be a good idea to delete these made up addresses out of the local hosts folder when you are done to avoid any future confusion.

Step Eight—RESULTS: See Your Virtual Host in Action


Once you have finished setting up your virtual host, you can see how it looks online. Type your ip address into the browser (ie. http://12.34.56.789)

It should look somewhat similar to my handy screenshot

Good Job!

Creating More Virtual Hosts


To add more virtual hosts, you can just repeat the process above, being careful to set up a new document root with the appropriate domain name, and then creating and activating the new virtual host file.