Setup logging in application.ini for Zend Framework 1

Today I had to look it up again: how to quickly setup logging for a Zend Framework 1 application. To make it easy for myself to find it again, should I ever need it, I will post it here.

A log is a resource that ZF 1 can load using a predefined resource plugin. That means that we can be lazy: If we setup a logger as a resource called ‘log’ in application.ini, we can use it.

But then, when I started writing this, I stumbled on this blog post, that does exactly the same thing, so just read it here:

http://blog.niklasottosson.com/?p=1158

What this post doesn’t show you is how to add logging to firePHP in the same go:

resources.log.firebug.writerName = "Firebug"
resources.log.firebug.filterName = "Priority"
resources.log.firebug.filterParams.priority = 7

Logging with FirePHP in ZF2

Yesterday I wanted to set up logging to FirePHP in CuddleFish (my pet project business framework). I thought it would be easy, and looking back, it is very easy. Before I figured out how to set it up, it was not so easy, so I’d better blog about it to remind myself of how it’s done.

First of all, you have to set up FirePHP. You can download it from the FirePHP website or install it using pear:
[bash]
pear channel-discover pear.firephp.org
pear install firephp/FirePHPCore
[/bash]

Next, in the Module.php file of your module, you can add a service that provides the configured logger:

[php]
// at the top of the file:
use Zend\Log\Logger;
use \Zend\Log\Writer\FirePhp as FirePhpWriter;
use \Zend\Log\Writer\FirePhp\FirePhpBridge;

// Note that I place FirePHPCore in vendor
require_once ‘vendor/FirePHPCore/FirePHP.class.php’;

// further down
public function getServiceConfig()
{
return array(
‘factories’ => array(
// [..] other factories for other serivces left out
‘log’ => function($sm) {
$log = new Logger();
$writer = new FirePhpWriter(new FirePhpBridge(new \FirePHP()));
$log->addWriter($writer);
return $log;
},
),
);
}
[/php]

Simplifying it

In fact, since we require_once the core FirePHP class, there is no need to pass it to the constructor of the writer using the bridge. I only came to realize this while writing this post. When the FirePHP class exists, it will be used automatically by the writer. So the simplified code becomes:

[php]
// at the top of the file:
use Zend\Log\Logger;
use \Zend\Log\Writer\FirePhp as FirePhpWriter;

// Note that I place FirePHPCore in vendor
require_once ‘vendor/FirePHPCore/FirePHP.class.php’;

// further down
public function getServiceConfig()
{
return array(
‘factories’ => array(
// [..] other factories for other serivces left out
‘log’ => function($sm) {
$log = new Logger();
$writer = new FirePhpWriter();
$log->addWriter($writer);
return $log;
},
),
);
}
[/php]
Now if you need the log somewhere, say in a controller, you can pass it in using the factory for the controller and call:
[php]
$this->info(‘It works’);
[/php]

Alternatively you can call getServiceLocator() inside the controller to get the ServiceManager and get the log instance:
[php]
$this->getServiceLocator()->get(‘log’)->info(‘Will work equally well’);
[/php]

There is however a downside to this: If you have a lot of calls to the log, it is more code to type than just calling $this->log->info(‘something’);

If you have an initalizer in your controller, you can set the log there:
[php]
// inside initializer
$this->log = $this->getServiceLocator()->get(‘log’);
[/php]

If you use a factory to create your controller, you can add a method setLog() to your controller:
[php]
public function setLog($log)
{
$this->log = $log;
}
[/php]

The factory can be a closure in the controller configuration, like we did for the log:
[php]
public function getControllerConfig()
{
return array(
‘factories’ => array(
‘index’ => function($controllers) {
$sm = $controllers->getServiceLocator();
$controller = new Controller\IndexController();
$controller->setLog($sm->get(‘log’));
return $controller;
},
),
);
}
[/php]
Now the log is available as $this->log right after instantiation of the controller.

 

Unit testing Zend Framework 1.x with PHPStorm

Warning: This post is outdated. If you want something more up-to-date: The Dutch Web Alliance has an excellent series on unit testing and debugging with PHPStorm, by Joshua Thijssen

In case I ever forget, to easisly install the latest phpunit, follow the manual blindly, which means to:

go-pear
pear update pear

At the moment of writing, the above yields an error, complaining about Strutures\Graph.php. The solution is to get the Structures_Graph tar by typing:

pear install Structures_Graph

This will yield an error once more, but you can see where the tar file is downloaded to. You can extract it manually and then copy the Structures directory into your PEAR directory (at the same level as the ‘Console’ directory). After that, you can

pear update pear

Once pear is up to date, configure it to auto discover channels. This is really important! And the next step is install phpunit.

pear config-set auto_discover 1
pear install --alldeps phpunit/PHPUnit

NOTE that for ZF 1.x you still need to specify the correct version of phpunit:

pear install --alldeps phpunit/PHPUnit-3.5.15
PHPStorm context menu detail
Run option in PHPStorm context menu

Last night I wanted to run a unit test for Zend Framework 1.11. I only recently switched from ZendStudio to PHPStorm and I didn’t yet run any PHPUnit unit tests from inside PHPStorm. I always liked running unit tests in ZendStudio, although this wasn’t always easy to setup, so I feared the new learning curve ahead of me. This wasn’t quite as hard as I imagined: like anything else in PHPStorm, it is easy to find and easy to setup. Just in case I forget how it all works, I write this down.

First of all, there are some differences in how PHPStorm and ZendStudio approach unit testing. In ZendStudio, you have to select ‘run as PHPUnit test’ from the context menu. The context menu is what you see when you click your right mouse button on the code you are editing and that is also the file that contains the unit test that you want to run. In PHPStorm, you just choose ‘Run’ from the context menu (see image).

Another option in the PHPStorm context menu is to setup a run configuration for the file. Once it is setup,  you will be able to select the run configuration from the menu bar and you get the opportunity to edit it as well. When setting up a run configuration, you can define the scope: Directory, Class,  Method or As Defined in the Configuration File, which is absolutely a great feature.

One of the things that will go wrong in ZendStudio is that you forget to include PHPUnit on the include path of your project, in which case ZendStudio cannot find the PHPUnit library. It will not tell you, it will just not run. PHPStorm will tell you it could not connect a testreporter if it can’t find PHPUnit. This is the exact error message: “Unable to attach test reporter to test framework or test framework quit unexpectedly”. In that case, you don’t have installed PHPUnit for the php version PHPStorm is using. In case you have several versions of php available on your system, you can configure which one PHPStorm should use. This is much the same as it is in ZendStudio. See the next image for how it is done in PHPStorm. In the same dialog, you can add entries to the include path for your php version. Make sure you add the path where PHPUnit lives (in my case that is “/Applications/MAMP/bin/php/php5.3.6/lib”).

Setting the php version in PHPStorm
Setting the php version in PHPStorm

One nifty little feature here is the little ‘i’ button, that brings up all ini settings if you click it. These are editable, but I did not check if that actually takes effect. To change the interpreter, you click the button with the three dots to select the path to your php. By clicking the ‘+’ button you can add entries to the include path.

Setting up PHPUnit

PHPUnit can be easily installed using PEAR. I once had this setup, but because I alwasy used ZendStudio, I had no need to keep it up and running an my installation had been broken by installing MAMP Pro over MAMP. I remembered that installing PHPUnit was a pain, because the pear installer that had shipped with MAMP was to old for the PHPUnit installation. Luckily, that problem did not re-occur.  I could easily install phpunit with pear, but I did no longer have the pear command. I broke that along with the same MAMP Pro installation.

Setup the pear command

To get the pear command back, the directory where it is located must be on your computers PATH. This is not the php include_path, but the PATH environment variable of your system. The PATH variable is set in your .profile file, that is located in your home directory. In my case, the home directory is /Users/bartmcleod. To edit the profile file, just open up terminal and type:

$s sudo vim /Users/bartmcleod/.profile

Inside .profile you will see something like:

export PATH=/opt/local/bin:/opt/local/sbin:$PATH

I changed that to:

export PATH=/opt/local/bin:/opt/local/sbin:/Applications/MAMP/bin/php/php5.3.6/bin:$PATH

to include the location where pear installs it’s commands. Once you have done this, you can proceed to install PHPUnit and you will also have the phpunit command available, since that goes into the same directory.

Installing PHPUnit for Zend Framework 1.x

You will think that installing PHPUnit with PEAR is easy: something along the lines of ‘sudo pear install phpunit’. Of course I tried that first and it executes and everything looks fine, except it didn’t really work for me. Then I found I had to type ‘sudo pear install phpunit/PHPUnit’. That worked, but it didn’t work with Zend Framework 1.x unit tests. They do not support PHPUnit 3.6. I found that the most recent version they support is PHPUnit 3.5.15. So I tried to uninstall phpunit and subsequently install that specific version, using the instructions I found here: http://stackoverflow.com/questions/1569012/how-to-install-an-older-version-of-phpunit-through-pear

In the same article however, it is specifically stated that to install 3.5.15, you have to uninstall separate phpunit components one by one, before installing the specific older version. If you don’t, pear will automatically detect that these components need the latest version and install that instead of the requested older version. This is annoying and hard to believe when you see it happen on the commandline. I had to try several times before I actually believed what was going on.

Because I did not want to type all the commands or paste them one by one, I just created two batch scripts. One to uninstall the latest versions and one to install the 3.5.15 versions.

Uninstall:

sudo pear uninstall phpunit/PHPUnit
sudo pear uninstall phpunit/DbUnit
sudo pear uninstall phpunit/PHP_CodeCoverage
sudo pear uninstall phpunit/File_Iterator
sudo pear uninstall phpunit/PHPUnit_MockObject
sudo pear uninstall phpunit/Text_Template
sudo pear uninstall phpunit/PHP_Timer
sudo pear uninstall phpunit/PHPUnit_Selenium
sudo pear uninstall pear.symfony-project.com/YAML

Re-install 3.5.15:

sudo pear install pear.symfony-project.com/YAML-1.0.2
sudo pear install phpunit/PHPUnit_Selenium-1.0.1
sudo pear install phpunit/Text_Template-1.0.0
sudo pear install phpunit/PHPUnit_MockObject-1.0.3
sudo pear install phpunit/PHP_Timer-1.0.0
sudo pear install phpunit/File_Iterator-1.2.3
sudo pear install phpunit/PHP_CodeCoverage-1.0.2
sudo pear install phpunit/DbUnit-1.0.0
sudo pear install phpunit/PHPUnit-3.5.15

The stackoverlow article from the above url gives more details and use cases that might apply to your particular situation, so if this set of commands doesn’t work for you, make sure you check the original post.

If unit testing with PHPUnit still doesn’t work from inside  PHPStorm

I upgraded to PHPStorm 4 and I tried to repeat the above procedure, and it didn’t work immediately. I kept getting the “Unable to attach test reporter to test framework or test framework quit unexpectedly” error message. I had to change the interpreter from php 5.4 (that ships with PHPStorm apparently) to php 5.3 local, like I had it set up before. I verified that the correct phpunit version is still installed, but with no luck. While trying again and again I found it seems to matter where you click inside the code. Clicking on a single test function will allow you to test only that function, while clicking on the class name will allow you to run the entire test class.

display_errors should be on (obviously)

While that is a nice feature, it doesn’t cover all the cases where unit testing doesn’t work. In one case for example, I had display_errors set to ‘off’ (accidentally) and if you do, you get the same error message  (“Unable to attach test reporter to test framework or test framework quit unexpectedly”) while you see nothing else that could help you detect the error.

Mind your slashes!

In yet another case with the same error message, I found I included the test superclass using windows (back)slashes as directory separators. Apparently, I had been developing those tests on a windows box and didn’t use forward slashes. The error message you get in that case is “Warning: require_once(PHPUnit\Framework\TestCase.php): failed to open stream: No such file or directory in …”. You might not notice immediately that the wrong  slashes are used if you run the tests on *nix or a Mac.

Zend Framework 2.0 patterns

Today I came across a presentation by Matthew Weier O’Phinney on slideshare, that I just do not want to forget about. Because bookmarks tend to disappear when I switch browsers and because I create bookmarks but rarely look at them a second time (using 10+ different browser installations and having bookmarks spread all over) I decided to embed the presentation on my blog, so that it sticks. So here it comes:

I have to remember to try this Depency Injection phenomenon I hear so much about lately.

Zend_Tool and Model generation

Zend_Tool is a command line tool that helps you setup a Zend Framework MVC application. You can also use it after you have set up your application to add controllers, actions, views, configuration and models. Since I use Zend Studio for development, I am used to the integrated version of Zend_Tool. This means that if you set up a Zend Framework MVC application as a new Zend Studio project, you will have menus available that let you add things like controllers and actions.

This is really nice of course, but the nature of the tool, that is command-line by birth, makes that I would like to be able to use it from the command-line too. Continue reading “Zend_Tool and Model generation”