Speaking at ZendCon

It appears the schedule for ZendCon is at least partly up. I'd been reserving this announcement mostly out of a personal sense of superstitution, but since it seems to be official now, so I'll go ahead and pipe up: I'm speaking at ZendCon.

Out of four proposals, one managed to make it onto the conference schedule, and that was Pick Your Protocol: Creating Web Services with Zend Framework. It won't be my first time at ZendCon, but it will be my first time there as a speaker. I'm looking forward to being among their ranks as well as meeting friends new and old.

See you all in September!

Output Filters in Zend_View

A feature of Zend Framework MVC that isn't currently very well documented is output filters. They're mentioned in passing in the Zend_View documentation, but not reviewed in detail anywhere in the Reference Guide as of version 1.5.2. I was curious enough about how to implement markup minification that I decided to trace through the Zend_View source code in attempt to discern how output filters actually worked. As it turns out, it's actually pretty simple.

First, you need to get a reference to the current Zend_View instance. If you're using the Zend_Layout MVC integration, you can get this by calling $this->_helper->layout->getLayoutInstance within your Zend_Controller_Action class to get the current Zend_Layout instance and then getView on that to get your Zend_View instance. Otherwise, the Zend_View instance is available via the view property of Zend_Controller_Action instance.

Next, call addFilterPath or setFilterPath on your Zend_View instance from your Zend_Controller_Action class. Pass in a path to the directory to contain your output filter classes and a naming prefix that all of your output filter classes will use. I'm not sure why the class prefix defaults to "Zend_View_Filter_" since no such classes exist. In my opinion, it would have made more sense to derive the prefix based on the provided directory path. Anyway, create the directory you've specified if it doesn't already exist and create a new class file within that directory. In my case, I named the directory Vendor/View/Filter, the file Minify.php, and the class contained in the file Vendor_View_Filter_Minify.

Within this class, you must implement at least one method, filter. This method should accept a single parameter, which will be a string containing the view ouput to be filtered, and should return the filtered version of that string. Optionally, if your filter requires access to the related Zend_View instance, you can also declare a setView method that accepts the Zend_View instance as its only parameter and it will automatically be passed in when your output filter class is instantiated. Within setView, you can store the Zend_View instance in an instance property of the output filter class so it can be referred to later in the filter method.

Once you've finished your output filter class, you need to explicitly add it to the output filters in use from your Zend_Controller_Action class. You can use addFilter or setFilter for this. Pass in the name of your output filter class without the class prefix. In my case, I passed in "Minify." At this point, the filter should be used when rendering your page. I poked around in the DOM and Tidy PHP extension documentation, but couldn't find a feature for markup minification, so I ended up using the PCRE extension to do the job. Below is the final source code for my output filter class.

Vendor/View/Filter/Minify.php
class Vendor_View_Filter_Minify
{
public function filter($string)
{
return preg_replace(
array('/>\s+/', '/\s+</', '/[\x0A\x0D]+/'),
array('>', '<', ' '),
$string
);
}
}

Vendor/Controller.php
class Vendor_Controller extends Zend_Controller_Action
{
public init()
{
$this->_helper->layout->getLayoutInstance()->getView()
->addFilterPath('Vendor/View/Filter', 'Vendor_View_Filter_')
->addFilter('Minify');
}
}

DomQuery

Ever since I started working with the jQuery JavaScript library, I've loved it. It offers the power to do a lot with only a little code and makes features offered by the JavaScript DOM implementation much easier to access. My interest in web scraping prompted me to consider creating an equivalent of sorts for PHP.

This obviously doesn't include some features specific to the client-side or any that require evaluating CSS, but it does include many for extracting data from a valid XML or HTML document. I've posted my initial work on the concept in an Assembla SVN repository. The code there is commented with docblocks and includes unit tests with over 99% code coverage. Comments and suggestions are welcome.

php|tek and the Conference Experience

I read the conference synopsis post that Ben Ramsey posted to his blog about php|tek 2008 and couldn't help but feel that I would made the exact same post myself had I been able to summarize my own thoughts as well. It really was a conference focused on community and I commend both the folks over at php|architect for their hard work in organizing it and the community for bringing their own unique talents and perspectives to enhance the experience.

ZendCon was an excellent first conference for me in 2007 and it had its own focus: the enterprise. However, the community was a large part of what brought me into the PHP community and continues to keep me there today, and that was what made php|tek so special. I enjoyed the good times had with friends new and old and look forward to being in attendance at php|tek in future years.

Apologies to all that I wasn't able to say proper goodbyes to on account of having to rush to make my flight back home. I hope everyone made it home safely and that I will see many of you at ZendCon 2008 where, with any luck, you will find me among the speakers for the first time.

Now, back to your regularly scheduled programming...

Unit Tests and Code Coverage with PHPT

My initial experiences with unit testing and PHP were with PHPUnit. While it's a great tool and I have to give kudos to Sebastian for contributing so much to its development, I've come to appreciate the simplicity of PHPT tests. Recently, I wrote some for a project and realized that I wasn't aware of how to generate code coverage reports. Many thanks to the very helpful patrons in the #pear channel on EFNet for helping me to get this working.

First, the stock Kubuntu installation of PEAR is version 1.6.1. Their first recommendation was to upgrade to 1.7.2, which was easy enough:

sudo apt-get install php-pear
pear update-channels
pear upgrade-all

Next, PEAR bug 13958 can prevent code coverage reports from being generated properly. This bug has an available patch, which you can apply by doing the following:

cd /usr/local/share/PEAR
wget -c http://pear.php.net/bugs/...
patch PEAR/RunTest.php phpt_coverage_bug.patch.txt

Now to install PHPUnit. I ran into an odd issue here where following the installation documentation resulted in PHPUnit 1.3.3 stable being installed, which is obviously a fairly old version. Even pear clear-cache didn't seem to solve the issue. I checked to confirm that PEAR was using PHP 5. The only way I was able to get around this was to explicitly specify the latest version.

sudo pear install phpunit/phpunit-3.2.19

The current version of PHPUnit, 3.2.19, also has bugs 482, 483, and 484 related to generating PHPT code coverage reports. I had to apply the patch for bug 482 to fix issues I was having, but the others may also be necessary depending on the code being tested. These issues should be fixed when PHPUnit 3.2.20 is released. In the meantime, if you want to avoid manually applying patches and you're feeling adventurous, you can use an SVN checkout.

As far as I can tell, PHPUnit itself does not contain a runner for its PHPT suite extension. However, there is a runner script to do this in PEAR CVS. Download the script to the directory containing your PHPT test files and execute it with a command similar to this.

phpunit --coverage-html ../Tests-Results \
Console_CommandLine_AllTests AllTests.php

In the case of this particular command, the Tests-Results directory parallel to the directory containing your PHPT files should now contain an index.html file with your test results. There you have it. Happy testing folks!

Page:  1 2 … 7