Version 1.1.2 of the Tutorial

28th November 2006

Just a quick note to let you know that I've updated my tutorial to version 1.1.2. This version fixes the include path and a slew of typos that have been found by Brendon Kozlowski. Thanks Brendon!

Isn't it amazing that even after all the reading that's been done of this tutorial that there are still typos to be found?!

Italian Translation of the Zend Framework Tutorial

24th November 2006

Hot on the heels of the Polish translation, Fabrizio Frosali has released an Italian version!

Thank you very much Fabrizio!

Zend PHP 5 Certification Guide Competition

14th November 2006

I'm still in shock that I've won!

I never expected to be in a position where I could afford to get Zend Certification. I'm gonna have to read the book very carefully though as I have no intention of failing!

Polish Translation of the Zend Framework Tutorial

14th November 2006

I'm extremely pleased to announce that there is now a Polish translation of my Zend Framework Tutorial.

The PHP.pl team did the hard work and I'm very grateful to them. Thanks guys! They are hosting it on their site, so head on over to: Pierwsze kroki z Zend Framework

preg_last_error() returns No Error on preg_match() Failure

13th November 2006

A question came up on a mailing list that I subscribe to that I thought interesting.

Consider this code:

<?php
$result preg_match("/href='(.*)"'blah');
$error preg_last_error();

if($error === PREG_NO_ERROR) {
    echo "No Errorn";
} else {
    echo "An Error Occurredn";
}
var_dump($result);

The output is:

Warning: preg_match(): No ending delimiter '/' found in /var/www/preg_test.php on line 2
No Error
bool(false)

As you can see the pattern passed to preg_match is invalid as it is missing the end delimiter, so intuitively there is an error, but preg_last_error() says that there isn't!

This comes about because preg_last_error() only tells you the last error returned from the PCRE library, rather than the last error from the last call to a preg_* function. The difference is subtle, but important.

To see why this is, we have to go to the source code.

Start at line 840 to discover that the php function preg_match() maps to php_do_pcre_match() in the C code. php_do_pcre_match() is at line 477. This function doesn't do a lot: it does some validation checks and then if all is ok, it calls php_pcre_match_impl() which does the real work.. Or to put it another way, this means that if any of the validation checks fail, then the pcre library isn't called.

One of the validation checks that's done is a function called pcre_get_compiled_regex_cache() which checks that the pattern supplied is a valid. If it's not valid, then an E_WARNING is generated and the function returns NULL (i.e. an error). This causes php_do_pcre_match() to return false. If you are interested, the actual check for an ending delimiter starts at line 256, but make sure you know a bit about C pointers!

So there you have it. An invalid pattern will cause preg_match() to return false and preg_last_error() to return PREG_NO_ERROR.

Thus, you should check preg_last_error() in addition to checking the return value.

Zend_Config Documentation in 0.2

5th November 2006

Note that the documentation for Zend_Config is wrong in version 0.2 of the Zend Framework, as awormus has found out!

Key things to know:

Instantiation

$config = new Zend_Config_Ini('file.ini''section');
Zend_Config_Array has been removed

It's no longer necessary as you can do:

require 'config.php';
$config = new Zend_Config($config);

Inheritence in Zend_Config_Ini has changed
Was:

    [proof]
    extends = common

Now:

    [proof : common]

We'll get the docs sorted soon, sorry!

Update:The wiki version of the manual has been updated thanks to Darby!

Zend Framework Tutorial: Version 1.1

4th November 2006

It turns out that there are hardly any changes required to make the tutorial code compatible with version 0.2 of the Zend Framework! The only changes I had to make were to the index.php file.

The two changes needed were:

Zend_Config construction
You now create a Zend_Config_Ini directly:

$config = new Zend_Config_Ini('./application/config.ini''general');

is all that's needed now!

Front Controller instantiation
For the original tutorial, I needed a special route for compatibility. This is now included by default in 0.2, so the work needed to be done is less. However, I've been playing with setting the rewrite base, and may have a better solution now. The new code for this bit is now:

$router = new Zend_Controller_RewriteRouter();
$baseUrl substr($_SERVER['PHP_SELF'], 0, 
        strpos($_SERVER['PHP_SELF'], '/index.php'));
$router->setRewriteBase($baseUrl);
$controller Zend_Controller_Front::getInstance();
$controller->setRouter($router);

I think it's more likely to work on more configurations than my previous code. If anyone can see a security hole in this particular use of PHP_SELF, please shout though!

The new tutorial (version 1.1.0 - this time I'm prepared for point releases!) is available in the usual place. As always, comments and bug fixes are very welcome!