I’ve just uploaded the slides from my confoo.ca talk “Making software management tools work for you”. You can download the slides from here.
Thanks again to everyone who attended! Please give me feedback on joind.in.
209966 items (235 unread) in 24 feeds
CNN
(10 unread)
MSNBC
(18 unread)
PHP
(16 unread)
Deals
(170 unread)
Tech
(2 unread)
Web Development
(9 unread)
CNN Money
(10 unread)
I’ve just uploaded the slides from my confoo.ca talk “Making software management tools work for you”. You can download the slides from here.
Thanks again to everyone who attended! Please give me feedback on joind.in.
Tuning a webserver in three minutes while it's being slashdotted.
PEAR consists of literally hundreds of packages (libraries) that help you to build your PHP applications faster, less error-prone and more secure. Millions of web applications use and rely on the proper functioning of PEAR packages.
To ensure constant quality, many packages utilize phpt or PHPUnit tests that are run during development and before each release. They help us making sure new features or bug fixes do not break existing functionality.
One of hard to solve challenges is ensuring that a package's unit tests do not only run on the specific PHP version the developers have installed on their machines (which often is the latest and greatest, maybe not even released version from SVN), but to cover the whole range of supported PHP versions. This goal can be achieved in several ways:
Solution number 1 requires either much hardware or at least quite some setup time for virtual machines. Besides that, running tests regularly on many different machines needs automated deployment tools - you won't ssh into the 15th machine manually, let alone setting up database servers and other software that might be required.
There is no single Linux distribution I know of that supports installing multiple versions of PHP beside each other - making solution number 2 similar daunting to setup and running as #1. The benefits above #1 are obvious: All software on one machine means easier deployment because the software to test needs to be setup only once. Software dependencies need to be installed only once. Executing the tests is easier if all versions of PHP are on this single machine, which means that the cross-version tests can be automated really easily.
A tool to solve all problems with the multiple-php-versions-on-one-machine solution is phpfarm. The best way to demonstrate its easiness is probably a shellshot:
$ svn co [svn.php.net] phpfarm $ cd phpfarm/src $ ./compile 5.3.2 ... fetching sources from php.net ... configuring ... compiling ... installing ... fetching and setting up pyrus $ php-5.3.2 --version PHP 5.3.2 (cli) (built: Mar 10 2010 18:08:27) (DEBUG) Copyright (c) 1997-2010 The PHP Group Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies $ pyrus-5.3.2 --version Pyrus version 2.0.0a1 SHA-1: 2FDFB5E00A6D707437DBC047AAF9D115C6484D90 Using PEAR installation found at /home/cweiske/Dev/cvs/pear/phpfarm/inst/php-5.3.2/pear php pyrus.phar version 2.0.0a1.
That's it. With one single command, you can install each version of PHP you like, and you get pyrus, the next-generation PEAR installer for free! Let's try it:
$ pyrus-5.3.2 channel-discover pear.phpunit.de Discovery of channel pear.phpunit.de successful $ pyrus-5.3.2 install phpunit/phpunit ... Installed pear.phpunit.de/PHPUnit-3.4.11 $ pyrus-5.3.2 list-packages Listing installed packages [/home/cweiske/Dev/cvs/pear/phpfarm/inst/php-5.3.2/pear]: [channel pear.phpunit.de]: PHPUnit
phpfarm automatically sets up your php.ini with the values you desire. It sets your include_path. It lets you specify custom configuration options, per patch, minor or major PHP version - just have a look at the README.
Now everything is ready for you (and us PEAR developers!) to let the unit tests run on all the little PHP versions we want to. Did I tell you that phpfarm also installs php-cgi versions? My next blog entry will show you how to run dozens of php versions simultaneously in apache.
If you have questions or suggestions about phpfarm, don't hesitate to ask on the pear-general mailing list (subscription info) or on the #pear IRC channel.
Happy testing!
I’ve been working hard on Goodsie.com lately trying to bring it to launch. It’s been great being in on a new PHP project from (near) the beginning, as it frees up a number of things.
One of those, is the fact that I can be using PHP 5.3 and all the new features that come with PHP 5.3. While I’ve used my fair share of the short-cut ternary already (?:), the bigger win for me, are the Lambda functions with scoping (anonymous functions).
I found a very specific use out of the blue of Lambda functions that I have now used and I see as a great use-case. Which is specifically passing functions/logic from your Controller to your View.
In the case of Goodsie, I’m using PHP for my templating language and as usual I’m trying to remove as much logic from my View as possible, while still allowing the view to be malleable.
The specific case I had, was a subview that was generating some pagination code for me. You know, the standard ‘previous, page 1, page 1, next’ section of links. The basic html template I had, looked looked similar to:
<div class="pagination">
<a href="<?= $baseurl . '/page:' . ($page - 1) ?>">← Previous</a>
Page <?= $page ?> of <?= $total ?>
<a href="<?= $baseurl . '/page:' . ($page + 1) ?>">Next →</a>
</div>
Rather straight forward, but I quickly ran into a problem. The way it worked, as you see, is that you passed in a base URL, and the page number you are currently on, and it generated appropriate forward/back links. (Ok, there was also some other logic where it determined if you needed the prev/next links at all, but I’ve removed that for clarity)
But I then had a case, where I wanted to reuse this subview in an ajax situation. Where instead of straight URL’s being passed in, I might want to pass in a javascript function, and have that function be called with the page number as a parameter. That would be nice as I could use it in both situations. What pagination looked like, could completely change, and still work on both cases. Perhaps we’d want to give a full list of all possible pages. Or show a couple forward/back, etc. The view could handle all of that without a change to the controller.
But therein lied the problem. When using a URL based pagination, I wanted to concat the page number onto the end of the URL. But when using javascript, it wasn’t pure concatenation, it instead needed to wrap the page number with the function call. Oh the pain a simple ) could cause me.
I started writing code, where I ended up with tons of switch statements and logic inside of the view. I’d have to pass in two different possible values, a URL or a javascript function. The view at every point where it would output a link, would need to see which version was being used, and from that decide what type of output to create. In short, it was a mess.
But then the solution dawned upon me. A lambda function would work admirably here. So what I did, is inside of my controller I created a function on the fly, that would generate the appropriate type of link that I was wanting. It looks something like:
if ($jsfunc) {
$url = function ($p) use ($jsfunc) { return "javascript:{$jsfunc}({$p})"; };
} elseif ($baseurl) {
$url = function ($p) use ($baseurl) { return "{$baseurl}/page:{$p}"; };
}
Now I could simply rewrite my original template, to use this lambda function $url to generate it’s URLs.
<div class="pagination">
<a href="<?= $url($page - 1) ?>">← Previous</a>
Page <?= $page ?> of <?= $total ?>
<a href="<?= $url($page - 1) ?>">Next →</a>
</div>
Now not only would this work for my specific situation, but ANY controller could reuse this pagination subview and define exactly how it wanted it’s URLs to be formed. Now, the view could completely change around how the pagination section is displayed, show as many, or as few pages as it wants to, and all that without ever touching the controller.
This is one simple example, but I’ve become enamored of this approach. Using lambda functions in this way, you are able to have complicated logic represented inside of your view, but encapsulated/created by the controller. Also of note is the fact that the view is managing to use the $jsfunc and $baseurl values, but without actually having to be granted access to them. This allows for another level of encapsulation, as I exposed one function,
Truncated by Planet PHP, read more at the original (another 1389 bytes)
Qaiku, the conversational microblogging service that launched a year ago had a refresh that launched today. While it hasn't yet convinced the twittering masses, it has already proven itself as a lot more thoughtful platform for the Finnish online community, and as a valuable workstreaming tool.
The new version looks quite nice and fresh. Notice the privacy information on the right-hand side, which is relevant as Qaiku allows channels and profiles that are private or invitation-only:

Technically the new version is also remarkable as it is the first major website to run fully on top of the legacy-free Midgard2 platform. So yes, every entry you see there is a GObject. And D-Bus signals fly when you post.
On to the challenge, thenTo highlight Qaiku's threading, conversational nature I started a new "On my travels, I have" thread for sharing your most extraordinary travel experiences. This is not on Twitter or Buzz as with Qaiku it is so easy to keep the conversation together and accessible for the future as well.
To contribute, sign up on Qaiku, go to the thread and add your experiences as a comment. If you have a link or picture to include, you can also do so. My first entry was:
seen ice descend from the heavens and provide us with cold beer on a hot day in Lesotho
Will be interesting to see what comes out of this :-)
I'm doing a talk today in the Bossa Conference about using Midgard as a content repository for mobile applications. As part of my presentation I wrote some simple example code for using the Midgard APIs in Python, and thought they would be good to share to those not attending the event as well.
The idea of a content repository is that instead of coming up with new, isolated file formats or database setups for your application you can just work with objects and signals, and let Midgard handle the rest. This is something that lots of people are doing with CouchDB as well, but we feel Midgard, with its light footprint and native APIs for languages like Python, C, Vala and PHP fits better in the mobile applications context.
Installing MidgardMidgard packages are available for many different Linux distributions through the OpenSuse Build Service. To find the right repository for your setup, go to the OBS project page. For example, on my Ubuntu Karmic netbook the URL to add to apt sources.list is deb [download.opensuse.org] ./. Then I just:
sudo apt-get update sudo apt-get install python-midgard2
Midgard is also available in Maemo extras and for OS X on MacPorts.
Defining a schemaThe first thing when developing a Midgard application is to define your storage objects. This is done using the MgdSchema XML format. In this case we're doing a simple "attendee" object that amends Midgard's built-in person record with information related to the conference:
<?xml version="1.0" encoding="UTF-8"?>
<Schema xmlns="http://www.midgard-project.org/repligard/1.4">
<type name="openbossa_attendee" table="openbossa_attendee">
<property name="id" type="unsigned integer" primaryfield="id">
<description>Local non-replication-safe database identifier</description>
</property>
<property name="person" type="unsigned integer" link="midgard_person:id">
<description>Person attending the event</description>
</property>
<property name="registration" type="datetime">
<description>Registration date of the attendee</description>
</property>
<property name="likesbeer" type="boolean">
<description>Whether the attendee likes beer</description>
</property>
</type>
</Schema>
Then we just save this XML file into /usr/share/midgard2/schema/ so that Midgard will find it.
Once the MgdSchema is in place it is time to import antigravity and start hacking in Python. The code works pretty much in the same way in other languages Midgard is available for, but Python is used here for the sake of simplicity. First we load the Midgard extension:
import _midgard as midgard
Then we setup the repository connection. With these settings we will store our content into an SQLite database located in ~/.midgard2/data/midgardexample.db:
configuration = midgard.config() configuration.dbtype = 'SQLite' configuration.database = 'midgardexample' # Open a Midgard repository connection with our config connection = midgard.connection() connection.open_config(configuration)
As this is the first time we're interacting with the repository we need to tell Midgard to prepare the storage for itself and also for our new openbossa_attendee class:
midgard.storage.create_base_storage()
midgard.storage.create_class_storage('midgard_person')
midgard.storage.create_class_storage('midgard_parameter')
midgard.storage.create_class_sTruncated by Planet PHP, read more at the original (another 2314 bytes)
Which CMS does The Real Story Group Use? (Tony Byrne / CMS Watch):
The answer is, we use an open-source platform called "Midgard." We picked it nearly ten years ago, and it has held up fairly well.
...
One of the things we like about Midgard actually makes it rather unsuitable for many simpler publishing scenarios: it is highly object-oriented. This allows us to run multiple sites off largely a single codebase -- at the cost of quite user-unfriendly administrative and authoring facilities.
Also, Midgard is very much a development platform, and we have had to create a fair amount of custom code, especially to handle structured content. In that regard, our CMS experience probably resemble yours. As an industry we remain very far from plug-and-play content management technology for all but the simplest of websites.
While the post contains many negative points about older Midgard (the UIs are a bit better now than they used to be, quite a lot of development has since been happening especially in the LTS branch), it is remarkable that CMS Watch has been able to run their services through the same CMS setup for ten years. This really shows the durability and commitment to long-term stability we have in the Midgard community. We've been doing this for more than ten years, and will likely keep going for quite a bit longer.
As for usability and popularity of Midgard, there is quite little we can do about it in the Midgard1 area, as that is now in long-term support phase that won't allow major changes. But Midgard2 is a new world with new opportunities. Midgard's content repository is pretty much there already, as is the MVC layer, and this spring we should be able to unveil the new, quite revolutionary CMS concept as well. Watch this blog for updates!
Gio = imports.gi.Gio;
Gtk = imports.gi.Gtk;
var f = Gio.file_new_for_path('/home/');
f.enumerate_children_async (
"*",
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT,
null,
function(o,ar) {
// listing completed..
var fe = f.enumerate_children_finish(ar);
var ch = false;
while (ch = fe.next_file(null)) {
Seed.print(ch.get_name());
}
Seed.quit();
},
null);
Gtk.main();
Few weeks ago I got new hardware for my home network, a QNAP TS 119 Turbo NAS.
Together with the release of PHP 5.3.2 by the PHP team I have released Suhosin-Patch 0.9.9.1 which comes with bugfixes and new features. The changes are:
While going through the [HTTP_REFERER] log of the Month of PHP Security website I realised that there are more incoming refers from various blog posts about it than there are submissions to drawing@php-security.org. Like I previously announced we will honor 10 blog postings with 25 EUR amazon coupons. The winners will be selected by random, however only among those we will select that announce their blogpost to us via the email address provided above.
The reasons for this rule is very simple. Without the announcement we would have to look at every new [HTTP_REFERER] and manually check if it is just spam, an old link to the Month of PHP Bugs, someone who just copied the blog of another person or other nonsense. In addition to that we have to find a contact address of the person who originally has written the entry and ask him/her if he/she wants to take part in the drawing. This would be too much work. Therefore announce your blog posting to drawing@php-security.org or you have no chance of winning one of the coupons.
Now that we have WINCACHE 1.1 Beta release which supports user as well as session cache, I am going to tell you a way to integrate session cache with Joomla using WINCACHE. Joomla has the way of integrating session cache based on user cache implementation and that’s what I am going to explain today. Increasing performance of Joomla by enabling it’s user cache functionality using WINCACHE is explained here.
Joomla session code is modular enough and in order to enable session cache based on WINCACHE user cache, one needs to paste the below code in a file named wincache.php and place it at folder libraries joomla\session\storage. This folder path is relative to your Joomla root installation folder.
<?php
// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();/**
* WINCACHE session storage handler for PHP
*
* @package Joomla.Framework
* @subpackage Session
* @since 1.5
* @see [www.php.net]
*/
class JSessionStorageWincache extends JSessionStorage
{/**
* Constructor
*
* @access protected
* @param array $options optional parameters
*/
function __construct( $options = array() )
{ if (!$this->test()) {return JError::raiseError(404, "The wincache extension is not available");
}
parent::__construct($options);
}
/**
* Open the SessionHandler backend.
*
* @access public
* @param string $save_path The path to the session object.
* @param string $session_name The name of the session.
* @return boolean True on success, false otherwise.
*/
function open($save_path, $session_name)
{return true;
}
/**
* Close the SessionHandler backend.
*
* @access public
* @return boolean True on success, false otherwise.
*/
function close()
{return true;
}
/**
* Read the data for a particular session identifier from the
* SessionHandler backend.
*
* @access public
* @param string $id The session identifier.
* @return string The session data.
*/
function read($id)
{$sess_id = 'sess_
Truncated by Planet PHP, read more at the original (another 7501 bytes)
Now that we have WINCACHE 1.1 Beta released which has got implementation for both user and session cache, one can easily take advantage of WINCACHE user cache and increase performance of Joomla. In this post I am going to tell you steps to use WINCACHE user cache with Joomla.
Joomla caching code is modular and in order to enable WINCACHE user cache, one needs to paste the below code in a file named wincache.php and place it at folder libraries\joomla\cache\storage. All the folders mentioned here is with respect to root folder of Joomla installation.
<?php
// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();/**
* WINCACHE cache storage handler
*/
class JCacheStorageWincache extends JCacheStorage
{/**
* Constructor
*
* @access protected
* @param array $options optional parameters
*/
function __construct( $options = array() )
{parent::__construct($options);
$config = & JFactory::getConfig();
$this->_hash = $config->getValue('config.secret');}
/**
* Get cached data from WINCACHE by id and group
*
* @access public
* @param string $id The cache data id
* @param string $group The cache data group
* @param boolean $checkTime True to verify cache time expiration threshold
* @return mixed Boolean false on failure or a cached data string
* @since 1.5
*/
function get($id, $group, $checkTime)
{$cache_id = $this->_getCacheId($id, $group);
$this->_setExpire($cache_id);
return wincache_ucache_get($cache_id);
}
/**
* Store the data to WINCACHE by id and group
*
* @access public
* @param string $id The cache data id
* @param string $group The cache data group
* @param string $data The data to store in cache
* @return boolean True on success, false otherwise
* @since 1.5
*/
function store($id, $group, $data)
{$cache_id = $this->_getCacheId($id, $group);
wincache_ucache_set($cache_id.'_expire', time());
return wincache_ucache_set($cache_id, $data, $this->_lifetime);
}
/**
* Remove a cached data entry by id and group
*
* @access public
* @param string $id The cache data id
* @param string $group The cache data group
* @return boolean True on success, false other
Truncated by Planet PHP, read more at the original (another 10114 bytes)
The old and fairly reliable Sennheiser RS40’s I was using up until a few weeks ago finally gave up the ghost in the run-up to Mobile World Congress this year – or to be more accurate, the battery packs finally…
In previous articles, I've explored building service endpoints and RESTful services with Zend Framework. With RPC-style services, you get to cheat: the protocol dictates the content type (XML-RPC uses XML, JSON-RPC uses JSON, SOAP uses XML, etc.). With REST, however, you have to make choices: what serialization format will you support?
Why not support multiple formats?
There's no reason you can't re-use your RESTful web service to support multiple formats. Zend Framework and PHP have plenty of tools to assist you in responding to different format requests, so don't limit yourself. With a small amount of work, you can make your controllers format agnostic, and ensure that you respond appropriately to different requests.
Since the WinCache Extension for PHP has been released last year it has been widely deployed by customers who run PHP on Windows OS and it has proven to provide a substantial performance boost for PHP applications hosted on Windows-based web servers.
Today IIS team has published a beta of WinCache 1.1, which provides more options for improving performance of PHP applications on Windows. Specifically, the new version includes :
The beta builds of the extension can be downloaded and installed from the extension home page at: [www.iis.net] (look for the “WinCache 1.1 – Beta” section there). The source code can be obtained from [pecl.php.net] . The documentation for the extension can be found on PHP.NET WinCache documentation.
This is the beta release and the WinCache team is looking for your feedback on new features and functionality. Use the WinCache Community Forum to ask questions about the extension, report bugs and problems and to suggest features and improvements.
Since the WinCache Extension for PHP has been released last year it has been widely deployed by customers who run PHP on Windows OS and it has proven to provide a substantial performance boost for PHP applications hosted on Windows-based web servers.
Today IIS team has published a beta of WinCache 1.1, which provides more options for improving performance of PHP applications on Windows. Specifically, the new version includes :
The beta builds of the extension can be downloaded and installed from the extension home page at: [www.iis.net] (look for the “WinCache 1.1 – Beta” section there). The source code can be obtained from [pecl.php.net] . The documentation for the extension can be found on PHP.NET WinCache documentation.
This is the beta release and the WinCache team is looking for your feedback on new features and functionality. Use the WinCache Community Forum to ask questions about the extension, report bugs and problems and to suggest features and improvements.
Configuring PHP is easy. You can change almost any aspect of the interpreter within the php.ini configuration file, e.g. modify error handling, increase memory usage, etc.
Unfortunately, problems can occur when you move your application to a live hosting environment or are distributing the code to customers. ISPs usually lock down the php.ini configuration file — especially on shared hosting. This could cause your application to fail.
Fortunately, it’s not necessary to upgrade to an expensive dedicated server. The two methods below allow you to override PHP settings within your application.
Apache Module DirectivesThe majority of ISPs provide Apache web server hosting on Linux or Unix platforms. Hopefully, they’ve also granted “AllowOverride Options” or “AllowOverride All” privileges in Apache’s [httpd.conf] configuration. This allows you to create an .htaccess file within your application’s root folder overrides the default Apache and PHP configuration.
Two PHP directives are permitted within .htaccess:
php_flag should be used for on/off values, whereas php_value can be used for any others. For example, the following .htaccess file will disable globals, set the maximum file upload size to 20MB, and allow PHP scripts to run for 10 minutes (600 seconds):
php_flag register_globals off
php_value upload_max_filesize 20M
php_value max_execution_time 600
However, the solution will not work in all Apache installations or other web servers such as IIS.
PHP Runtime ConfigurationA more portable, server-agnostic solution is PHP’s ini_set function. — it allows you to change a setting within your application at runtime. The function accepts two arguments: ini_set(flag-name, flag-value), e.g.
<?php
ini_set('register_globals', 0);
ini_set('upload_max_filesize', '20M');
ini_set('max_execution_time', 600);
?>
Booleans, numbers and strings can be used interchangeably — PHP will attempt to cast the value to an appropriate type.
Several related functions are available:
ini_get(flag-name)
Returns the configuration value. I’d recommend checking your configuration change and taking appropriate action. Don’t assume ini_get() will always work.
ini_get_all([extension])
Returns all configuration values as an associative array. The optional extension parameter returns options specific to that extension, e.g. ‘allow_url_fopen’.
get_cfg_var(flag-name)
Returns the original configuration value from php.ini (not any overrides set in .htaccess or by ini_set).
ini_restore(flag-name)
Returns a configuration option to its original value.
Coming soon: How to Handle Unloaded PHP Extensions.
Has PHP configuration ever caused you problems when porting an application to another server?
<script src="http://adscluster.aws.sitepoint.com/openx/adjs.sp.php?region=14&did=adz&adtype=vertical" type="text/javascript">Related posts:
Update, 2010-03-04: I just rolled a 0.0.2 release. In case you had 0.0.1 installed, just use pear upgrade-all to get it automatically. This release is trying to fix a random hang while reading documents from the source server.
I also opened a repository on Github.
---
As some may have guessed from a previous blog post we are currently running a test setup with CouchDB lounge. My current objective is to migrate our 200 million documents to it, and this is where I am essentially stuck this week.
No replication, no bulk docsThe lounge currently does not support replication (to it) or saving documents via bulk requests, so in essence migrating a lot of data into it is slow and tedious.
I have yet to figure out if there is a faster way (Maybe parallelization?), but DB_CouchDB_Replicator is the result of my current efforts.
I think I gave up on parallelization for now because it looked like hammering the lounge with a single worker was already enough, but generally I didn't have time to experiment much with it. It could have been my network connection too. Feedback in this area is very, very appreciated.
DB_CouchDB_ReplicatorDB_CouchDB_Replicator is a small PHP script which takes two arguments, --source and --target. Both accept values in style of http://username:password@localhost:port/db and attempt to move all documents from source to target.
Since long running operations on the Internet are bound to fail, I also added a --resume switch, and while it's running it outputs a progress bar, so it should be fairly easy to resume. And you also get an idea of where it's currently at and how much more time it will eat up.
These switches may change, and I may add more — so keep an eye on --help. Also, keep in mind, that this is very alpha and I give no guarantees.
Installation is simple! :-)
apt-get install php-pear
pear config-set preferred_state alpha
pear channel-discover till.pearfarm.org
pear install till.pearfarm.org/DB_CouchDB_Replicator
Once installed, the replicator resides in /usr/local/bin or /usr/bin and is called couchdb-replicator.
The code is not yet on github, but will eventually end up there. All feedback is welcome!
I’m reinvestigating Doctrine and Zend Framework for a new project. I’d dismissed them last year as not meeting my needs, but am giving it another go this year. I have to say I’ve got mixed impressions at best, as there seems to be little in the way of documentation with real use cases.
I would have expected there to be some explicit reference to how to set this up, but the best I can find are general examples where the Doctrine models directories are appended to the include_path in a ZF index file. Shouldn’t there be a way to explicitly have the Doctrine subsystem react to requests for models as well?
I was expecting the Doctrine::autoload to look for the classes on the ‘models path’ set via Doctrine::setModelsDirectory() call, but it doesn’t.
Hrm… after more investigation, it seems there’s a ‘modelsAutoload’ method on the Doctrine_core which will automatically look at the models_path set via setModelsDirectory(). Almost what I need. Except…(!)
There’s no support for multiple directories. The standard Doctrine generation process creates a ‘BaseFoo’ object in a ‘generated’ directory below where the standard ‘Foo’ file is written. The ‘Foo’ file subclasses the BaseFoo, but there’s no support to have it autoloaded.
In my ‘_initDoctrine()’ in Bootstrap, I’ve got
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader(array('Doctrine','modelsAutoload'));
I know what to do here! I thought to myself. I’ll subclass Doctrine’s Core (which is what’s referenced by the ‘Doctrine’ above) and have that be the autoloader to use. I’ll modify the modelsAutoload() method to deal with an array of $_modelsDirectory entries, and attempt to load from each of them. Except…(!)
$_modelsDirectory is *private*. I can’t modify it in a subclass, nor is there a get() method on the Core class to access it. There’s a *set* method (setModelsDirectory()) but no get! So, I’m rather forced to go through modifying the Doctrine Core to get the behaviour I want, in the simplest form. I’ve been trying to followup on some other postings about getting autoload to work with Doctrine-generated models, but they seem incomplete (to me anyway) or suggest to modify how Doctrine generates its class names (doesn’t seem simple or straightforward to me at all). Having Doctrine core be able to deal with an array of paths to check for models would be the simplest, especially given that Doctrine *forces* this issue on you by generating classes in different directories by default.
Crux of the code is:
Doctrine/Core.php line 1142
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | if(is_array(self::$_modelsDirectory)) {
foreach(self::$_modelsDirectory as $dir) {
$class = $dir . DIRECTORY_SEPARATOR "/> |
Truncated by Planet PHP, read more at the original (another 4098 bytes)
Over the years I’ve played key roles in many software projects. Although I have had many successes there are only a few which were truly memorable. On average I probably do a very exciting project every three years. I would say that’s above industry standards :)
Last week we released Zend Server 5 and it is another memorable moment for me. Not because the process of getting it out the door was all smooth (it sometimes felt like pulling teeth) or because it’s a new major version of Zend Server.
It’s because the new code tracing feature gets me very excited and is a kickass technology. Code tracing solves real problems for developers and IT operation teams. One of the biggest challenges in managing production environments is troubleshooting problems. Whether it is an application that runs transactions against a database, calls Web Services, or interoperates with a Java app server, being able to reproduce the problem after the fact is very often hard and sometimes just impossible. Working on such problems has always killed my productivity and reduced the amount of time I could truly be focused on writing new code.
This is where code tracing comes in. It’s a very cool technology that is optimized to run in production and can keep track of what’s happening deep within the PHP application. It hooks into our event system that tracks DB events, slow scripts, errors, and more. When something goes wrong it can dump a snapshot of the whole execution flow – function calls, arguments, return values, memory consumed, duration – from the beginning of the request to the point where the error occurs. This enables developers to analyze and triage the problem after the fact – easily and efficiently. Best of all – while it’s targeted at production (high performance and robust) it’s also extremely useful during development and testing.
What makes this feature even cooler is that Adobe worked closely with us to build a really nice Flex UI ( [static.zend.com] ) for analyzing code tracing. It feels good to have stable and efficient production technology, but it’s even better when there’s visualization that enables the users to interact with the data quickly and effectively. Thanks to Adobe for helping us build a superb UI! This is just the first version of the UI – the sky’s definitely the limit with where this can go.
I am proud of what we’ve built and the people who participated in building it. I have no doubt that it will lead to tremendous time savings for PHP shops and make developers’ lives significantly easier and happier. I just hope I don’t need to wait another three years now for the next big thing… I bet not!
Just about finished a gumblar cleanup, for a small Hong Kong company. This is not the first crack I've seen in the last few months, I fixed another server last month that got ssh brute force attacked. It looks like cracking is on the up, so if you need help fixing a site, by someone who knows what they are doing, and at the same time you will help out a number of open source projects - give me a bell (alan@akbkhome.com)
The gumblar (or derivative) attack I was looking at was quite interesting, the first indication the owner got was that browsers kept showing the "Reported Attack Site!" or "Warning: Visiting this site may harm your computer" message. So I get the call to find out what's going on.
When you ignore the message and go through to the site, look at the html the first thing you see is that there is a <script> tag added just before the body pointing to a gifimg.php file. After that you have a long hunt around google to find out what's going on.
At the time of writing, the exact attack vector does not look like it's been confirmed, but is either a brute force ftp attack (I think is quite unlikely considering the username/pass combo on this sample site). Or more likely a PDF desktop attack to a machine that has access to the site.
My first assumption was that it was a Wordpress exploit, but the more I examined the situation, it seemed less likely. However I highly suspect that the PDF attack vector having got the ftp credentials goes looking for standard locations of wordpress installations (eg. '/wordpress) - so hint one is not to install your software in such obvious places.
Cleaning it out
The first step in sorting out the mess was to mirror the original site, with virus and all onto a offline location. (both as a precaution that if we broke things we had a backup, and so we can use this as a source to replace the hacked files with new ones).
After that it was a matter of googling for details of the attack and writing a gumblar cleaner script. It basically checks for infected file types, then preg_replaces out the hacked additions. These include
I used ftpput, and check return values, to ensure that each file was successfully replaced before overwriting the local copy and making a nice copy for my reference into the virus folder.
Inside out of the attack.
The infection is quite interesting, and in this case was quite painful, due to the nature of how Wordpress publishes files.
Initially I suspect the core code in the PDF actually has some ftp code which will try and modify standard set of PHP files to add a small base64_encode script.. (phplist, and wordpress appear to be core targets, and I'm sure there are more.)
This is a snippet of some of the code that get's added (it's all eval, base64_encoded - read up on my blog post about idiot ways to protect your PHP code using this idea.)
This is a snippet of the decoded script
if(!function_exists('kqyf')){
function kqyf($s){
... infect the page stuff goes here...
}
function kqyf2($a,$b,$c,$d){
global$kqyf1;
$s=array();
if(function_exists($kqyf1))
call_user_func($kqyf1,$a,$b,$c,$d);
foreach(@ob_get_status(1)as$v)
if(($a=$v['name'])=='kqyf')
return;
elseif($a=='ob_gzhandler')
break;
else
$s[]=array($a=='default output handler'?false:$a);
for($i=count($s)-1;$i>=0;$i--){
$s[$i][1]=ob_get_contents();
ob_end_clean();
}
ob_start('kqyf');
for($i=0;$i<count($s);$i++){
ob_start($s[$i][0]);
echo $s[$i][1];
}
}
}
$kqyfl=(($a=@set_error
Truncated by Planet PHP, read more at the original (another 1041 bytes)
Achtung! Neuer Termin: 04. März 2010
On a number of occasions I have found myself needing to assemble a daemon process for some type or processing done using Ruby. Each time I roll things a little different and I finally started to wonder if someone had already put together tools for doing the daemon parts. After some quick digging I ran into Daemon-Kit and after adding it together with a couple other tools it seems like what I've needed. I've put together a few recipes here to help guide others who might be looking for something similar.
Creating a simple daemon is easy. This is a simple walk through so look at the project's documentation for much more information. First you will need to get the gem installed:
gem install daemon-kit
After the gem is installed you create a daemon with the following command:
daemon-kit asimple
Now you have some generated code in the asimple directory. In that directory you will find a README that tells you want each directory is used for. The main file to look at for this example is:
libexec/asimple-daemon.rb
A fresh file will have a lot of comments in it pointing you in the right direction. Here is a modified version where I'm displaying the contents of /tmp over and over:
DaemonKit::Application.running! do |config|
end
loop do
DaemonKit.logger.info Dir.entries('/tmp/').join(' ')
sleep 5
end
To run the daemon you would use a command like the following:
RUBYOPT=rubygems ./bin/asimple
The documentation found in the project is great so look there for more information. There is a lot of flexibility built in like multiple environment support and command line options. The daemons and angels blog post is educational and worth a read for more on the basics of daemon-kit.
After experimenting for a while I think I may want to go back and redo the live segmenter so that it uses daemon-kit instead of my hand rolled process. That is probably a good example of where the simple functionality comes in.
An event driven daemon with RabbitMQ
What tilted me towards looking into Ruby daemon options was actually another event driven process I was thinking about. As it turns out daemon-kit supports creating evented daemons as well. I picked RabbitMQ for the following example but anything that supports AMQP should work. I'm going to assume you have RabbitMQ installed already.
First off you need to install the AMQP gem:
gem install eventmachine gem install amqp
At this point you might want to verify that you can connect to your MQ server using some AMQP examples.
To generate an event based daemon use the following command:
daemon-kit -i amqp eventbased
For some reason the generated code didn't work right out of the box for me but a slight modification fixed the issue. I added the following to the top of the config/environment.rb file:
require 'amqp' require 'mq'
Again the file generated in libexec is the starting point and gives you good hints as to where you want to start. I've modified my example above to take a directory to gather the contents of and respond with those contents as another message:
DaemonKit::Application.running! do |config|
end
DaemonKit::AMQP.run do
amq = ::MQ.new
amq.queue('dir_request').subscribe(:ack => true) do |h, msg|
h.ack # just ack the message
DaemonKit.logger.debug "Received message: #{msg.inspect}"
amq.queue('dir_response').publish(Dir.entries(msg).join(' '))
end
end
One thing to note is that I've set the message queue to require an acknowledgement for each message. I did this to simulate a process that requires that each request be executed once. Now all that is needed is a simple application to produce request messages and display the response:
require 'rubygems
Truncated by Planet PHP, read more at the original (another 7600 bytes)
Just about finished a gumbar cleanup, for a small Hong Kong company. This is not the first crack I've seen in the last few months, I fixed another server last month that got ssh brute force attacked. It looks like cracking is on the up, so if you need help fixing a site, by someone who knows what they are doing, and at the same time you will help out a number of open source projects - give me a bell (alan@akbkhome.com)
The gumbar (or derivative) attack I was looking at was quite interesting, the first indication the owner got was that browsers kept showing the "Reported Attack Site!" or "Warning: Visiting this site may harm your computer" message. So I get the call to find out what's going on.
When you ignore the message and go through to the site, look at the html the first thing you see is that there is a <script> tag added just before the body pointing to a gifimg.php file. After that you have a long hunt around google to find out what's going on.
At the time of writing, the exact attack vector does not look like it's been confirmed, but is either a brute force ftp attack (I think is quite unlikely considering the username/pass combo on this sample site). Or more likely a PDF desktop attack to a machine that has access to the site.
My first assumption was that it was a Wordpress exploit, but the more I examined the situation, it seemed less likely. However I highly suspect that the PDF attack vector having got the ftp credentials goes looking for standard locations of wordpress installations (eg. '/wordpress) - so hint one is not to install your software in such obvious places.
Cleaning it out
The first step in sorting out the mess was to mirror the original site, with virus and all onto a offline location. (both as a precaution that if we broke things we had a backup, and so we can use this as a source to replace the hacked files with new ones).
After that it was a matter of googling for details of the attack and writing a gumbar cleaner script. It basically checks for infected file types, then preg_replaces out the hacked additions. These include
I used ftpput, and check return values, to ensure that each file was successfully replaced before overwriting the local copy and making a nice copy for my reference into the virus folder.
Inside out of the attack.
The infection is quite interesting, and in this case was quite painful, due to the nature of how Wordpress publishes files.
Initially I suspect the core code in the PDF actually has some ftp code which will try and modify standard set of PHP files to add a small base64_encode script.. (phplist, and wordpress appear to be core targets, and I'm sure there are more.)
This is a snippet of some of the code that get's added (it's all eval, base64_encoded - read up on my blog post about idiot ways to protect your PHP code using this idea.)
This is a snippet of the decoded script
if(!function_exists('kqyf')){
function kqyf($s){
... infect the page stuff goes here...
}
function kqyf2($a,$b,$c,$d){
global$kqyf1;
$s=array();
if(function_exists($kqyf1))
call_user_func($kqyf1,$a,$b,$c,$d);
foreach(@ob_get_status(1)as$v)
if(($a=$v['name'])=='kqyf')
return;
elseif($a=='ob_gzhandler')
break;
else
$s[]=array($a=='default output handler'?false:$a);
for($i=count($s)-1;$i>=0;$i--){
$s[$i][1]=ob_get_contents();
ob_end_clean();
}
ob_start('kqyf');
for($i=0;$i<count($s);$i++){
ob_start($s[$i][0]);
echo $s[$i][1];
}
}
}
$kqyfl=(($a=@set_error_ha
Truncated by Planet PHP, read more at the original (another 1038 bytes)
Continuous integration is all the rage these days; you are unit testing your code are you not? During some consulting in January with the help of Sebastian Bergmann, from thePHP.cc, we setup continuous integration utilizing Atlassian Bamboo and received training on PHPUnit.
Using Atlassian Bamboo for continuous integration will take you a bit to setup, however, I have found it to be an invaluable tool when utilizing the Atlassian stack (JIRA, Confluence, Crucible, Bamboo and Crowd).
OverviewThis posting assumes the following:
This posting will go over the following:
Welcome to the voyage of continuous integration with Bamboo, now that you are ready, lets get started.
Installing the PHP ToolsWe will assume using the PEAR installer for installing all of the tools.
PHP Dependpear channel-discover pear.pdepend.org
pear install pdepend/PHP_Depend-beta
pear channel-discover pear.phpunit.de
pear install phpunit/PHP_CodeBrowser-alpha
pear install PHP_CodeSniffer
pear install phpunit/phpcpd
pear channel-discover pear.phpmd.org
pear install --alldeps phpmd/PHP_PMD-beta
pear install phpunit/PHPUnit
There are a few plugins that we will utilize to capture build metrics. You will want to install these to follow along:
Plan DetailsAssuming that you are new to Bamboo and have not created a build as of yet, you will need to login to Bamboo and then click on “Create Plan” in the navigation. Here you will find a few options, most of these are self explanatory. Just remember that you can have several different builds so you may want to specify if it is a trunk build or a specific component build. Once you are completed, click on next.
Source RepositoryPut in the details to your source code repository. If the source code repository is not available, there is likely a plug-in for it available. Download it, restart bamboo, and continue to this step. We do not force a clean build every time, this is due to some additional configuration that we have set for an environment in a configuration file and to reduce the amount of time to do a build. Lastly, we do polling to detect if we need to do a build. This helps us because we do not want a 5 minute build during every change but rather within 10 minutes of any change. This helps reduce building too frequently or causing a potential for a race condition (assuming there was a bug in Bamboo). Go to the next step…
BuilderLet’s use ant for the build process. Do not worry about this for now, we will get more into the ant build script later on. State the build file as “build.xml” which will live in the main root of the source code (you could place this elsewhere but for simplicity sakes lets put it here and assume you’re not storing the htdocs at the root – please tell me you’re not). Under target place “clean build” since we will do some manual cleanup of existing build information.
Under the following questions you will want to fill out information:
Truncated by Planet PHP, read more at the original (another 21234 bytes)
(This is just a quick note to get some information out there for reference, I am adding it to the PHP manual as well!)
Currently, in PECL/Cairo the only way to draw text is the referred to as the "toy" text API, which is a very basic way of handling text compared to the facilities available in the Cairo library itself. However, it's sufficient for most purposes that I've come across so far. In version 0.1.0 of PECL/Cairo, there was only one way to choose what font you wished to use, which was the CairoContext::selectFontFace() method. You pass a string to this method with the name of the font you want, along with the optional slant and weight parameters. This then invokes your system's font handling to find the font you're after, or an alternative if it's not available, so you need to have the font you want installed into your system's font library.This is occasionally not handy.
In version 0.2.0 FreeType support was added. It allows you to choose any font file you'd like, as long as PHP's streams API can find it. Yes, this means 'http://' streams, but I wouldn't recommend it.
<?php
/* Set up the surface, and make the background white */
$s = new CairoImageSurface(CairoFormat::ARGB32, 300, 100);
$c = new CairoContext($s);
$c->setSourceRgb(1, 1, 1);
$c->paint();
/* Draw the text using the Vollkorn font, from
[friedrichalthausen.de] */
$c->setSourceRGB(0, 0, 0);
$c->moveTo(10, 60);
$f = new CairoFtFontFace(dirname(__FILE__) . "/vollkorn.otf");
$c->setFontFace($f);
$c->setFontSize(50);
$c->showText("Hello world");
/* Send the image to the browser */
header("Content-type: image/png");
$s->writeToPng("php://output");
?>
The output image should hopefully look like this:

(For those who are familiar with the Cairo library, this function maps to the cairo_ft_font_face_create_for_ft_face function in its API.)
There is still some work to be done in this area, notably to support the Windows and Mac OS X font systems, but they'll be coming in a future release, we hope. If anyone would like to help us with that, or any other aspect of it (including documentation!), you can get in touch on the PECL dev mailing list, or if you're on IRC, drop in to #php.pecl on EFnet. All contributions are welcome!
Thanks to everyone that came along to my talk about integrating search engines at the wonderful PHP UK 2010. The slides are available over at Slideshare. It was great speaking to so many people afterward about the challenges and solutions they've found with various engines, and the conference itself was top notch - congratulations to the organisers.
I'll be giving a (slightly shortened) version of the same talk at the Dutch PHP Conference 2010, which June 10-12th in the ever lovely Amsterdam. The schedule is absolutely chocker with great talks, from people like Elizabeth Naramore, Helgi, Thijs, Derick, Johannes and a load more. I'm particularly looking forward to Marcus' talk on geo data, and I would be looking forward to Sam de Freyssinet's talk on HMVC, except it's on at the same time as mine!
I've just released Xdebug 2.1.0beta3 which includes a few crash bugs as well as the issue that headers sent from PHP scripts are not actually set.
You can find the full changelog here and get the latest version from the download page.
Everyone who cares about security will remember the Debian Openssl disaster in 2008. The debian developers had patched their version of openssl to fix compiler warnings. This resulted in a broken random number generator that made all keys generated by Debian systems predictable. One would think that Debian developers are more careful with patching “bugs” in security tools since that day.
However two days ago I finally installed a mail client on my reinstalled desktop system and checked mails of the hardened-php account that were not checked for 2 months, because usually noone uses this account to email me. While killing thousands of SPAM messages I also found a message from the Debian PHP maintainers, dating back to the 10th February 2010, telling me about a crash problem inside the Suhosin patch. The email also contained their solution to the problem: a patch for the suhosin patch. You can view this patch here. However you should not commit this patch to your PHP because it breaks Suhosin’s security.
I previously blogged about one of the new features in Suhosin Patch for PHP 5.3.x. It is now possible to adjust several internal features by setting certain environment variables on startup. This includes the memory manager canary protection, the sanitization of free memory blocks, the protection of linked lists and hashtables. When a Suhosin patched PHP starts the environment variables are evaluated and the suhosin config is written into a variable called suhosin_config.
It should be obvious that this kind of feature comes with a little problem. Certain bytes in memory now control if Suhosin’s internal memory protections are activated or not. This means that a memory corruption vulnerability in PHP could be used by an attacker to overwrite the config variable and disable the security. Because of this Suhosin Patch tries to align the suhosin_config variable to a page boundary and then set it to read only.
/* hack that needs to be fixed */
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#ifdef ZEND_WIN32
__declspec(align(PAGE_SIZE))
#endif
char suhosin_config[PAGE_SIZE]
#if defined(__GNUC__)
__attribute__ ((aligned(PAGE_SIZE)))
#endif
;
static void suhosin_write_protect_configuration()
{
#if defined(__GNUC__)
mprotect(suhosin_config, PAGE_SIZE, PROT_READ);
#endif
}
The implementation has some problems. First of all it only works in case of a GNU C compiler. The second and more serious problem is that it assumes that the PAGE_SIZE is smaller than or equal to 4096. Otherwise mprotect() will not correctly work. On systems where the PAGE_SIZE is bigger than 4096 the mprotect() will either fail or set too many bytes to read only. In case of a write access after the suhosin_config variable this can lead to a crash.
The Debian people saw this crash on some architectures and reacted with a patch. However they do not understand the security feature and therefore their patch looks like this.
char *suhosin_config = NULL; static void suhosin_write_protect_configuration&
Truncated by Planet PHP, read more at the original (another 2834 bytes)
Two days ago I installed a mail client on my reinstalled desktop system that was not doing anything for 2 month and checked mails of the hardened-php account that were not checked for 2 months. Usually noone uses this email account to contact me, but the Suhosin bug reports sometimes end up there. While killing thousands of SPAM messages I also found a message from the Debian PHP maintainers, dating back to the 10th February 2010, telling me about a crash problem inside the Suhosin patch. The email also contained their solution to the problem: a patch for the suhosin patch. You can view this patch here. However you should not commit this patch to your PHP because it does not solve the problem correctly.
I previously blogged about one of the new features in Suhosin Patch for PHP 5.3.x. It is now possible to adjust several internal features by setting certain environment variables on startup. This includes the memory manager canary protection, the sanitization of free memory blocks, the protection of linked lists and hashtables. When a Suhosin patched PHP starts the environment variables are evaluated and the suhosin config is written into a variable called suhosin_config.
It should be obvious that this kind of feature comes with a little problem. Certain bytes in memory now control if Suhosin’s internal memory protections are activated or not. This means that a memory corruption vulnerability in PHP could be used by an attacker to overwrite the config variable and disable the security. Because of this Suhosin Patch tries to align the suhosin_config variable to a page boundary and then set it to read only.
/* hack that needs to be fixed */
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#ifdef ZEND_WIN32
__declspec(align(PAGE_SIZE))
#endif
char suhosin_config[PAGE_SIZE]
#if defined(__GNUC__)
__attribute__ ((aligned(PAGE_SIZE)))
#endif
;
static void suhosin_write_protect_configuration()
{
#if defined(__GNUC__)
mprotect(suhosin_config, PAGE_SIZE, PROT_READ);
#endif
}
The implementation has some problems. First of all it only works in case of a GNU C compiler. The second and more serious problem is that it assumes that the PAGE_SIZE is smaller than or equal to 4096. Otherwise mprotect() will not correctly work. On systems where the PAGE_SIZE is bigger than 4096 the mprotect() will either fail or set too many bytes to read only. In case of a write access after the suhosin_config variable this can lead to a crash.
The Debian people saw this crash on some architectures and reacted with a patch. However they did misunderstand the security idea behind it and therefore their patch looks like this.
char *suhosin_config = NULL;
static void suhosin_write_protect_configuration()
{
#if defined(__GNUC__)
mprotect(suhosin_config, sysconf(_SC_PAGESIZE), PROT_READ)Truncated by Planet PHP, read more at the original (another 3081 bytes)
I previously blogged a sneak preview of the Month of PHP Security which is a new initiative to improve security in the PHP ecosystem. Today the call for papers was released. Everyone from the PHP and security community is invited to produce quality articles/advisories about PHP security topics/bugs and submit them to the CFP committee.
The event is generously sponsored by Syscan, SektionEins and CodeScan. And the best submissions can win a number of attractive prizes. The first prize consists of 1000 EUR, a free Syscan ticket and a free CodeScan PHP License. For a full list of the submissions accepted and prizes available check out the website.
In case you are not a PHP security expert you can still help to improve the event. Spread the word about the Month of PHP Security in your blog, link to it and announce your blog posting at drawing@php-security.org and win one of ten 25 EUR amazon coupons.

I'm happy to say that I'll be speaking at the Dutch PHP Conference in June in Amsterdam, on the subject of the PECL/Cairo extension I've been helping out by working on for the past few months. This will be my first appearance as a speaker at a technical conference so I'm a little nervous, but I've no doubt I'll be practicing a bit before it happens. Apologies in advance to anyone I inflict the talk on before the event.

Gearman is a lightweight, high-performance solution for farming out processing work from one machine to another. I’m currently looking at using Gearman as a key part of the architecture of a new web API that I’m doing the R&D for. (I’ll go into why I need something like this, and why I’ve chosen Gearman in particular, another day).
Getting Gearman up and running on Ubuntu 9.10 (Karmic Koala) is very straight-forward and only takes a few minutes, but oddly not clearly documented on Gearman’s own wiki at the time of writing.
You’ll find that the gearmand process is already up and running, and listening on port 4730 on localhost. All you need to do now is to write some code to take advantage of it
I really enjoy giving talks. This is particularly because I like to teach people something and because I’m really enthusiastic about the technical things I talk about. Once of these things are obviously decentralized version control system, in particular Git and Mercurial. Finally after two years of submitting talks to various conferences, people and conferences in the PHP community start to pick up this topic. Seems that 2010 is the year of DVCS, and I’m really looking forward to give a talk about the advanced features of Git at
The talk will give a very brief overview how Git works, and will then give a more detailed insight in how Git handles commits, files, etc so that people get a very good understanding about the concepts that are needed to fully understand tools like git rebase, git reflog and git svn. The aim is to provide them will all necessary information and a few examples to get lost commits back, rebase their branches and design more complex git workflows in the future without needing to search the web or ask a guru.
A second talk will be more focused on beginners and developers coming from subversion. This talk will be part of a series of talks the german telekom is organizing. I’ll also give an extended version of this as an in-house workshop at a Munich based company.
So for me it seems that after five years, DVCS is mature enough to get into companies and that we can expect a bright variety of companies to adopt new tools and workflows. Let’s see what’s coming…
probably shameless self promotion
Last week we published an article with different methods to hide e-mail addresses on websites. Because of several comments with suggestions on how-to solve this problem, we provide this week a solution which is “from these days” and more powerful.
Based on the idea if you don’t show an address, a spambot can’t see it, we use in our example a simple Ajax call (using jQuery) and show a tiny box with some friendly message including the link with e-mail address.
DEMO: We used the code from this tutorial on the this page.
First we need to create a simple php file that holds the content and the e-mail address, we use json_encode to make the string less readable:
<?php
// change the two vars below
$email = 'user@mail.com';
$html = 'Please contact us by e-mail: <a href="mailto:%%mAdr%%">%%mAdr%%</a><br /><br />
<a href="javascript:void(0);" id="hideme">Close</a>';
$eparts = explode('@', $email);
$data = array('ename'=>$eparts[0], 'dom'=>$eparts[1], 'htmlcode'=>$html);
echo json_encode($data);
?>
Don’t forget to block that file in your robots.txt file!
Now we need a function that will load the external content into the current page using an Ajax request.
$(document).ready(function() {
$("#clickme").live('click', function() {
$.ajax({
url: 'glink.html',
dataType: "/>Truncated by Planet PHP, read more at the original (another 8358 bytes)
Yesterday, I was very excited to announce that PHPWomen will be partnering with Open Source projects who foster open, friendly and respectful communities. We work with project leaders for these projects to identify specific areas where they can use the most help, then we, in turn, promote these opportunities to PHPWomen members. The result is that we get more women involved in contributing to open source, open source projects get the help they desperately need, and everybody goes home happy.
It's interesting to note that while we ask that a project provide a Statement of Diversity, or other similar language somewhere on the site, this is not always easy to do. I understand some hesitation in putting this idea in writing, and if a project leader instead can assure me that our members won't be harassed by a bunch of assholes, then I'm okay with that. By linking the PHPWomen name with your project, we're putting faith in the fact that you will treat everyone (male and female) with respect and as a valued member of the community.
I've been asked by more than one person why a Statement of Diversity is needed, when that should be the default. It should be obvious that everyone is respectful and treats all others equally. My answer to that is yes, it *should be obvious*. But it's not. Consider this. If you take the time to dedicate a page of your site, or even write up language that suggests your community embraces diversity, is open, friendly, and doesn't tolerate disrespect or discrimination based on anything, then that tells me that this is a priority for you. It sets the tone for your community. It clearly identifies your stance on the matter. If I come to your site, and I don't see anything anywhere that mentions how you treat newcomers, then for me to assume you're going to welcome me and my contributions with open arms ... well that's a big assumption to make. So while we don't require it, we do appreciate those that take the time to clarify the culture of their communities.
We already have 6 projects that have partnered with us, and are in discussions with numerous others. We are proud to partner with these awesome projects, and you can read more about them or see what specific opportunities they have:
If you are the project leader of an awesome Open Source project, and you'd like to be included on our list, by all means give me a shout at Elizabeth.at.Naramore.dot.net. And if you have considered contributing to open source, but you aren't sure where to start, then check out the wonderful opportunities that are out there!
I've been a big fan of Subversion since 2005, but since lately I've been having a bit of distributed source-control envy. Many people seem to be switching to Git and Mercurial, and frankly I've felt a bit left behind.
For some smaller stuff I've been starting to use Mercurial a bit more, and I've been pretty easily convinced since then. If you have some random code lying around, and need to make some changes you might need to revert? Just enter "hg init ." and now it's a repository. hg add, hg commit and it's committed as a first repository.
So I've bit the bullet and now also converted SabreDAV to Mercurial, which was a very easy process using Google's manual (which by the way could apply for non-google repo's too). The biggest change from here on is to remember to type hg instead of svn.
Joel Spolsky actually recently wrote a nice tutorial for hg, pretty easy to get through; especially if you already understand version control.
At the recent Symfony Live conference I used the core team QA to address the audience to push for building new dedicated apps on top of general purpose frameworks like symfony and friends. More importantly those efforts should be released as early as possible in the development process as open source to ensure that others join instead of creating their own and then eventually releasing more and more redundant solutions. See the various symfony CMS solutions are an example of how wrong things can go. We now have several solutions whose architectural differences are either cosmetic or simply bad design decisions probably a result of trying to invent things in the small ecosystem of a company project team. So I was very happy to hear then that phpBB will adopt Symfony 2 for their next version. Hopefully this will become a role model for others.
At the conference we also talked about how to better merge the current CMS efforts for Symfony 2, but I fear that will proof to be tricky. From my experience the easiest approach is to put stuff out there early so that people can pool around a leader (or a hand full of leaders): there might be one or two other competitors that differentiate themselves via fundamentally different approaches (lets say a RDBMS vs. a document store CMS or using flat files or a database for configuration). With the ecosystem we have for CMS solutions for symfony 1.x we have several solutions that were open sourced by companies in the hopes of getting new customers, where collaboration with the community is more a nice side effect than the real focus. There the risk of turf wars is quite high since there would simply be too many potential leaders.
So I hope that there will be a fast mover that will proof to be a good leaders as well. Liip might even attempt to become just that building on top of the Jackalope project to provide a JCR based CMS for the PHP world. I assume phpBB will have a need for various social networking features which many currently popular CMS solutions also offer, so there might also be an opportunity for them to lead some of these aspects, but it might be too large a burden to deal with the Symfony community at large, while they are just joining themselves. Meaning they might also need to convince their developers that this is the way to go, which means they probably want to see more code and less talk.
MeeGo is the new mobile Linux platform developed by Nokia and Intel. As the community is forming up, we thought that it would be good to enable people to use their maemo.org identities also on the MeeGo web services (as well as on any other OpenID enabled website). For this, let me introduce Maemo's OpenID provider.
First of all, go to meego.com and click login:

Select the "Log in using OpenID" option, and provide your maemo.org OpenID URL:

Then the request will be redirected to maemo.org where the site will check your credentials and ask whether to relay your information on to meego.com:

And that's it, suddenly you can use your maemo.org account with meego.com!
The same OpenID provider component can also be utilized on any other Midgard-powered website.
Jose Antonio Bayona Medina has put up a slideshow demonstrating how to use the basic technique outlined in this chapter to add PHP-GTK 2 autocompletion in Netbeans 6.7.
Anyone who knows me knows that when I talk about the model, I’m usually talking about Propel. I’ve liked Propel ever since I started working with it in the middle of last year; I personally find it easier and more fun to use than Doctrine or other ORMs available today. I was excited to see recently that Propel’s development team had released Propel 1.5 as a beta, with a launch of the new features to come soon.
There are a couple new features in Propel 1.5 that I think are going to be pretty awesome additions. Here are my two favorites:
Collections and On-Demand Hydration
One of the things you’d sometimes have to do with Propel is fetch an array of objects and iterate through that array to find the data you wanted. However, this created a significant concern: it actually had to hydrate these objects all at the same time. This means that if you had a limit of, say, 200,000, you could quite possibly run out of memory.
Propel 1.5 adds the ability to have the Collection object hydrate the objects on demand, rather than all at once. This saves memory until the object is actually requested. Propel is smart enough not to need to run back and forth to the database; it still has access to the results set, but doesn’t hydrate the objects until it needs them.
Model Queries
Prior to Propel 1.5, in order to query the database in any unusual way (say, attaching an unusual WHERE clause for example), you had to use a Criteria object. Criteria objects were exceptionally useful, but had certain limitations, the largest one being that they are unaware of the way the model is constructed, and therefore cannot offer additional help at building queries.
With the introduction of Propel 1.5, there is a new set of classes automatically generated called Query classes. These classes extend the Criteria class, incorporating it’s functionality while offering helper methods that make writing common queries easier. For example, if you’re searching for a user you can find that user more easily because there will be a method named findByUsername() that you can access.
These features, along with lots of other cool components, make Propel 1.5 pretty awesome. I’m looking forward to it’s stable release and to integrating it into my development in the near future.
I have just released the bug fix version 0.9.10 of PHP_Depend. This release contains several bug fixes and improvements for PHP_Depend.
Truncated by Planet PHP, read more at the original (another 2310 bytes)
framework | rel | avg | 1 | 2 | 3 | 4 | 5
------------------------ | -------- | -------- | -------- | -------- | -------- | -------- | --------
baseline-html | 1.1972 | 5702.79 | 5527.29 | 5775.74 | 5779.59 | 5671.24 | 5760.10
baseline-php | 1.0000 | 4763.50 | 4718.24 | 4751.51 | 4760.75 | 4763.68 | 4823.32
zend-1.10 | 0.1596 | 760.45 | 766.90 | 764.70 | 758.62 | 752.04 | 759.98
symfony-2.0.0alpha1 | 0.1366 | 650.61 | 641.98 | 655.41 | 653.86 | 656.68 | 645.12
solar-1.0.0beta3 | 0.1131 | 538.86 | 539.76 | 536.95 | 540.63 | 540.10 | 536.87
yii-1.1.1 | 0.0821 | 390.87 | 401.90 | 392.59 | 386.18 | 395.98 | 377.72
symfony-1.4.2 | 0.0441 | 210.22 | 211.20 | 209.78 | 210.72 | 210.49 | 208.92
cakephp-1.2.6 | 0.0406 | 193.56 | 193.84 | 193.35 | 193.27 | 192.57 | 194.75
Truncated by Planet PHP, read more at the original (another 6736 bytes)
framework | rel | avg | 1 | 2 | 3 | 4 | 5
------------------------ | -------- | -------- | -------- | -------- | -------- | -------- | --------
baseline-html | 1.1972 | 5702.79 | 5527.29 | 5775.74 | 5779.59 | 5671.24 | 5760.10
baseline-php | 1.0000 | 4763.50 | 4718.24 | 4751.51 | 4760.75 | 4763.68 | 4823.32
zend-1.10 | 0.1596 | 760.45 | 766.90 | 764.70 | 758.62 | 752.04 | 759.98
symfony-2.0.0alpha1 | 0.1366 | 650.61 | 641.98 | 655.41 | 653.86 | 656.68 | 645.12
solar-1.0.0beta3 | 0.1131 | 538.86 | 539.76 | 536.95 | 540.63 | 540.10 | 536.87
yii-1.1.1 | 0.0821 | 390.87 | 401.90 | 392.59 | 386.18 | 395.98 | 377.72
symfony-1.4.2 | 0.0441 | 210.22 | 211.20 | 209.78 | 210.72 | 210.49 | 208.92
cakephp-1.2.6 | 0.0406 | 193.56 | 193.84 | 193.35 | 193.27 | 192.57 | 194.75
Truncated by Planet PHP, read more at the original (another 6636 bytes)
Bossa Conference, an event about mobile development with free software technologies will be held on March 7th-10th in Manaus, Brazil. This year I'm speaking about using Midgard as a replicated storage layer in mobile applications, with examples for multiple programming languages and toolkits.
The idea behind the Midgard content repository is that instead of coming up with your own file formats you can just keep working with objects and signals, and let the repository deal with the rest.

It is always fun to go to Brazil and meet the vibrant free software community there. The plan is to fly over this weekend, spend a few days in Sao Paulo and then head for the Amazon. Feel free to ping me if you're around.
Now that Facebook has finally released the source for HipHop PHP it is time to give it a spin. Of course it is still a little rough around the edges so I figured I would toss together a quick howto on getting it to build.
The first thing to note is that they are only supporting 64 bit systems officially. Having said that it isn't too hard to modify the code to make it work on a 32 bit system although it may turn out that such early modifications are missing some fundamental bits on why they were only support 64 bit systems. I'm going to assume at first that you are using a 64 bit system and then end with what you need if you are still using a 32 bit system.
I don't actually have a 64 bit system myself so I used an EC2 instance for the following instructions. To do the same start with Amazon's Basic 64-bit Fedora Core 8 (AMI Id: ami-86db39ef) instance (note that this is EBS backed so you will end up with an EBS volume after you start it) and then upgrade to Fedora 12 using my previous instructions on building a EBS bootable Fedora 12 instance. You will need to remove a few packages to get the 64 bit version of Fedora 8 to upgrade that I didn't have to do for the 32 bit version, here are all the commands you need to get to a running 64 bit Fedora 12 instance (the entire upgrade takes about 20 minutes):
# Fedora 8 to Fedora 10 yum -y remove dmraid-1.0.0.rc14-4.fc8.i386 dmraid-1.0.0.rc14-4.fc8.i386 curl-7.18.2-7.fc8.i386 yum clean all rpm -Uhv [mirror.liberty.edu] http://mirror.liberty.edu/pub/fedora/linux/releases/10/Fedora/i386/os/Packages/fedora-release-notes-10.0.0-1.noarch.rpm yum -y update # Fedora 10 to Fedora 11 yum -y remove gpm-1.20.5-2.fc10.i386 yum clean all rpm -Uvh [mirrors.usc.edu] http://mirrors.usc.edu/pub/linux/distributions/fedora/linux/releases/11/Fedora/i386/os/Packages/fedora-release-notes-11.0.0-2.fc11.noarch.rpm yum -y update # Fedora 11 to Fedora 12 yum -y remove cryptsetup-luks-1.0.6-7.fc11.i586 yum clean all rpm -Uvh [mirrors.kernel.org] http://mirrors.kernel.org/fedora/releases/12/Fedora/i386/os/Packages/fedora-release-12-1.noarch.rpm yum -y update # Make sure the basics are installed yum -y install gcc-c++ git
To start with there are some prerequisites you need. This can be taken care of in one command with yum:
yum -y install git cmake boost pcre-devel libicu-devel libmcrypt-devel oniguruma-devel mysql-devel gd-devel boost-devel libxml2-devel libcap-devel binutils-devel flex bison expat-devel
Next create a directory to hold everything in, change into that directory and create another directory to hold the customized libraries needed to compile HipHop PHP:
mkdir hiphop cd hiphop mkdir local
Next it is time to pull down the HipHop PHP source along with the source for some libraries it depends on (these all go into the hiphop directory created above):
git clone git://github.com/facebook/hiphop-php.git wget "http://downloads.sourceforge.net/project/re2c/re2c/0.13.5/re2c-0.13.5.tar.gz?use_mirror=cdnetworks-us-2" wget "http://www.threadingbuildingblocks.org/uploads/77/142/2.2/tbb22_20090809oss_src.tgz" wget [curl.haxx.se] wget [www.monkey.org] tar xvjf curl-7.20.0.tar.bz2 tar xvzf libevent-1.4.13-stable.tar.gz tar xvzf re2c-0.13.5.tar.gz tar xvzf tbb22_20090809oss_src.tgz
Next the customized patches get applied to some of the library sources and each is built to install in the custom directory:
export CMAKE_PREFIX_PATH=`pwd`/local cd tbb22_20090809oss gmake cp -Rp include/tbb/ /usr/include/ cp `pwd`/build/*_release/*.so /usr/lib/ ldconfig cd .. cd re2c-0.13.5 ./configure --prefix=`pwd`/../local make install cd .. cd libevent-1.4.13-stable cp ../hiphop-php/src/third_party/libevent.fb-changes.diff . patch < libevent.fb-changes.diff ./configure --prefix=`pwd`/../local make install cd .. cd curl-7.20.0 cp ../hiphop-php/src/third_party/libcurl.fb-changes.diff . patch -p0 < libcurl.fb-changes.diff ./configure --prefix=`pwd`/../local make install cd ..
There is one problem at this point that requires a little surgery on the HipHop PHP source itself. There is more about this in issue #6 and once it gets fi
Truncated by Planet PHP, read more at the original (another 3005 bytes)
Thanks to all the participating communities, I was able to produce the following ConFoo video. It talks about what to expect from the 2010 conference. I hope you have as much fun watching it as I had making it.
We were discussing the difficulty of the hiring process from a company point of view last week at the github meetup in Paris, and more specifically how hard it is to get quality people without relying on test assignments, which most agree are total bullshit, or on a couple of interviews, which can also be very misleading since it depends a lot on the person's social skills, or lack thereof.
One big thing that is overlooked in my opinion is participation in open source projects, be it a single patch or long term commitment. As an employer you can see that the guy has enough interest in programming in general that he has taken the extra step to contribute something, and also that his work was accepted by a peer as valid. It is obviously not the full story and we all know some open source projects' code is utter crap (disclaimer, this also applies to closed source software, you just don't get to see it), but I still believe it gives you a better metric than just some code the guy did (or didn't) code and is presenting to you during an interview.
You can use ohloh to track your open-source-CV of sorts, and I would very much like it if more companies would push the open source involvement forward in their job ads, probably not as a requirement but at least as a big plus. It would benefit both companies that are trying to hire good people, and good people to be recognized. Of course it would also benefit the open source community at large if the work you do there gets you more recognition, pushing more people to take the leap to contribute. It is definitely helping already, if only for the contacts you get, which are always good when looking for a job, but increasing the perceived benefit of contributing to the open source world would be great, so I would very much like if all you HR people would give it a thought, and other readers please mention it to HR in your company, or your friends looking for work, your little brother starting to study, anyone can contribute.
Any other ideas on how to find great developers? Is your company using open source as a criteria? Did it help?
I wanted to play with Symfony 2 and so needed to install PHP 5.3 on my OSX 10.5. What seemed like a simple task turned into a huge waste of my time.
I use MAMP because it’s a nice out-of-the-box solution. The problem is, it still doesn’t ship with 5.3 because it’s waiting for it to be “stable”.
It’s funny that I got a similar answer a few years ago from a big web hosting company about PHP5 when it was clearly announced that PHP4 is discontinued.
I first searched for a way to upgrade PHP in MAMP and came across this nice post: [www.davidgolding.net]
Unfortunately, while following the steps, I kept getting errors because some dependencies were missing. First openssl, then libjpeg, and so on. After some time I grew tired of that catch-up game and decided to go with a product that comes with 5.3 pre-compiled.
XAMPP was my answer. You can download it here: [www.apachefriends.org]
So if you’re tired of MAMP, it’s time to switch.
EDIT:
To migrate your vhost config from MAMP, copy to XAMPP/etc/extra/httpd-vhosts.conf and enable the line that contains this path in XAMPP/etc/httpd.conf
To migrate your MySQL, my favorite method is to enable MySQL via MAMP, dump all the databases to a file (you may use MySQL Administrator for convenience), disabling MySQL via MAMP, enabling it via XAMPP and then restore your databases from the dump file.
EDIT 2:
At the time of this post, XAMPP ships with PHP 5.3.0 while Symfony 2 requires 5.3.1. Oh well, I guess I’ll just wait for them to release a new version before I play with Symfony.
Am kommenden Donnerstag, den 25.02.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in München statt (Mannhardtstraße 6, S-Bahn Isartor).
Last week Lukas, Pierre and myself attended the Symfony Live 2010 conference since we have a growing interest in it lately, including a pilot project at Liip that uses symfony 1.4.
Overall the conference was quite a success I would say, they had a few organizational issues but considering it was the first international event of that scale they hosted it was really good. Most talks revolved around symfony and also doctrine since it's a major part of the symfony ecosystem, but a few sessions were held on more general topics, such as PHP performance, deploying apps to the cloud or Zend Framework. Lukas and I spoke about Liip's framework Okapi since it's second iteration, that is still in the works, is using a few symfony components. As we mentioned there we decided to use them to alleviate some of the maintenance work and benefit from the dependency injection feature, which offers amazing opportunities for customization and testing. Our slides can be found on slideshare and the Okapi2 source on our svn repository.
The highlight of the conference was obviously the announcement and release of the Symfony 2 codebase. Symfony 2, just like Okapi 2, is based on the Symfony dependency injection container component, which means it will have the same flexibility. Given the community it has, it is definitely an interesting development for us and we will follow its development closely. If it happens to fit our requirements as well as Okapi does for fully custom high performance websites we might adopt it but it is too early to say since it won't be stable until the end of the year.
The last decade has been witness to the second iteration of web design and development. Web sites have transformed into web applications and rarely are new projects commissioned that do not involve some element of interactivity. The increasing complexity of the software being developed for the internet fuelled a requirement for structured and considered application design.
Today the most common design pattern for web software is the Model-View-Controller (MVC) pattern. The widespread adoption of the MVC design pattern was supported, in part, by the success and popularity of the Ruby on Rails framework. MVC is now synonymous with web application development across all platforms.
With the rising complexity of projects developed for the web, modern software for the web increasingly relies on dedicated services to perform processor intensive tasks. This has been encouraged further by the introduction of cloud services from Amazon, Google and several others enabling developers to considerably reduce the processor load on their servers. Each service is usually designed as a separate piece of software that runs in its own domain using its own resources.
When working with small budgets, it is generally much harder to convince clients of the benefits of funding more than one complete piece of software. In these situations I have found that many clients conclude that scalability is not a concern. They “look forward to the day when they will have to worry about scaling”.
To reduce the initial investment, usually it is decided that the application should designed to be one holistic piece of software containing all the required features. This represents a potential point of failure if the software becomes very popular in a short timeframe. I have painful memories of refactoring existing codebases that have not scaled well. It can also be very costly in time and resources to re-architect software that not scaled well. Ideally applications should grow organically as required and without large sums of money being exchanged in the process.
Hierarchical-Model-View-Controller patternThe Hierarchical-Model-View-Controller (HMVC) pattern is a direct extension to the MVC pattern that manages to solve many of the scalability issues already mentioned. HMVC was first described in a blog post entitled HMVC: The layered pattern for developing strong client tiers on the JavaWorld web site in July 2000. Much of the article concentrates on the benefits of using HMVC with graphical user interfaces. There has been some suggestion that the authors where actually re-interpreting another pattern called Presentation-Abstraction-Control (PAC) described in 1987. The article in JavaWorld provides a detailed explanation of how HMVC can aid in the design of desktop applications with GUIs. The focus of this article is to demonstrate how HMVC can be used to create scalable web applications.
HMVC is a collection of traditional MVC triads operating as one application. Each triad is completely independent and can execute without the presence of any other. All requests made to triads must use the controller interface, never loading models or libraries outside of their own domain. The triads physical location within the hosting environment is not important, as long as it is accessible from all other parts of the system. The distinct features of HMVC encourages the reuse of existing code, simplifies testing of disparate parts of the system and ensures that the application is easily enhanced or extended.
To successfully design applications that implement the HMVC pattern, it is critical that all of the application features are broken down into systems. Each system is one MVC triad within the larger HMVC application, independently managing presentation and persistent storage methods. Presently few frameworks are available that support HMVC without additional extensions, or use inefficient Front Controllers and dispatching. Kohana PHP version 3 is a framework that was designed from the ground up with HMVC at the core. I will be using Kohana PHP 3 for all of the code examples in this document.
Kohana 3 uses the core request object to call other controllers. Requests can be made internally to application controllers or externally to web services transparently using the same request class[1
Truncated by Planet PHP, read more at the original (another 49126 bytes)
I'm thrilled that I'll be speaking at the 2010 edition of the Dutch PHP Conference. I've not attended or spoken at this conference before; in fact I've never been to Europe so this will definitely be a new adventure. I'm quite excited.
I'll be speaking on the topics of Technical Debt and Technical Writing, both of which I find fascinating and enjoy talking about. If you're around at the conference, I hope you are able to pop in and say hello.
My thanks to the selection committee and I really look forward to seeing friends old and new!
After SemanticScuttle gets better and better, it's time to think about providing a installation/setup wizard for people that freshly install the bookmarking application.
The current steps to setup SemanticScuttle are:
This is not easy for newbies and casual users that just want their own private boomarking site. It also makes it really easy to miss the dozens other configuration options that are not part of the config.php.dist file but are only declared in config.default.php. A better way for setup would be:
This way of installing SemanticScuttle would make installation less error-prone and more pleasing.
Now instead of writing an installer yourself, there could be tools somewhere out in the web that already to this, right? Something like NSIS , IzPack or WiX , just for PHP web applications? Something like PEAR post-installation scripts, just not only for the command line?
There are some of them, but not a single one that I liked. To save you your own investigation, here is a list of them.
Desired feature setHere is a list of features I would expect or wish to be in such a setup/configuration tool:
General featuresTruncated by Planet PHP, read more at the original (another 4554 bytes)
This week I worked on lowering the number of queries that SemanticScuttle needs to deliver a bookmark listing page.
Just looking at the front page of a SemanticScuttle instance with 10 or more bookmarks, not logged in, caused 37 SQL queries to be fired to the database. If you are logged in, doing the same action took SQL 54 queries!
After my optimizations, it only takes 8 queries for the front page for anonymous people and 22 for users that are logged in. The logged-in count can easily be lowered to 13 by combining the watch queries that are sent for each single bookmark to be displayed into one.
I also tried running SemanticScuttle with 32000 bookmarks which actually worked, but I got response times of over 1 second. Problem here seems to be that SemanticScuttle uses COUNT() and DISTINCT for some queries. This cannot be easily fixed, only by i.e. putting those counts as hard-coded values into the bookmark rows and updating them whenever the database changes, or doing that via a cron job.
So the next feature release of SemanticScuttle (0.97) should feel a bit snappier, especially with many concurrent users requesting pages on your server.
Well, I’ve been working on my project for the week and here’s the update that you were promised! (And stick with the post, there’s a live demo!) I haven’t gotten as far as I had hoped but I have learnt a lot whilst here. See the previous post for more on that and what I had planned.
Monday
I sat down with Eamon and planned out exactly what the app would do, the users and roles, and what out of that I could get done in the week. I spent the remainder of the day planning each of the “actions”, “roles” and “resources” my app would have so that I could write the app much better and understand what would be going on in it. On that day I really got a sense of object-oriented programming that I hadn’t before, mostly thanks to David and Helgi for helping me with it and finding my feet with Zend Framework and understanding the concepts behind OOP.
Tuesday
I got started with the code. Much of this day was taken up with looking up various things in the Zend documentation and trying to understand how it worked. Despite the ton of reading I had to do to find out how to make Zend do what I wanted I got a lot of the core features for the model done like adding, viewing and listing resources. The main thing I learnt was how to use Zend_Db which is a critical component to most apps using Zend since the database contains all that info!
Wednesday
I coded the remainder of the models and started on creating the interfaces and forms. The theme I was lucky to get off ThemeForest so I just dropped in the default code from Zend_Layout and that was that. Then I learnt that you really should add users before models because I had one fun time trying to add it in retrospectively using Zend_Auth and Zend_Acl.
Thursday
I just finished the journal and resource components and rounded them off. I learnt that you really should make sure your revision control is working before you screw up your code by deleting an entire library that you have no backup of. (Doh!)
Friday
Today, I finished the prototype of the app, all the components started behaving and working together. I cleaned up the user system so the Zend_Acl worked to the best of it’s potential and rewrote the library that had I deleted by accident on Thursday. I learnt that when under pressure I code faster and that you should really, really plan out and code the user system first before any other components. Also libraries are better the second time you code them!
Here’s some screenshots and a live demo for you to try out! I still have not decided on a name, so I’m just going with Project X for now


You can play around with what I’ve been working on here: [projectx.teachmetothink.com]
Building a conference website as the conference was being organized is probably one of the biggest challenges I ever faced. It is also the project I’m the most proud of. I’d like to share that experience with you. By the way, the event is still in progress, so my work on the site is not done.
Throw away old codeThe first decision was to throw away the old code base that dated back to the first PHP Quebec Conference in 2003. We decided to start from scratch with the Symfony framework and I was going to be in charge (yay!)
PrioritiesThe conference was moving on and I had to keep up with the programming. Developing the website was only part of my responsibilities as an organizer, which made things even more difficult time-wise. I had to prioritize and develop the strict minimum based on the immediate conference needs. There was very little time to test between deployments (I know, it’s bad practice).
1. Logo and designI was learning the framework while another member of the team, Yann Larrivée, was building the project skeleton. At the same time, we had an organizer, Mathieu Chartier, and his partner prepare the logo and the website design. Last year I was the one doing it and you could clearly see that I’m no designer and no expert in Web standards.
Besides a few static pages to present the event, the call for papers was the absolute first priority. Another member of the team had already put a project skeleton together, so I could dive right into the good stuff. Creation of user accounts, authentication, member dashboard and paper submission had to be put in place in record time.
Speakers could associate tags with their talks so that the organizers will be able to sort them out more easily. To put it in context, organizers were responsible each for his own track (php, python, java, ruby, etc.) and needed to know which talks fell under their responsibility.
The worst that could happen did happen. I was speaking at a conference in Paris during the last day of the call for speakers and the server crashed. Once fixed, we had to extend the call by three days because some people missed the deadline as a result of this extended site unavailability.
3. Talk selectionWe needed a tool to sort through the 450 or so talk submissions. Thus came the admin section which was built by another member of the team, Sylvain Mathon, who had more experience with the framework. We put the talks in their corresponding tracks and spent a whole Saturday selecting the ~130 talks.
Since budget is a big consideration for a non for-profit organization, we built some tools on that same day to monitor, in real time, the estimated travel and lodging costs based on the selected speakers.
Then I also needed to implement the Session and Speaker sections. Considering the large number of presentations, I had to figure alternate ways to present all that info. I couldn’t just put it all on one page as we did with PHP Quebec in the past, where we had 55 presentations at most.
4. TicketsA conference is no good if people can’t buy tickets to attend it. The next big priority was to implement a checkout process. So without time to catch my breath, I implemented a public shopping cart, then a mandatory login/registration, the billing information screen, the confirmation screen and a redirection to the payment screen. Also, I had to consider that ticket price varies over time (early bird, regular and at-the-door prices).
This was not the end. Since companies often purchase multiple tickets for their employees, we needed them to enter the attendees’ names and associate those with user accounts. I made the account creation/association process transparent to the buyer. They simply needed to enter the name and e-mail of the attendees.
Then people need receipts. Also, many institutions can only pay by check and thus need an order form. And so another member implemented the PDF module for our site.
5. Monitoring toolsNow that we started to sell tickets, we needed to monitor it closely to know when and where to promote the event. For example, we sponsored another conference in Quebec City (CLLAP) and needed to know our ROI. Based on promotional codes and referrers, visitor locations and technologies, we knew how to approach the different communities.
Also, we needed to monitor the impact of the various communications by checking what tickets we sold on each day.
6. Flash saleI still couldn’t put the checkout process to rest. Now we decided to do a flash sale, that is, a special price that will only last a week. Luckily for me, the mechanism was already in place with the different pricing, so it was simply a question of adding one entry to the da
Truncated by Planet PHP, read more at the original (another 3033 bytes)
Three years ago the Hardened-PHP project organized the Month of PHP Bugs. During one month I disclosed more than 40 vulnerabilities in the PHP interpreter in order to improve the overall security of PHP. In the history of PHP this event has been one of a kind. But now, three years later, my company SektionEins GmbH will continue in the same spirit and organize the Month of PHP Security. Our preparations are not finished yet, but here is a sneak preview of what it will be.
The Month of PHP Security will take place in May 2010 and will be very different from all the previous “Month of Bugs” or “Week of Bugs” events. You can think of the Month of PHP Security as a conference without a conference. This means around the 1st of March we will send out a call for papers in order to collect the best advisories, the best research and the best articles about PHP security. We invite everyone from the PHP and from the security community to take part in this event.
The basic idea will be that during May we are planning to release (at least) one advisory or one research paper or one article about PHP security topics that were submitted to the public. And in the end of May our jury will select the best X submissions and give out prizes. We are still in the process of selecting good prizes and would be happy about more sponsors. Therefore: If you consider this event to be a good idea to improve the security of PHP and want to sponsor prizes, do not hesitate to contact us at info@sektioneins.de.
The accepted topics will be:
Of course we will accept multiple submissions by the same person/team and there will most probably also be articles/advisories by ourself. (But of course we cannot win the prizes)
We at SektionEins are already very excited about the event and hope it will be a success and once again improve the security of the PHP ecosystem.
VLD is a tool that I started working on years ago to visualise the opcode arrays in PHP. Opcode arrays are what PHP's compiler generates from your source code and can be compared to assembler code that is generated by a C compiler. Instead of it being directly executed by the CPU, it is instead executed by PHP's interpreter.
Over the years I've been adding some functionality, also aided by Ilia and some others, to show more information. For example Ilia has added a more verbose dumping format for opcodes (through the vld.verbosity setting) whereas I have added routines to find out which ops in oparrays can never be reached. A very simple example of the latter is shown here:
<?php function test()
{
echo "Hello!\n";
return true;
echo "This will not be executed.\n";
}
??>
If we run the above through VLD with php -dvld.active=1 test.php, you'll see the following output (I removed the part about the script body itself):
Function test:
filename: /tmp/test1.php
function name: test
number of ops: 9
compiled vars: none
line # * op fetch ext return operands
---------------------------------------------------------
2 0 > EXT_NOP
4 1 EXT_STMT
2 ECHO 'Hello%21%0A'
5 3 EXT_STMT
4 > RETURN true
7 5* EXT_STMT
6* ECHO 'This+will+not+be+executed.%0A'
8 7* EXT_STMT
8* > RETURN null
End of function test.
Every opcode that has a * after the number (like in 5*) is code that can not be reached, and can possibly be eliminated from the oparrays in an optimiser.
The dead code analysis routines have also made their way into Xdebug which uses them for the code coverage functionality to highlight dead code. This mostly makes sense if you are running your code coverage together with unit tests such as you can do with PHPUnit.
Recently I've been working on some new functionality to visualise all the code paths that make up each function. These new routines sit on top of the routines that do dead code analysis. Every branch instruction (such as if, but also for and foreach) is analysed and a list of branches is created. Each branch contains information about the line on which the branch starts, the starting and ending opcode numbers that belong to the branch, as well as to which other branches this branch can jump to. There can be either no linked branches (when for example a return or throw statement is found), one linked branch (for an unconditional jump) or two linked branches (on a branch instruction). However, you need to be aware that internally, PHP's opcode don't always reflect the source code exactly.
Once all the branches and their links are found, another algorithm runs to figure out which paths can be created out of all the branches. It is best to illustrate this with an example. So let us look at the following script:
<?php function test()
{
for( $i = 0; $i
In this script we have a for-loop with a nested if construct. When we run this script through VLD (with php -dvld.verbosity=0 -dvld.dump_paths=1
-dvld.active=1 test2.php) we get the following output (again, only the test() function and with some white space modifications):
Function test:
filename: /tmp/test2.php
function name: test
number of ops: 22
compiled vars: !0 = $i
line # * op fetch ext return operands
-----------------------------------------------------------
2 0 > EXT_NOP
4 1 EXT_STMT
2 ASSIGN !0, 0
3 > IS_SMALLER ~1 !0, 10
4 EXT_STMT
5 > JMPZNZ 9 ~1, ->18
6 > POST_INC Truncated by Planet PHP, read more at the original (another 4288 bytes)
This has been an amazing week for me, Symfony, and the whole Symfony community. With more than 350 attendees coming from more than 30 countries, the Symfony Live conference was a blast. I want to thank all attendees, speakers, and the Sensio Labs team for coming to the conference and making it a truly fantastic event.
If you have not attended the conference, you can still come to the Symfony Live After-Party next week in London. And don't miss Symfony Camp in June and Symfony Day in October. If you live far away from Europe, stay tuned as we have more exciting news to announce in the coming weeks.
The conference was also the occasion to unveil the first preview release of the upcoming Symfony 2 framework. Since then, the buzz has been great and I have already received a lot of good comments on it. Of course, I hope that this is just the beginning, and that more people will provide feedback.
On the PHP CommunityI'm also very proud that people from so many different PHP "sub-communities" attended the conference: Jon Wage (Doctrine project manager and lead developer of Doctrine 1.x), François Zaninotto (lead developer of Propel), Nils Adermann (lead developer of PhpBB), and of course, Matthew Weier O'Phinney (Zend Framework lead).
I like to see the whole PHP community as a big unified group of developers trying to promote the same platform. And I do my best to be a good "PHP citizen". I try to innovate by adapting concepts from other languages. But I also try to not reinvent the wheel when it's not mandatory. The symfony 1 framework uses a lot of third-party libraries like Propel and Doctrine. And for Symfony 2, I'm proud to have replaced our own Logger and Cache system by the equivalent components from the Zend Framework. And you can imagine that it was not an easy decision to take. First, because it meant throwing away code we have written and maintained for years. Then, because the Zend Framework is our main competitor. But I'm sure we have made the right decision and Matthew seems to have the same point of view on that matter.
On PHP FrameworksPeople are jealous, so jealous that it makes me really sad. For the last few years, some PHP framework communities attempted to "kill" Symfony by trying to demonstrate that it is too slow, too complex, and too bloated. Of course, that's not true. And the number of high-traffic websites using symfony 1 speaks for us.
I get inspiration from many different frameworks from many different languages. Besides PHP projects, I like to follow the development of Django, Spring, Rails, Maven, Jinja, Rack, Sinatra, and many others. I try to bring innovation to the table. And for Symfony 2, I have tried to take into account the major pain points of symfony 1. The truth is that Symfony 2.0 requires no configuration. The truth is that Symfony 2 is really fast. Is it the fastest framework? I don't care. It is probably fast enough for your next website, and so is symfony 1.
Now if some people cannot accept that Symfony 2 is really fast and if they cannot accept that Symfony 2 is great step forward for PHP, that's sad. The web evolves very fast. Competition is everywhere for PHP. We should all be in the same boat.
I would love if people from different framework communities can work together more often, like what we have done with the PHP 5.3 interoperability group. I would love if we can share more components. I would love to discuss how we can make our PHP community grow faster.
Is it a dream? I hope it's not. And I have a proposal. Let's organize an event where several PHP framework communities can discuss and share ideas. Anyone?
On Dependency InjectionThe biggest Symfony 2 innovation lies in its low level architecture. And its flexibility and speed is mainly due to the Symfony Dependency Injection Container component. Dependency Injection Containers are not widespread in the PHP world, and I really think that this is a very good approach. That's why I talk about Dependency Injection at conferences. Next time I will talk about this topic is during the ConFoo conference in March.
“There is a problem with component Fooey-Bar-Bazzy, I think it’s related to Nanny-Nanny-Neener. Please Fix Now.” If you’ve written a bug/issue report like that in the past with no other details- shame on you! This may come as a shock, but as great as some developers might be, they cannot read minds. Each has their own way of coding, custom working environment as well as their own favorite tools; aside from variances in coding standards and best practices. Some could argue these little intricacies are outside of the realm of coding standards and best practices and that these are the differences between good, great, and even terrible developers. Each developer has a different opinion on how particular applications, libraries of code, or even features of a particular project are expected to behave in practice. These varying expectations are why bugs/issues exist. No one developer producing code for mass consumption can anticipate every possible use case. Additionally, no one developer can replicate every environment surrounding every pre-conceived use case. There are simply not enough resources at hand; be it in the form of a variety of systems or simply the number of hours in a developers day.
With that in mind, I write this as a plea to all developers to be good to the maintainer of code you use. In the simplest form of advice, I suggest that before you click submit on that bug/issue report form, ask yourself two questions: “Did I do enough due-diligence in determining if this is really a bug?” AND “If I got this bug report, would I be able to reproduce it.. let alone understand it?”. If the answer is YES to both of those questions. Go ahead- click submit. If your answer is no, you’ve got some more work to do.
Some Tenets Of the Good Reproduction ScriptIn this short article, I’d like to outline a few details of what should go into a bug/issue report. These are some simple guidelines that should be considered when you write a bug/issue report. It should be noted that this list is by all means not exhaustive, but if you at least consider the list below before clicking submit- you’ll make a code maintainers day. I promise.
PHP specifically is well known for being a “glue language”. What that means is that PHP is generally sitting between multiple pieces of software that is, of course, not PHP. This means that these pieces of software each have their own set of configurations and environments that PHP is “gluing” together. That being the case, any assumptions about non-PHP assumptions should be clearly listed in the reproduction script. This could include database flavor and its settings, a PHP library component, or perhaps a specific version of an extension that is being used and the underlying unmanaged/c-based library your PHP environment is consuming.
As tempting as it is to copy a script from your project and paste it into the bug/issue submission box, don’t do this. If you are truly invested in seeing the bug/issue fixed in a timely fashion, take the time to create a small reproduction script. In this script should be the absolute minimal amount of code to demonstrate to another human that there is indeed a problem that needs solving. By keeping the script minimal and short, you are also removing any other distractions from the script that otherwise might confuse the maintainer and prevent him from fully understanding the real problem.
It cannot be stressed enough that any non-meaningful names should be discouraged at all costs. And as mentioned above, you want to have as few distractions as possible in the use case. For example, supplying your database table of customers, with first_name, last_name, etc has virtually nothing to do with the problem at hand. In these cases where table and column names are ancillary to the actual problem, they should be generalized: a table named ‘foo’, and columns named ‘bar1′ and ‘bar2′. Unless …
… the variable name can add context to the problem. What does this mean? $customer would be bad; but $faultyTableObject is good. The latter naming makes it easy for the maintainer to focus on the variable that need to be tracked leading up to the problem.
Claiming something is broken without offering what you expect and what the actual result is offers next to nothing to the maintainer attempting to fix the problem. Generally speaking, most use cases that end up being bugs/issues are outside of the original preconceived use cases for the actual component. That said, the maintainer is
Truncated by Planet PHP, read more at the original (another 8745 bytes)
Overall the conference was pretty interesting since I don't have a lot of experience with symfony I learned quite a bunch of things about it's usage. I also met a lot of nice people, and ended the trip yesterday evening at the github meetup, after going for food with a couple phpBB guys who are really much nicer than the forum software they stand for. They were also very open to us bashing phpBB and seem to be headed towards a brighter future for the next version, which I'm sure nobody will complain about.
I also had my first session at a conference, accompanying Lukas though so I wasn't really flying by myself yet but it was still a nice and interesting (and stressful) experience that I will try to renew. We didn't get all that much feedback by the way so feel free to do so (also here if you are too lazy to register on joind.in), the organizers need it and obviously I wonder how the talk was received as well.
As for Symfony 2 (which now comes with a capital S please), I kind of saw the flexibility coming since we already implemented the dependency injection container in our Okapi framework at Liip, but I was still impressed by the jump away from symfony (1) Fabien conceded, many people would have tried to keep more BC at the cost of going forward, and I'm really glad he didn't, I think it will pay in the long run. The new version of the framework will basically be able to be totally ripped apart to fit your needs better if you have high performance requirements, which was the major pain point of symfony 1 as far as I'm concerned, and one of our reasons to keep working on Okapi which is pretty much a baseline micro-framework you can build upon. We will have to see if adopting Symfony in its place will make sense, but it sounds promising and it would offload some maintenance away from us which is always good.
Obviously Symfony 2 isn't going to be stable for a while, and there are some rough edges that still need to be discussed and improved, mostly in the way bundles are handled imo, but it looks very good already and I'll definitely give it a try asap. I would also encourage everyone to do so, especially framework developers, because the dependency injection is a pretty awesome thing to have, both for the testability of code and flexibility of the development process. Although if it's your only interest in it, checking out the Okapi 2 core (or the liip.to app ported to use it) is probably easier as there is less code to read, and we didn't add any of the abstraction to the dependency injection layer that Symfony 2 has.
A recent El Reg article about trends in the PHP community caught my eye yesterday morning. The headline is about Zend’s depressing statistic that the majority of PHP developers do their development on Windows these days (which I’m assured by Marco is old news) … and that’s worth talking about at some point, but it isn’t what interested me the most.
As reported by El Reg, Zend’s survey results show that “seventy per cent use Zend’s Studio or Eclipse PHP Developer Tools, while 18 per cent use Vim.”
This isn’t a case of Zend making wild claims though, just less than full reporting by El Reg this time around. Zend’s own press release make it crystal clear that these are the results of a survey conducted across the Zend Framework developer community; most likely (but not directly attributed) the 2009 survey. That they haven’t released the breakdown for Zend Studio vs Eclipse PDT is perhaps telling, but still, the real headline should be:
In its own community, Zend is being very successful at convincing its community members to use multiple Zend products.
Zend’s “full-stack” strategy is starting to yield results, and it looks like Zend Framework might have been the missing component that held back their earlier attempts. The whole stack has been refreshed, true (Zend Studio now runs on Eclipse, Zend Core has folded into Zend Platform, which itself has the new and far-better-architected Zend Server positioned below it), but with Zend Framework, Zend are (imho) now able to appeal to the sort of developer communities who are willing to pay Zend’s prices. And Zend Framework is finally a product that third parties can make money from, making Zend a little more relevant in the daily lives of your average PHP developer. (I’m a great believer that a key component of all really successful products is that third parties can make money off it, not just the original creator / provider).
Now, if only Zend had an outreach programme for making Zend Server suited both technically and commercially for ISPs like where I work to consider adopting for their shared hosting and VPS customers …
This week, I've been attending Symfony Live in Paris, speaking on integrating Zend Framework with Symfony. The experience has been quite rewarding, and certainly eye-opening for many.
To be honest, I was a little worried about the conference -- many see Symfony and ZF as being in competition, and that there would be no cross-pollination. I'm hoping that between Fabien, Stefan, and myself, we helped dispel that myth this week.
Years ago I wrote about a Firefox extension that allows you to start an Xdebug debugging session by clicking on an icon in Firefox' status bar. For some unexplained reason, this extension is no longer available through Firefox' addon-site. Although I have a copy at [xdebug.org] for archival purposes, there are now a few other browser extensions that do the same thing.
easy Xdebug
easy Xdebug is an extension that serves as a replacement for the now unavailable Xdebug helper extension. It's written by Brecht Vanhaesebrouck of eLime. The extension was originally tested with Netbeans but it also seems to work fine with Komodo.
Xdebug enabler
Xdebug enabler is an extension for Google's Chrome browser. It "allows you to enable and disable triggering Xdebug from with in Chrome. Useful if you are a web developer using an IDE that supports Xdebug like Eclipse with PDT." It's written by 'remailednet' and available through the Google Chrome Extensions website.
JavaScript 'enabler'
I also ran across a blog post by 'Caleb G' from HigherVisibility. Instead of making an extension for a specific browser, he outlines two JavaScript bookmarklets that allow you to start and stop an Xdebug debugging session.
In SintoniaPHP, I've posted a tutorials to create a translator client with PHP-GTK2 using Google Translator service.
The posts links are:
I recently needed to create a clean EC2 AMI using a fairly new linux distro. It has been a while since I've needed to create a new AMI so I also wanted to move away from the older pre-packaged AMI and boot using EBS. After taking a look at what was currently available publicly I decided I would just create my own EBS bootable AMI using Fedora 12. It wasn't all that complicated but there are a decent number of steps so I figured I would document them for anyone else who might want to give it a try.
I'm going to assume you already understand how to do things like create instances, create EBS volumes and ssh into your running instance using key based authentication. I use the AWS management console for a lot of what follows with the exception of needing to register the AMI and for that you will need the Amazon EC2 API Tools and Amazon EC2 AMI Tools
There are two ways to get to a bootable EBS backed Fedora 12 instance and they start off the same. The first thing to do is fire up the AMI named "Basic Fedora Core 8 (AMI Id: ami-84db39ed)" that is provided by Amazon.
Once the Fedora Core 8 EC2 instance is ready ssh into it. Fedora 12 requries a newer version of RPM to install so you now need to upgrade the instance to Fedora 10. This is pretty easy and can be done by following my instructions on upgrading from Fedora 9 to Fedora 10 (don't worry about skipping 9 it will work). Here are the commands needed to do the upgrade:
yum clean all rpm -Uhv [mirror.liberty.edu] http://mirror.liberty.edu/pub/fedora/linux/releases/10/Fedora/i386/os/Packages/fedora-release-notes-10.0.0-1.noarch.rpm yum -y update
After a few minutes the instance will be upgraded and ready for the next step. This is where the two paths diverge depending on how you want the final product constructed. The options are to install Fedora 12 on a freshly minted volume or continue upgrading the instance you just created.
Upgrade path
I will start with the upgrade path since that is probably the easier of the two although may leave you with a messier instances after it is done. The next step for the upgrade path is to do what I outline in upgrading from Fedora 10 to Fedora 11 and upgrading from Fedora 11 to Fedora 12. Here are the commands all in one place to make it easy:
yum clean all rpm -Uvh [mirrors.usc.edu] http://mirrors.usc.edu/pub/linux/distributions/fedora/linux/releases/11/Fedora/i386/os/Packages/fedora-release-notes-11.0.0-2.fc11.noarch.rpm yum -y update yum clean all rpm -Uvh [mirrors.kernel.org] http://mirrors.kernel.org/fedora/releases/12/Fedora/i386/os/Packages/fedora-release-12-1.noarch.rpm yum -y update
Once you have everything upgraded to Fedora 12 you will have a 15G root partition that has less than 2G used. This may not suite your needs very well if you really don't need that extra 13G but thankfully if you want to shrink the root EBS partition you can.
I found some instructions in this article on EBS backed AMIs that describes using the following command to copy the entire file system over. Assuming you have created a smaller volume and attached it to the instance as sdh you should be able to do something like the following to copy everything to the new volume:
mkfs.ext3 /dev/sdh mount /dev/sdh /mnt tar cpS / | cpipe -vt -b 1024 | gzip -c | tar zxpS -C /mnt rm -rf /mnt/mnt/* rm -rf /mnt/proc/* umount /mnt
One thing to note in the above is that the entire sdh drive is formatted for the file system (you will actually get a prompt asking if that is ok). As far as I can tell this is the way it has to be or the instance will not boot correctly. I assume this is because the root device is hidden behind a partition already as /dev/sda1 and so shouldn't have a second partition table.
Skip to the common part now to learn how to make the final bootable AMI.
From scratch path
This path is similar to and mostly
Truncated by Planet PHP, read more at the original (another 5600 bytes)
Am kommenden Donnerstag, den 18.02.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in München statt (Mannhardtstraße 6, S-Bahn Isartor).
This article is part of a series on testing untestable code:
In a unit test, mock objects can simulate the behavior of complex, real (non-mock) objects and are therefore useful when a real object is difficult or impossible to incorporate into a unit test.
A mock object can be used anywhere in the program where the program expects an object of the mocked class. However, this only works as long as the object can be passed into the context where the original object is used.
Consider the following example:
<?php
require_once 'Bar.php';
class Foo
{
public function doSomething()
{
// ...
$bar = new Bar;
$bar->doSomethingElse();
// ...
return TRUE;
}
}
?>
<?php
class Bar
{
public function doSomethingElse()
{
print '*';
}
}
?>
With the code above, it is impossible to run a unit test for the Foo::doSomething() method without also creating an object of Bar. As the method creates the object of Bar itself, we cannot inject a mock object in its stead.
In a perfect world, code such as the above could be refactored using Dependency Injection:
<?php
require_once 'Bar.php';
Truncated by Planet PHP, read more at the original (another 10780 bytes)
If you place your e-mail address somewhere visible on your website, it will be only a matter of time until your e-mail account will get more and more spam messages. There are lots of spam bots checking the Internet for email addresses on regular websites, forums, blog and mailing lists. Once caught by some spam bot your mailbox is in need of a strong spam filter or sometimes it might be better to use a new e-mail address.
In this article we show you different ways, how you’re able to show your e-mail address to human visitors and hide it for spam bots.
Don’t forget, the solutions mentioned in this article are not a total protection against spam. If you share your e-mail address online, the chance that your e-mail address get on a spammer’s list is big. We advice that if you need to share an e-mail address with your websites’s visitor, to not use your personal e-mail address.
With each solution we give a review for:
Just providing image version is very simple and easy. Open your image editor, create a small image from your email address and upload the image to your website.
After this you’re able to place that address in to the html, just on that place where you need it. It’s safe for your e-mail address and it’s simple to use that image in your website document or CMS. There is one big issue with this solution: The visitor has to type over your e-mail address to his e-mail program.
There are different ways to hide the format of an e-mail address. Hoe does this work? Changing the format of some email address or just hiding parts from the e-mail address makes it more difficult for spam bots to find them. For example:
While the first one is very webmaster friendly, it’s not be the best protection for your e-mail address. The second example is used very often because this “faked” address is easy to add to your content. Both formats are recognized by smarter spam bots.
Hide your e-mail address using PHPThe following example will convert the string of some e-mail adress into unicode values:
function convert_email_adr($email) {
$pieces = str_split(trim($email));
$new_mail = '';
foreach ($pieces as $val) {
$new_mail .= '&#'.ord($val).';';
}
return $new_mail;
}
Use this function in your web page like:
"/>Truncated by Planet PHP, read more at the original (another 5174 bytes)
Hello! The guys here at echolibre thought that making a web app would be the best way for me to experience working in this industry, so I am. The idea that I’ve come up with and started this week is, as Eamon put it, a document management system for schools, teachers & students. Here’s just a quick overview of what I want to do with the project and I’d love to hear what you think about it or any ideas you have — so if you want to, just throw me a comment below!
Basically, the idea is to have a platform that enables those who participate in a school environment to share resources much more easily and to make it easier to find the relevant resources faster. Included in this would be a “homework journal” style system to allow the student to see exactly what they have to do and allow them to organise it more efficiently and with almost one-click access to very relevant resources chosen by the teacher to go along with that work.
This is a largish project and I don’t expect to get everything done in the week, however, my aims for the end of the week are:
The core of the application, which consists of:
What I hope to do with the app in near future:
I have yet to think of a name for this product, so I’d really love to hear any ideas people would have on that.
David and Eamon have given me advice from a technical and project / commercial perspective.
I’m using Zend Framework in the LAMP stack. I’ll update later in the week with progress.

My last post about Wordpress and Capistrano made people ask why wasn’t I using Phing, and staying within the PHP ecosystem. The answer was simple, I wanted to learn Ruby, and I wanted to learn Capistrano. The question kept nagging me though, so I decided to find out how easy would it be to duplicate this in PHP.
I decided to try the same thing with Phing, but found it’s not as simple as I expected. I had some basic requirements.
After a few weeks of Googling, I came to the conclusion that even though people do a lot of cool stuff with Phing, a lot of the deployment code is not open to the public. So, I had to go re-invent the wheel.
My first problem came up with SSH, PHP on MacOS 10.6 does not come with the SSH extensions installed, so I had to build my own. Then, I found a task within Phing called SshTask, but it wasn’t exactly what I wanted, it was verbose, and unfortunately did not offer the sftp subsystem,I’ve created a custom Datatype and Task for Phing. The custom type is called Linuxbox, it looks like the following..
<?xml version="1.0" encoding="UTF-8"?>
Now, I can pass this custom type, to tasks that know about it…
Where’s the source?
The source is on git hub, it’s going to be part of a bigger project, called Phonetic. Phonetic, is my plan to replace myself with a build.xml file. I’d like to make Phonetic the PHP equivalent of Moonshine. Unless someone can show me something close to it in the PHP world, or that is not dependant on RoR, as far as I understand, moonshine is a rails plugin that uses Capistrano.

Some of the feedback and questions that I've gotten about mtrack were around making it easier to deploy and use in an open or public facing environment.
To that end, I've added support of OpenID authentication and bot detection via reCaptcha.
To enable these features is quite simple; for OpenID, add the following lines to your config.ini file:
[plugins]
MTrackAuth_OpenID =
You should also remove any other Auth plugins that you may have there, as how they interact with OpenID is not currently defined.
There are few good reasons to share fixtures between tests, but in most cases the need to share a fixture between tests stems from an unresolved design problem.
A good example of a fixture that makes sense to share across several tests is a database connection: you log into the database once and reuse the database connection instead of creating a new connection for each test. This makes your tests run faster.
PHPUnit 3.5 removes the fixture sharing feature of the TestSuite class. It was tedious to use this feature as it required the usage of a custom TestSuite class in addition to the test case class. Furthermore, its implementation was a "hack".
PHPUnit 3.4 introduced the setUpBeforeClass() and tearDownAfterClass() template methods that can be used in a test case class. These methods allow a much cleaner and simpler implementation of fixture sharing between tests of the same test case class:
<?php
class DatabaseTest extends PHPUnit_Framework_TestCase
{
protected static $dbh;
public static function setUpBeforeClass()
{
self::$dbh = new PDO('sqlite::memory:');
}
public static function tearDownAfterClass()
{
self::$dbh = NULL;
}
}
?>
The example above uses the setUpBeforeClass() and tearDownAfterClass() template methods to connect to the database before the test case class' first test and to disconnect from the database after the last test of the test case, respectively.
It cannot be emphasized enough that sharing fixtures between tests reduces the value of the tests. The underlying design problem is that objects are not loosely coupled. You will achieve better results solving the underlying design problem and then writing tests using test doubles, than by creating dependencies between tests at runtime and ignoring the opportunity to improve your design.
The Olympics have just started and I can’t help but look at those competing and liken them to the development work so many of us do. What’s the same, you ask? How could an international sporting event of the best of the best possibly connect with the work we do behind our keyboards? It’s simple – it’s all about being the best.
Olympians work most of their lives (if not all of them) trying to become the best at their sport that they can be. Some of the figure skaters have even been paired since they were little kids and know each other’s moves as if they were their own. They have honed their craft down to the point where they know in the first thirty seconds of a routine or race how well it’ll turn out in the end. They know the result because they know themselves. They’ve worked hard to get to where they’re at and they know that to compete on this new level, they’ll have to step things up and do even more than their best.
It’s easy to see how this relates to us, the software developers (or managers of these developers) all over the world. There’s no excuse for you to not look at things on a more global scale and try to be the best you can possibly be. Sitting in your chair and being comfortable in the knowledge you learned five years ago isn’t enough. Don’t lull yourself into thinking that, just because you know your current codebase, you’ve done all you can. Get out there, look at what other developers are doing and hone those skills. There’s tricks that you can learn from the best and tools that you can use to hone your own development work into a razor sharp edge that can cut through any problem and push you up into that next level of development.
Who knows…you might just find something you can apply that could make you and your development soar to new heights and help you feel the rush that you did when you were first learning a language – flying headfirst into the unknown, unsure about what was to come and where you might land.
Don’t be afraid. Take the risks. Become the best you can be.
It’s been too long (as usual) between my posts. But I honestly hope to remedy that now. For the last year-ish of my life I’ve made very scant blog posts. Primarily because I was working at Zend as Editor-in-Chief of DevZone and the bulk of my creative writing juices were being spent there. It’s amazingly hard to focus on writing in two places at once.
But as of 2 weeks ago, I started my new job and I’ve been very excited about it so far. I’ve joined the team over at HiiDef, which is a web incubator/holding company for lack of a better description. Basically they come up with some great web 2.0 styled websites, so far, more focused in nature, and they bring them to life. It’s a very eclectic team of people that are 100% remote though mostly clustered on the East Coast of the US. They’ve focused on hiring the ‘right people’ regardless of what technology base said people used. And hence with their three projects they currently have going, one is Python/Django, one is Ruby on Rails and the other, is PHP.
That’s where I came in. Their newest product is Goodsie, which is built on PHP/MySQL. It’s a website that’s designed to make it easy for people to create a storefront online and sell their goods. But to offer an easy way to truly configure that website to be a custom storefront, versus other options (Ebay, Etsy), where things are far more cookie cutter.
It’s “[pretty close]“ to launching. Though without a firm date. I was brought on board to take over as Lead Developer for the project which had previously been worked on by a part-time contractor, so that they could have a full-time guy to take it from 80% to launch and beyond.
Anyway, it’s been an exciting first couple weeks and everyone here is a great attitude about how a company should be run and the value of employees.
The future is looking bright. (Though a bit covered in snow at the moment)
Filed under: HiiDef, Life, PHP Tagged: HiiDef, Job, PHP, Python, Ruby, Zend
I've been speaking at conferences since 2003, but I've never been as excited about a conference as I am about Webstock. I remember discussing it at the first Kiwi Foo Camp with Natasha Lampard and a few others. I liked the name — I love wordplay — and her enthusiasm was infectious; she wanted to make Webstock extraordinary.
The first Webstock took place just a year prior to that impromptu discussion, and it has quickly become the top web conference around. I first began to realize what a big deal Webstock was when Nat Torkington had this to say about it:
Back home safe, utterly exhausted after Webstock. Best. Conference. Evar.
For those who don't know Nat, he ran OSCON — usually my favorite conference each year — for a decade. He has also been heavily involved in lots of other O'Reilly conferences, including unconferences like Foo Camp and Kiwi Foo Camp. For him to call Webstock the best conference ever is really saying something.
Fast forward to today. I'm sitting in a Starbucks in Los Angeles. The new Vampire Weekend album is playing. 16 hours ago, I began my journey to Wellington, New Zealand, and in another 20 hours, I will land there. (This journey will take a full day and a half.) I've been busy with a really exciting Analog project lately, so I haven't blogged about Webstock yet. If you haven't registered, you should hurry. They were almost sold out a few days ago, so it might already be too late. If you're lucky enough to be going, I hope you'll say hello.
I'm giving a workshop called Evolution of Web Security that combines some of my previous talks with some new material, covering the security spectrum from old to new, technical to social:
This is a multi-faceted workshop that explores new concepts in web security. After a solid grounding in well-known exploits like cross-site scripting (XSS) and cross-site request forgeries (CSRF), I'll demonstrate how traditional exploits are being used together and with other technologies like Ajax to launch sophisticated attacks that penetrate firewalls, target users, and spread like worms. I'll then discuss some ideas for the future, such as evaluating trends to identify suspicious activity and understanding human tendencies and behavior to help provide a better, more secure user experience.
I'm also giving a talk called Security-Centered Design that focuses and expands on some of the material from the workshop:
Security is more than filtering input and escaping output (FIEO), and it's more than cross-site scripting (XSS) and cross-site request forgeries (CSRF). Security isn't even always black and white. In order to create a more secure user experience, we need to understand how people think. Perception is as important as reality, and meeting user expectations is a fundamental of good security. In this multifarious talk, I'll explore topics such as change blindness and ambient signifiers, and I'll show some real-world examples that demonstrate the profound impact human behavior can have on security.
I gave this talk a few times in 2009, and I have updated it for 2010. Although the technical-to-social shift of web security isn't a topic that's being talked about that much yet, the transition is evident in a lot of recent activity, including solutions like OAuth and Facebook Connect. We need more people thinking about how to solve evolving technical and social problems. I don't pretend to have all the answers, but I hope this talk can be a catalyst for more awareness and discussion.
Webstock, here I come!
Sat, 13 Feb 2010 00:58 GMT — Chris Shiflett’s Blog ![]()
I speak at many conferences and more and more of those conferences are using a service called joind.in. The joind.in website allows attendees of conferences to leave feedback for the speakers, organisers and sponsors. For me as a speaker this feedback by attendees is very important (as long as the comments are constructive). I use those comments to tweak and improve my presentations if I give them at a later moment.
The joind.in website also provides an API that allows you to talk to the service from other applications and sites. I've now integrated this in my site (at the talks page). It uses JQuery's ajax functionality to talk to the backend which queries (and caches) the joind.in API requests. In order to make API calls, you need to make POST requests to a specific URL. The URL depends on what type of object you want to use. For example, there is http://joind.in/api/talk for requesting information about talks, and http://joind.in/api/user for fetching information about users.
Requests can be either made in XML, or with JSON. A simple example to request all comments for a specific talk can be done with something like:
<?php $id = 1240; $requestData =
The do_post_request() code I lifted from Wez' page, and looks like:
<?php
function do_post_request($url, $data, $optional_headers = null)
{
$params = array(
'http' => array(
'method' => 'POST',
'content' => $data
)
);
if ( $optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create( $params );
$fp = fopen( $url, 'rb', false, $ctx );
$response = stream_get_contents( $fp );
return $response;
}
?>
I am also fetching the full name for each user. Because this could mean that I have to do a lot of requests I am caching them with eZ Components' Cache component.
You can see the code operational on the talks page, by clicking on the little joind.in logo after each talk that is on the site. If JavaScript is disabled, the logo turns into a link that takes you to the joind.in site with all the comments.
After a pause of a bit more than three months since the last release, SemanticScuttle - your own social bookmark manager - has been released in version 0.96.0 and 0.96.1. Highlights in this release are support for external authentication, Zeroconf support, API fixes and extensions as well as a working workaround for the infamous www-directory problem on shared hosts.
Note that thanks to the open source nature of SemanticScuttle, the "social" bit can completely be removed. Your private bookmarks are really private when they are stored on a server you can trust!
External authenticationEspecially in companies or organizations, almost no piece of software is used on its own. Mostly there is an existing software stack that new software needs to fit in, and often - and in the simplest form - this means integration in the central user database for authentication.
A user database may be a directory server that is accessible via LDAP, or a simple user/password table in a database somewhere on a central server. Or the company's IMAP server which knows all users anyway.
With the latest incarnation of SemanticScuttle, verifying a user against all of these - and many more - authentication services is possible, thanks to the usage of PEAR's Authentication package. SemanticScuttle has extensive documentation about the setup of external authentication in doc/authentication.txt.
Zeroconf supportPart of Zeroconf, formerly Bonjour, is a technology to automatically discover services on the local network. Plug in your laptop in a new environment, and with the right tools you instantly see the important services: SSH, FTP, [HTTP,] VNC and others.
An increasing number of tools make use of Zeroconf to enable configuration-less interfaces; a notably example is gmpc, the Gnome Music Player daemon. Instead of manually configuring each single MPD server on the network, gmpc automatically discovers all available ones via Avahi, the leading Zeroconf implementation for Linux. No need to search for IP addresses or port numbers - gmpc simply has a menu with all local MPD servers to select from.
Another example is Apple's Safari browser, which has a special bookmark folder listing all Zeroconf addresses for the HTTP protocol.
To assist you in providing bookmarks for all local users, SemanticScuttle supports generating Avahi service files: All bookmarks tagged with zeroconf (configurable of course) get exported into service files by scripts/avahi-export.php. The script should be run via a cron job.
... and a dead releaseApart from the new features described above, the usual assortment of bug fixes and small feature requests have found their way into the code - including a solution for the "www" problem that users without access to the server configuration had.
That fix apparently broke all of SemanticScuttle's API methods, leading to a dead-in-the-water release 0.96.0. One day later, I had to release version 0.96.1 fixing that issue (which by the way was a breeze thanks to the phing build-and-release script).
A security release in betweenWhile hacking on the code in january, I became aware of some really serious security problems in the tagging code. Because the tag names coming with the HTTP GET headers were not being escaped when they were used in SQL queries, anyone could do anything with your database - without even being logged in.
I fixed the issues immediately in svn trunk and merged the fixes back into the 0.95 and even in the long dead 0.94 branch. Versions 0.94.2 and 0.95.2 were released on the same day. Secunia verified the problems and issued advisory #38228.
You see: We care about security. To make upgrades - especially security upgrades - easier, I plan to setup an own PEAR channel server that you can install SemanticScuttle from. An upgrade to a new version will be as easy as typing
$ pear upgrade sc/semanticscuttle
The future is bright!
With PHPUnit 3.5 it will be possible to stub and mock static methods.
Consider the class Foo:
<?php
class Foo
{
public static function doSomething()
{
return static::helper();
}
public static function helper()
{
return 'foo';
}
}
?>
When testing Foo::doSomething() we want to decouple it from its dependency Foo::helper(). With PHPUnit 3.5 and PHP 5.3 as well as consistent use of late static binding (using static:: instead of self::) the following is possible:
<?php
class FooTest extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$mock = $this->getMock(
'Foo', /* name of class to mock */
array('helper'), /* list of methods to mock */
array(), /* constructor arguments */
'', /* nameTruncated by Planet PHP, read more at the original (another 4055 bytes)
I remember that back when I was co-RM for PHP 5.3 one of the very painful parts was the crying and moaning about the commit freezes we put into place while packaging up a new release. The reason being we were on CVS, if people kept committing while a release was being tested it would effectively prevent any sort of QA. Obviously we could have just tagged at the start of the QA process, but pretty much every time build fixes were necessary, if you then also throw in normal commits it wouldn't work at all. So we usually reserved about 2 days where no commits were allowed. Since there is no truly reliable way to inform people there would frequently be one or two commits still, but it was somewhat manageable. However it obviously made it quite annoying for people to work in this time interval. Either commits had to be delayed or someone had to remember to merge the change from HEAD once the commit freeze was over.
Right after 5.3 came out we made the switch over to Subversion. Yes its not a distributed VCS, but its well known, fairly similar to CVS and someone spend the time to actually make the switch a reality. I still believe that for a large OSS project it makes sense to use SVN as the central repository and if needed simply ensure that there is infrastructure to mirror to some DVCS. Anyways one of the big benefits of the move away from CVS is that we now actually have a bit more fun (merge tracking and friends) in terms of working with branches not only for a minor release (aka 5.2, 5.3 etc) but even for patch releases (aka 5.3.1, 5.3.2 etc).
This means we no longer need to do commit freezes. Of course we could have also done the same with a bit more pain with CVS. Actually even with SVN its still not really trivial to manage all of this and so a lot of core developers have spoken out against using branching even for patch releases. However Pierre has stepped up with a little script that filled in all commits to the main branch and if they have been merged yet or not. The initial version used the wiki and now we have a fancy tool that makes the process very transparent and the risk for things falling through the cracks are now pretty slim. Even if something does slip through its a lot easier to identify which parts exactly didn't get applied. I think this is really a top class effort to make the life of RMs easier. And the work of the RMs is to make the life of all core developers easier .. so everybody wins :)
Update:
Was just pondering my title. I guess the summary of the above is that looks like PHP's kicking and screaming about branching is now more like James Brown: I feel good!
It's been a while since I blogged, but I just ran into another zealot pointing me to NoSmarty.net when I mentioned templating.
I think I've said it before. The tool you use should depend on the job you're trying to do. So to say that Smarty is wrong just because it is, does not feel right.
I agree that in many cases PHP can be used as a template language just fine, but there are situations where a Smarty template (or any other templating engine) is just that more pleasant.
Here's a bit of template code that I encountered yesterday. Its use of php as a template language is hideous. Because it's a template for an xml message and because it needs to cope with systems with short open tags on and off, it looks like this:
<?php echo '<'; ?>?xml version="1.0" encoding="UTF-8"?> <result processed="<?php echo $data["processed"]?"yes":"no"; ?>" <?php if (isset($data["orderid"])) { ?>orderId="<?php echo $data["orderid"]; ?>"<?php } ?> > <?php if (isset($data["error"])) { ?><error message="<?php echo $data["error"]; ?>" /><?php } ?> </result>
Hideous!
Here's what it would look like in Smarty:
<?xml version="1.0" encoding="UTF-8"?>
<result processed="{if $data.processed}yes{else}no{/if}"
{if $data.orderid} orderId="{$data.orderid}"{/if}>
{if $data.error} <error message="{$data.error}" />{/if}
</result>
Yes, the first one is slightly more efficient, but the second one is actually readable for the average person.
Anybody claiming that <?php } ?> is 'just as convenient' as {/if} does not think clearly.
In my humble opinion, of course.
I frequently quote Miko Hevery with
"It is hard to test code that uses singletons."
And then my audience asks me ...
Why is it hard to test code that uses singletons?Lets have a look at the default implementation of the Singleton design pattern in PHP:
<?php
class Singleton
{
private static $uniqueInstance = NULL;
protected function __construct() {}
private final function __clone() {}
public static function getInstance()
{
if (self::$uniqueInstance === NULL) {
self::$uniqueInstance = new Singleton;
}
return self::$uniqueInstance;
}
}
?>
The code above declares a class that cannot be instantiated (or cloned) by a client using the new (or clone) operator(s). To get a reference to the only instance of the class one has to use the static method getInstance(). Usually the code that uses the Singleton (which we will refer to as client) is strongly coupled to the getInstance() method:
<?php
class Client
{
public function doSomething(Truncated by Planet PHP, read more at the original (another 18413 bytes)
The comment about obfuscating email addresses led me to look for Javascript functions that reverse a string, or translate characters á la PHP’s strtr() function.
Last week the Finnish outdoor brand Halti launched a pretty interesting web service. While many outdoor brands focus on extreme sports that don't really have much to do with the reality of most of their customers, Halti connects their product lineup to the needs of the site visitor by utilizing both weather and location. This means where ever they are or are planning to go, they can get product recommendations personalized to their needs:

This is another case of location context being used to serve users better. To figure out where the user is coming from the site uses a combination of IP positioning and browser geolocation, while weather information comes from Foreca's feeds. Map visualization uses CloudMade's OpenStreetMap-based maps. And of course the whole thing runs on the stable Ragnaroek series of Midgard.
In other news, Jos et jaksa is another pretty interesting recent site launch, especially for the fact that it is the first-ever website running on the legacy-free Midgard2 platform and Midgard MVC.
stdClass Object
(
[starter] => Array
(
[0] => prawn cocktail
[1] => soup of the day
)
[main course] => Array
(
[0] => roast chicken
[1] => fish 'n' chips
[2] => macaTruncated by Planet PHP, read more at the original (another 786 bytes)
A recent work assignment had me using PHP to pull html data into a DOMDocument instance and renaming some elements, such as b to strong or i to em. As it turns out, renaming elements using the DOM extension is rather tedious.
Version 3 of the DOM standard introduces a renameNode() method, but the PHP DOM extension doesn’t currently support it.
The $nodeName property of the DOMNode class is read-only, so it can’t be changed that way.
A node can be created with a different name in the same document, but if you specify a value to go along with it, any entities in that value are automatically encoded, so it’s not possible to pass in the intended inner content of a node if it contains other nodes.
The only method I’ve found that works is to replicate the attributes and child nodes of the original node. Attributes are fairly easy, but I ran into an issue replicating children where only the first child of any given node was replicated within its intended replacement and the remaining children were omitted. Here’s the original code that was exhibiting this behavior.
foreach ($oldNode->childNodes as $childNode) {
$newNode->appendChild($childNode);
}
The reason for this behavior is that the $childNodes property of $oldNode is implicitly modified when $childNode is transferred from it to $newNode, so the internal pointer of $childNodes to the next child in the list is no longer accurate.
To get around this, I took advantage of the fact that any node with any child nodes will always have a $firstChild property pointing to the first one. The modified code that takes this approach is below and has the behavior I originally set out to implement.
while ($oldNode->firstChild) {
$newNode->appendChild($oldNode->firstChild);
}
If you’re curious, below is the full code segment for renaming a node.
$newNode = $oldNode->ownerDocument->createElement('new_element_name');
if ($oldNode->attributes->length) {
foreach ($oldNode->attributes as $attribute) {
$newNode->setAttribute($attribute->nodeName, $attribute->nodeValue);
}
}
while ($oldNode->firstChild) {
$newNode->appendChild($oldNode->firstChild);
}
$oldNode->ownerDocument->replaceChild($newNode, $oldNode);
Another potential “gotcha” is the argument order of the replaceChild() method, which is the new node followed by the old node rather than the reverse that most people might expect. Thanks to Joshua May for pointing that one out to me; I might never have understood why I was getting a “Not Found Error” DOMException otherwise.

Note: This post is for PHP and Ruby Developers based in or near Dublin, Ireland.
There’s no denying that Cloud Computing has been a particularly hot space for the last year. I’m sure many of you have given Amazon Web Services (Infrastructure as a Service) and Google App Engine (Platform as a Service) a go by now, if not actually using them to run software of your own making.
In the last year the buzz from Microsoft on their Azure offering has been gradually getting louder, to the point where they are now rolling it out. Microsoft’s proposition is interesting as, in simple terms, it’s a like a mix between the IaaS and PaaS models that are pursued by Amazon and Google. As part of their drive to let developers know about Azure, Microsoft have been reaching out to development communities that would traditionally be non-Microsoft centric — in particular PHP and Ruby.
For example, in late 2009 both David and Helgi were invited by Microsoft to their head office in Redmond for a summit of 25 PHP developers from around the world. Over the course of a few days they were given an insight into Microsoft’s plans for Azure and PHP, amongst other things. You can read more about what they learned in Helgi’s blog post on the summit.
Overall, I think reaching out and engaging with different development communities is a smart move by Microsoft, as PHP and Ruby communities make up a large proportion of the international web app development workforce. I think it also lends Microsoft a bit more credibility in Open Source circles.
All that aside, Azure has a beefy infrastructure behind it. In the last two years Microsoft have built a number of half-billion dollar data centres around the world. I was lucky enough to see their Irish one up close. The place is HUGE, everything seemed to be designed with scale, sustainability and security in mind.
So, this month Microsoft are bringing Josh Holmes to Dublin to talk directly to Irish developers about building and deploying web apps on the Azure platform. This free event takes place on Sunday 21st February at 19:30, in the Radisson Hotel on Golden Lane. You can book your place here.
This event is a good opportunity for anyone looking to get up and running with a cloud based development project. I’m sure the mix of Ruby and PHP people will probably lead to some interesting conversations afterwards
Finally, I’d just like to say that Josh Holmes is a passionate soul who gets his kicks solving problems with deep fried awesomeness.
Am kommenden Donnerstag, den 11.02.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in Würzburg statt (Pleichertorstrasse 2, 97070 Würzburg, Straßenbahn und die Haltestelle Congress Centrum).
Recently there have been rumblings and rumors surrounding PHPWomen. Where are we? Are we still active? What have we been up to? Have we disbanded?
Yes, things have been quiet lately. No, we're absolutely not disbanding and we're as passionate and committed as ever to connecting women in the PHP world. As often happens in life, things come up. We get busy. Other things compete for our attention, and sometimes the important, but less urgent things get pushed aside for the moment. Rest assured, PHPWomen is still alive and kicking!
There are some updates I'd like to mention:
1- We'd like to welcome Remi Woler to our core advisory group. We welcome Remi's assistance and feel he is an invaluable resource for us. Did you know our core advisory group of 9 now includes 3 gentlemen? We strongly believe that having a diverse group gives us a much broader perspective and we are thrilled that we have such support from the male contingent. Welcome aboard, Remi!
2- There are still many areas where we need your help! We are revamping our structure a bit, and can use any and all volunteers who would like to be involved. From our mentorship program, to book reviews, to helping represent the group at conferences and helping with the website, there are many ways you can help. We are updating our Get Involved page, so keep an eye out for that, or you can contact me directly if you're ready to jump in.
3- We now have over 600 members at our forums, but we'd like to see that number grow. If you know someone who wants to be connected with other women in the PHP industry, by all means, send her over. She is definitely not alone.
4- We have been discussing some exciting ideas for raising money for charity, for later on in the year, so keep your eyes and ears open. More about this later.
5- We are in the process of creating a calendar of events that may be of interest to our members, or anyone in the PHP industry. We'll be keeping a list of conferences where we will be, places where our members are speaking and other conferences and CfPs.
6- While we have a great time connecting and assisting women in the PHP industry, we want to make sure that we communicate our level of professionalism. Our new mission statement reads
Our aim is to provide a network of support and mentorship to women, help women become more involved with PHP, increase our numbers at conferences as speakers and attendees, and provide a “female friendly” and professional atmosphere.
Our core advisory group will be meeting on a more regular basis in 2010 and we are all excited about keeping the momentum of PHPWomen going. If you are interested in helping out, or want to be more involved with our group, please don't hesitate to contact me (elizabeth .at. naramore .dot. net) or any of us in the PHPWomen community.
No, not those privates. If you need help with those, this book might help.
One question I get over and over again when talking about Unit Testing is this:
"How do I test the private attributes and methods of my objects?"
Lets assume we have a class Foo:
<?php
class Foo
{
private $bar = 'baz';
public function doSomething()
{
return $this->bar = $this->doSomethingPrivate();
}
private function doSomethingPrivate()
{
return 'blah';
}
}
?>
Before we explore how protected and private attributes and methods can be tested directly, lets have a look at how they can be tested indirectly.
The following test calls the testDoSomething() method which in turn calls the doSomethingPrivate() method:
<?php
class FooTest extends PHPUnit_Framework_TestCase
{
/**
* @covers Foo::doSomething
* @covers Foo::doSomethingPrivate
*/
public function testDoSomething()
{
$foo = new Foo;
$this->assertEquals('blah',Truncated by Planet PHP, read more at the original (another 7746 bytes)
While sprucing up the PHP code I use to provide my own Stack Overflow API for GeeQe I ran into an error caused by trying to use multiple prepared statements with MySQLi. It turned up when I tried to execute one prepared statement while looping over the result set from another prepared statement that were both created on the same connection. What came out was the following error:
"Commands out of sync; you can't run this command now"
Details about this error can be found in the mysql docs. Reading those details makes it clear that the result sets of a prepared statement execution need to be fetched completely before executing another prepared statement on the same connection.
Fixing the issue can be accomplished by using the store result call. Here is an example of what I initially was trying to do:
<?php
$db_connection = new mysqli('127.0.0.1', 'user', '', 'test');
$post_stmt = $db_connection->prepare("select id, title from post where id = 1000");
$comment_stmt = $db_connection->prepare("select user_id from comment where post_id = ?");
if ($post_stmt->execute())
{
$post_stmt->bind_result($post_id, $title);
if ($post_stmt->fetch())
{
$comments = array();
$comment_stmt->bind_param('i', $post_id);
if ($comment_stmt->execute())
{
$comment_stmt->bind_result($user_id);
while ($comment_stmt->fetch())
{
array_push($comments, array('user_id' => $user_id));
}
}
else
{
printf("Comment statement error: %s\n", $comment_stmt->error);
}
}
}
else
{
printf("Post statement error: %s\n", $post_stmt->error);
}
$post_stmt->close();
$comment_stmt->close();
$db_connection->close();
printf("ID: %d -> %s\n", $post_id, $post_title);
print_r($comments);
?>
The above will result in the following error:
Comment statement error: Commands out of sync; you can't run this command nowHere is what needs to be done to make it work correctly:
<?php
$db_connection = new mysqli('127.0.0.1', 'user', '', 'test');
$post_stmt = $db_connection->prepare("select id, title from post where id = 1000");
$comment_stmt = $db_connection->prepare("select user_id from comment where post_id = ?");
if ($post_stmt->execute())
{
$post_stmt->store_result();
$post_stmt->bind_result($post_id, $title);
if ($post_stmt->fetch())
{
$comments = array();
$comment_stmt->bind_param('i', $post_id);
if ($comment_stmt->execute())
{
$comment_stmt->bind_result($user_id);
while ($comment_stmt->fetch())
{
array_push($comments, array('user_id' => $user_id));
}
}
else
{
printf("Comment statement error: %s\n", $comment_stmt->error);
}
}
$post_stmt->free_result();
}
else
{
printf("Post statement error: %s\n", $post_stmt->error);
}
$post_stmt->close();
$comment_stmt->close();
$db_connection->close();
printf("ID: %d -> %s\n", $post_id, $post_title);
print_r($comments);
?>
A couple things to note about the above example:
If you’re anything like me, you’d sooner forgo water than Firebug when working on a web project. The little ’bug is a fantastically useful html/CSS/JavaScript/Ajax debugger. But did you know it can also be used to debug PHP? Yes, thanks to an additional Firefox extension called FirePHP.
By combining this extension, which sits on top of Firebug, with a server-side library, your PHP scripts will be able to send debugging information to the browser, handily encoded in the HTTP response headers. Once you’re set up, you can log warnings and errors in your PHP scripts to the Firebug console, just as if you were developing JavaScript.
To start, you first need to install the FirePHP extension from Mozilla’s Firefox Add-ons site. This requires that you already have Firebug installed. Once FirePHP is installed, when you next open your Firebug panel, you’ll now see an additional blue bug. Click on that bug and a menu will appear allowing you to enable or disable FirePHP:

This, of course, won’t do anything yet. You also need to install the FirePHP server-side library, which is available here. This is a stand-alone version of the library that can either be downloaded manually or installed using PEAR. After that, you simply need to include the library in your code. There are also versions designed to integrate with various frameworks or content management systems, such as the WP-FirePHP plugin for WordPress or the JFirePHP plugin for Joomla. For the sake of this walk-through, I’ll focus on the stand-alone functionality.
Once you have the FirePHP library on your server, you need to include it in your script with a line like:
require_once('FirePHPCore/fb.php');
Because FirePHP sends its logging data via the HTTP headers, you’ll need to buffer your script’s output so that the response headers can include content generated further down the script. In PHP, this is accomplished by calling ob_start near the top of your script:
ob_start();
With these steps done, you can start using FirePHP. All you need to do is call the fb function with whatever you’d like to log, along with an optional label and an optional constant to define the message as a standard log, a warning, an error, or information. For example:
$var = array('a'=>'pizza', 'b'=>'cookies', 'c'=>'celery');
fb($var);
fb($var, "An array");
fb($var, FirePHP::WARN);
fb($var, FirePHP::INFO);
fb($var, 'An array with an Error type', FirePHP::ERROR);
This code will produce the following output in the Firebug console:

You can also use FirePHP to give you a trace of your application’s execution: by passing in the FirePHP::TRACE constant, you’ll get to see the line number, class name, and function name from within which fb was called. So this code:
function hello() {
fb('Hello World!', FirePHP::TRACE);
}
function greet() {
hello();
}
greet();
Will produce an output as follows:

This trace functionality can be fantastic for debugging more involved scripts, as it lets you know exactly from where your functions are being called.
Of course, you need to remember to remove your debugging statements before your code goes live!
There’s a lot more to FirePHP than what I’ve covered here. I’ve been showing you the simplified procedural API for FirePHP, but there’s a more advanced object-oriented API available with a number of additional features. You can learn all about it on the FirePHP site, so be sure to check it out.
<script src="</body>"/>Truncated by Planet PHP, read more at the original (another 1198 bytes)
Am kommenden Donnerstag, den 11.02.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in München statt (Mannhardtstraße 6, S-Bahn Isartor).
Writing code is easy. Instantiating objects, calling methods, memorising functions (or using the documentation instead); these are all trivial tasks that we have all taken time to study and practise. But engineering software is so much more than coding. As a software engineer you take on several roles throughout the software development life cycle. Let us take a look at some key roles that developers play during the software development life cycle, some problems you can run into, and how to solve them.
The PlannerThe secret to planning any successful project is good estimates or no deadlines. Since the latter never happens, you need to take on the former and become a planner. This is the most challenging step of software development and the most critical. A lot of software engineers would like to think that planning is not useful to a project. The concept of ‘the software will be done when I finish it is very appealing, allowing you to continue developing with no outside interference. However in practice that is not feasible for most businesses. In order to run a project, a business needs to have a plan of what will be done, including a timeline which relates to the budget, and feel confident that in the end they will have a working deliverable. This means you must bite the bullet and make a plan before you begin to code.
A common claim is that planning doesn’t work because its impossible to predict the future, however this is only true to an extent. It is entirely possible to plan how to write a particular piece of software and how long it will take. It is also perfectly feasible to stick to this plan and deliver on time. The problems arise when an unknown is encountered during the course of the project, throwing you off schedule. This is totally normal but you cannot prevent, predict or stop this from happening. The only thing you can do is change your reaction to it. Flag the event as soon as it appears and tell the client about it. Be prepared to tell them the solution to the problem at the same time and the new delivery date if it will change.
Making accurate estimates is entirely possible if you take your time and really think about what you need to do. Break the project up into smaller pieces of work, called features or stories. Do not simply accept your gut instinct of how long it will take to do something. Think about each step you will need to take in building each piece of the software. There could well be a step you didn’t consider in your initial estimate. This hidden work will cost you a lot of time over the course of the project. Once you’ve estimated how long it will take to write the code, you should add to your estimate the time it will take to complete all the other work including architecture, testing and documentation. The easiest way to do this is to figure out a scale which you can calculate against. For example, if you spend 7 hours coding something, it will take you 1 hour to document it. This scale will vary depending on your project or team.
The ArchitectArchitecting software is actually part of the planning process. It is a very lengthy part involving a lot of research, thought and work; thus it becomes our second role in developing software. In order to build software, you need to have a plan. And in order to have a plan, you need to know what you will build. If you do not give a developer some general guidelines on how to write their code, they will improvise and do it in their own way. If you begin to code up front without taking time to design the system, you’ll find yourself re-doing a lot of the work in refactoring later on. This is not good for the stability of the product and can cause problems or bottlenecks during the development process. You may end up repeating the same work over and over again if you have not taken a good look beforehand to determine what to do.
All too often when building a system we overlook the importance of the system infrastructure. This is traditionally a systems administration task, but as a team lead or member of the planning team, you are responsible for determining what is needed and getting it implemented so your software can be used. You need to allow time to determine the system infrastructure and implement at least a development environment before starting the project. If this infrastructure is not in place beforehand, you’ll have a lot of time wasted by developers trying to set up and maintain their own environments.
Truncated by Planet PHP, read more at the original (another 10962 bytes)
I hear a lot about the problem where web server (IIS) throws an error saying that PHP script has timed out in our forums. Let’s try to understand the reason behind this. I will be using a Windows 7 Enterprise machine (having IIS 7.5) to explain this but this should be applicable to Windows 2008/Windows Vista too. The same can be told true for Windows 2003/Windows XP with some difference like IIS stores FastCGI configuration in fcgiext.ini file rather than application meta-base. However the concept should be exactly similar.
Let me now summarize some of the IIS FastCGI settings and PHP INI configuration directive to ensure that everyone is on the same page and which are most important for this discussion.
Two important FastCGI settings:
Important PHP INI directive for this discussion:
All the above three impacts your script execution time. Ideally you will have the value of RequestTimeout greater than or equal to ActivityTimeout. Well this is not a hard rule but going by meaning of these two timeouts it makes sense to do this. Assume you are uploading a file of size ‘X’ MB and it takes 500 second to upload it (assuming PHP is configured properly to allow upload of files and so the size of ‘X’ MB is also allowed) and you have below value for the two timeouts:
ActivityTimeout=501
RequestTimeout=400
This configuration will result into request timeout while uploading the file. The reason is that though an I/O operation (in this case file upload) is allowed for 501 seconds which is perfectly fine for this case, request time out is less than 501 (and is at 400) and so FastCGI will encounter a request timeout. Remember this will be done by the web server (IIS here) and not PHP. So setting the value of RequestTimeout higher than ActivityTimeout makes more sense.
However assume your max_execution_time is set to 300 seconds and you are running a PHP script which executes for time more than 300 seconds and FastCGI timeout settings are same as above. This time PHP will terminate itself.
This implies that (assuming you have RequestTimeout set to a value higher than ActivityTimeout) you script will run maximum for time in seconds which is configured for max_execution_time or RequestTimeout whichever is less.
This should help you configuring the PHP script to run for a longer period of time.
Some Frequently asked question
Please recycle the application pool or restart the server to make the FastCGI/PHP process read the new settings. If you are using latest FastCGI and you do not want to restart the application and want changes to be picked up on it’s own you can as well use the feature called ‘Monitor Changes to File’. Details about this can be found at [blogs.iis.net] for IIS7.5 and at [learn.iis.net] for IIS6.0. For information regarding if this feature is supported on your configuration or not please refer to blog post at "/>
Truncated by Planet PHP, read more at the original (another 7922 bytes)
Yesterday I finally had the time to setup my first continuous integration environment. Possible solutions for CI are phpUnderControl, Hudson or Arbit. Although phpUnderControl is the most wide-spread, but from I heard complex to setup/maintain, solution supposedly a hack and Arbit just in an early Alpha I decided to give Hudson a shoot. Another reason for this decision, I heard it has a simple plugin architecture and is easy to install and use. Additionally Hudson is easily integrated into Netbeans and Redmine, and I use both tools regularly in development.
My motivation to dive into CI is easily explained. I just never felt it was necessary to add a continuous integration enviroment to my projects, since I had one or two simple bash scripts that did the job. In general this is rather annoying, because they mostly only run PHPUnit and have to be done using a cronjob or manually, without any real process of notification. Additionally you have no way to navigate the test-results, code-coverage and no history of the last builds. For projects like Doctrine 2 we have the additional requirement to support 4 different database platforms, i.e. 4 different PHPUnit configurations. Currently that is solved by me using a Bash script that iterates over the configuration file names and invokes PHPUnit.
There are already some awesome sources how to get Hudson and PHP working. I'll list them here:
All those guides are already awesome and I would recommend choosing one of those to install Hudson, I think i can't add anything new to those. I have used Sebastians Howto, however i also like the third one. David Luhmans guide adds lots of details that are important to get the different parts of a build process to work.
Now what these tutorials all do is that they use a bash command to execute the build process or specifiy an Ant Build file. However there is also a Phing Build process plugin for Hudson that allows to specify the build.xml targets to execute in the process. From the "Available Plugins" list you can choose the "Phing plugin".
After installation you have to configure the Phing install. The Phing Plugin Wiki Page shows how to do this. You have to go to "Manage Hudson" => "Configure System" and look for Phing. There you find the dialog to configure your phing installations.
In the context of choosing a build script for your project you can now choose "Phing" instead of Ant:
You can enter the targets to build, for example on my local Hudson instance I only execute "test" for Doctrine 2, since I am not interested in the building and deployment onto the PEAR channel at this development stage.
From inside Netbeans you can then start builds by pointing to the Hudson instance. See this tutorial by one of the Hudson + Netbeans Developers. You can then start all the builds from inside Netbeans and be notified of the success or failure.
Just this tuesday Facebook announced a ambitious project called “HipHop for PHP”, if you missed it general opinion says you have been coding PHP in a cave. As I write this review no code has been posted yet, but Facebook has made a great move to open source the project so we can all get our hands on it, use it and contribute to it. So since the code is not out there yet, this is literally a first impression article based on the presentation made by Facebook and various posts from core PHP developers who got a first look at the technology before the release.
What is it?
To be blunt, its a PHP to C++ code transformer (compiler). But that does not make justice to it, so let’s look deeper. To those of you that know PHP intimately you understand the process behind running PHP, it is thus:
PHP Code –interpreter–> OP CODE –Zend Engine–> Machine Language
Generally caching solutions store OP Code and reuse it instead of running the interpreter for every request. What HipHop does is completely different and surprised quite a few people who decided to guess what they were doing. On a general view this is the process (simplified):
PHP Code –parser–> C++ Code –g++–> Compiled binary
Historically PHP has always been executed on the Zend Engine, heart of PHP that has been around since PHP3, but what this solution does is that the Zend Engine has been recoded into the HipHop Runtime Engine, which instead of OP Code takes in C++ code that has been generated based on the original PHP code.
Why HipHop?
Its a well known fact that running code in C is faster then running PHP code, for obvious reasons, its very common for large applications in PHP to port part of its codebase to C and package it into an extension, such as Yahoo and even PHP projects like Doctrine have done so, performance of simple operations can increase in as much as hundreds percent, depending on load and usage.
This is the premise for Facebook’s project, they have long contributed to APC and PHP to get more performance out of their code, but with the increased load of billions of pages served it was not enough, they decided then to solve the problem. One of the options on the table was move on to another language all together, but this is where PHP shines, Facebook declared that PHP is simply a great solution because they can easily and rapidly get new programers up to status and developing in PHP due to its simplicity, that and the fact that their code base consists of million+ lines of code made them decide that this was not a solution, thus HipHop started.
How does it work?
The idea is that PHP code can be divided into “mundane” and “magic” code. Being mundane code basic operations that are directly mapped to C++ functions. This code if converted to C++ can be executed with much higher performance, while the magic code, which is the really complex code to be converted would run at equal or slightly lower speeds. This is the point that determines if you application can benefit from this, is it more mundane then magic?
If your answer is yes, then you may want to look into it. The converter does a lot of processing identifying dependencies, doing static analysis and other operations to get the basic code, it then has to take care of the problematic issue, Typing. PHP is a weakly typed language, meaning variables can juggle their types to and from various types. In the backend of this Zend Engine implements the ZVAL type, which basically stores anything. For the C++ code the new variables are typed so the parser needs to do all this in its Type Interface. The project’s lead Engineer, Haiting Zhao, stated that one of the solutions was to map ZVALs to the C++ Variant type whenever its impossible to determine a specific type (failed type inference), or when typecasting occurs in the process of the script. After all this analysis code is finally generated.
Thus this code is compiled against the HipHop Runtime, which as I said works like the Zend Engine and works now with specialized types instead of the abstract types in the Zend Engine. Binary in hand this can now be run straight from the command line, or interfacing with a web server as its compatible with the libevent library. Currently Facebook also wrote a very simple web server to interface with its compiled code replacing its Apache on calls to this code (as far as information goes, they proxy PHP traffic to this server and leave resources going through Apache).
The good and th
Truncated by Planet PHP, read more at the original (another 6982 bytes)
Several months ago Twitter added the list feature to it's public API. While debating some use cases for an event registration application I stumbled upon an interesting feature, which adds participants automatically to a Twitter list upon registration. This way registered and interested users can discover like-minded individuals and get in touch prior to any pre-social event activities. This post will show how this feature can be implemented by utilizing the Zend_Service_Twitter component, and how it then can be used in a Zend Framework based application.Implementing the common list featuresLooking at the three relevant parts of the Twitter list API some common features emerged and had to be supported to get the feature out of the door. These are namely the creation, deletion of new lists and the addition, removal of list members (i.e. event participants). Since the current Twitter component doesn't support these list operations out of the box it was time to put that develeoper hat on and get loose; which was actually a joy due to the elegance of the extended Zend_Service_Twitter component laying all the groundwork. <?php
require_once 'Zend/Service/Twitter.php';
require_once 'Zend/Service/Twitter/Exception.php';
class Recordshelf_Service_Twitter_List extends Zend_Service_Twitter
{
const LIST_MEMBER_LIMIT = 500;
const MAX_LIST_NAME_LENGTH = 25;
const MAX_LIST_DESCRIPTION_LENGTH = 100;
/**
* Initializes the service and adds the list to the method types
* of the parent service class.
*
* @param string $username The Twitter account name.
* @param string $password The Twitter account password.
* @see Zend_Service_Twitter::_methodTypes
*/
public function __construct($username = null, $password = null)
{
parent::__construct($username, $password);
$this->_methodTypes[] = 'list';
}
/**
* Creates a list associated to the current user.
*
* @param string $listname The listname to create.
* @param array $options The options to set whilst creating the list.
* Allows to set the list creation mode (public|private)
* and the list description.
* @return Zend_Rest_Client_Result
* @throws Zend_Service_Twitter_Exception
*/
public function create($listname, array $options = array())
{
$this->_init();
if ($this->_existsListAlready($listname)) {
$exceptionMessage = 'List with name %s exists already';
$exceptionMessage = sprintf($exceptionMessage, $listname);
throw new Zend_Service_Twitter_Exception($exceptionMessage);
}
$_options = array('name' => $this->_validListname($listname));
foreach ($options as $key => $value) {
switch (strtolower($key)) {
case 'mode':
$_options['mode'] = $this->_validMode($value);
break;
case 'description':
$_options['description'] = $this->_validDescription($value);
break;
default:
break;
}
}
$path = '/1/%s/lists.xml';
$path = sprintf($path, $this->getUsername());
$response = $this->_post($path, $_options);
return new Zend_Rest_Client_Result($response->getBody());
}
/**
* Deletes an owned list of the current user.
*
* @param string $listname The listname to delete.
* @return Zend_Rest_Client_Result
* @throws Zen
Truncated by Planet PHP, read more at the original (another 14678 bytes)
In my last
article, I wrote about how to get started with
Zend_Application, including some information about how to write
resource methods, as well as listing available resource plugins. What
happens when you need a re-usable resource for which there is no existing
plugin shipped? Why, write your own, of course!
All plugins in Zend Framework follow a common pattern. Basically, you group plugins under a common directory, with a common class prefix, and then notify the pluggable class of their location.
For this post, let's consider that you may want a resource plugin to do the following:
As I mentioned before, I got the book Zend Framework 1.8 Web Application Development for review. It took me a bit more time than I though to do this (one of the reasons will become clear soon) but here it finally comes.
I think it is a great book for somebody who is somewhat acquainted with Zend Framework and wants to get really good at working with it. It covers a lot of ground, so if you never worked with ZF before you might be a bit overwhelmed by the amount of stuff going on (then again, maybe I am underestimating you
), so you may want either skip some detail to return to it later when the need arises or have a run through a very basic tutorial for getting to know how the framework works before. The book itself has the basic startup section but I feel for a complete newbie it still might be a bit tough to keep up with the amount of the material in the book. That of course will come handy later when you got the basics figured out.
I personally am a big fan of learning by example and I think one line of code is often worth a hundred words, so I was really pleased that this book is based on building a complete application and comes with full application code to accompany it. The application is a storefront with an admin interface, so it covers most of the common tasks in a typical PHP application.
While it means that on the road there were certain decisions to be taken, and certain ways of doing things will be chosen over certain others, the author clearly identifies the decision points and explains the reasons – i.e. why certain things go to a model and not controller, why this extension point and not that one is used, etc. ZF has a very rich set of features, so there’s no single “right way” to do all things – but the book certainly shows you one of the ways to reach the complete and nicely structured application.
I actually took a bit of an experiment – as I was at the time building some ZF-based application, I decided to use the book as a first reference for any question that I needed with the app. I am pleased to report that the book indeed proved very helpful and I was able to find most of the advanced topics – like the use of ACLs, interactions between forms, views and decorators, modifying the behavior of the standard ZF classes, etc. – answered in the book and demonstrated in the code. The author successfully avoided the temptation to quote the manual extensively and instead picks up where the manual leaves off – i.e. how does one use stuff that the manual describes in practice.
The book also covers – albeit somewhat lightly – the topic that is neglected by so many other ZF books – namely testing. It shows how to setup the test environment and how to execute some basic application tests. Ideally, I would like the topic of tests to be much more prominent and featured as something parallel to development and not something you do after (though I know that’s how it rally happens many times
) – but I know there’s only so much you can put into one book
Summarily, I think it is a good book to have if you do or about to do serious ZF development.
Tagged: book, PHP, zend framework
As many have noticed Google Maps API does not include a setIndex() method on the marker. You can set the z-index when adding a marker to the map. But it is not possible to change this afterwards.
I didn’t find a good solution to the problem when searching and had to resort to my own, hacking away on Google Maps. As I was feeling really good about myself when I had it working really well I just remembered that Google Maps Javascript API V3 has been released in Google Labs… And of course there it was. The Marker class has a new method, setZIndex(zIndex:number).
Well, version 3 of the API is still only released by Google Labs which is “home to developer products that are still in their formative stages“. So for anyone not inclined to use version 3 just yet, I’ll write down how I did it here.
As I use JQuery in this particular project the example is also using JQuery. If used in production I suggest using try/catch wherever appropriate as the solution depends on a specific dom structure.
I have the below html which is the container for the Google map.
<div id="indexmap"></div>
The map is created as below (you’ll have to add the lat/lng variable values yourselves.
var map = new GMap2($('#indexamp'));
var point = new GLatLng(lat, lng);
map.setCenter(point, zoom);
This, as most know, creates the actual map. Then it is time to add the markers. In my case I have a list of locations with the latitude/longitude in the actual html. JQuery helps me loop over these locations and dynamically add markers in the correct spots. This html looks like below. Note how each definition list have an id no with “mm_” as prefix. (Never mind any objections you have on having many definition lists like this… Never mind that these coordinates are fiction…)
<dl id="mm_0">
<dt>...</dt>
<dd>
<span class="lat">61.333</span><span class="lng">31.1324</span>
Random text
</dd>
</dl>
<dl id="mm_1">
<dt>...</dt>
<dd>
<span class="lat">61.333</span><span class="lng">31.1324</span>
Random text
</dd>
</dl>
What I want is the markers to be highlighted with a different icon every time I hover over a definition list element (dl). However, both have the same coordinates and one of the markers will be hidden behind the other.
So to prepare we need to make sure the actual images in the Google generated map can be connected to these defintion list id:s. The Google map have many different layers on top of each other. One layer contain the foreground images, another the shadows, mouse map definitions and so on. Each of these layers (normal div elements) have their own z-index.
In these different layers the images used have their own z-index. However, the z-index for the marker foreground image is the same as for the transparent clickable marker image. This makes it possible to use the transparent image z-index to restore the foreground image z-index. This is important as not to confuse the user when he later click on a marker…
So let’s loop over these images and give them appropriate id values as well as put the markers on the map. (No - Google does not give them id’s). This is, stripped to the bare essentials, the complete code with some comments.
// Create the map
var map = new GMap2($('#indexamp'));
var point = new GLatLng(lat, lng);
map.setCenter(point, zoom);
// Loop over the definition lists picking up coordinates
var n = 0;
$('dl').each(function() {
var lat = parseFloat($('span.lat', this).text());
var lng = parseFloat($('span.lng', this).text());
var point = new GLatLng(lat, lng);
// Create the marker with custom images
var markerIcon = new GIcon(G_DEFAULT_ICON);
markerIcon.image = 'marker_default.png';
markerIcon.iconSize = new GSize(23, 30);
markerIcon.shadow = "marker_shadow.png";
markerIcon.shadowSize = new GSize(50, 30);
markerIcon.iconAnchor = new GPoint(11, 29);
markerIcon.infoWindowAnchor = new GPoint(11, 14);
var marker = new GMarker(point, {icon: markerIcon});
// Change the foreground image when hovering over a definition list
// Note that the actual id's have not been created yet.
var no = this.id.substring(3); // Exclude the prefix
$(this).hover(
function() {
marker.setImage('marker_selected.png');
// Bring this image to foreground
$('#mf_' + no)[0].style.zIndex = 1;
},
Truncated by Planet PHP, read more at the original (another 933 bytes)
As many have noticed Google Maps API does not include a setIndex() method on the marker. You can set the z-index when adding a marker to the map. But it is not possible to change this afterwards.
I didn’t find a good solution to the problem when searching and had to resort to my own, hacking away on Google Maps. As I was feeling really good about myself when I had it working really well I just remembered that Google Maps Javascript API V3 has been released in Google Labs… And of course there it was. The Marker class has a new method, setZIndex(zIndex:number).
Well, version 3 of the API is still only released by Google Labs which is “home to developer products that are still in their formative stages“. So for anyone not inclined to use version 3 just yet, I’ll write down how I did it here.
As I use JQuery in this particular project the example is also using JQuery. If used in production I suggest using try/catch wherever appropriate as the solution depends on a specific dom structure.
I have the below html which is the container for the Google map.
<div id="indexmap"></div>
The map is created as below (you’ll have to add the lat/lng variable values yourselves.
var map = new GMap2($('#indexamp'));
var point = new GLatLng(lat, lng);
map.setCenter(point, zoom);
This, as most know, creates the actual map. Then it is time to add the markers. In my case I have a list of locations with the latitude/longitude in the actual html. JQuery helps me loop over these locations and dynamically add markers in the correct spots. This html looks like below. Note how each definition list have an id no with “mm_” as prefix. (Never mind any objections you have on having many definition lists like this… Never mind that these coordinates are fiction…)
<dl id="mm_0">
<dt>...</dt>
<dd>
<span class="lat">61.333</span><span class="lng">31.1324</span>
Random text
</dd>
</dl>
<dl id="mm_1">
<dt>...</dt>
<dd>
<span class="lat">61.333</span><span class="lng">31.1324</span>
Random text
</dd>
</dl>
What I want is the markers to be highlighted with a different icon every time I hover over a definition list element (dl). However, both have the same coordinates and one of the markers will be hidden behind the other.
So to prepare we need to make sure the actual images in the Google generated map can be connected to these defintion list id:s. The Google map have many different layers on top of each other. One layer contain the foreground images, another the shadows, mouse map definitions and so on. Each of these layers (normal div elements) have their own z-index.
In these different layers the images used have their own z-index. However, the z-index for the marker foreground image is the same as for the transparent clickable marker image. This makes it possible to use the transparent image z-index to restore the foreground image z-index. This is important as not to confuse the user when he later click on a marker…
So let’s loop over these images and give them appropriate id values as well as put the markers on the map. (No - Google does not give them id’s). This is, stripped to the bare essentials, the complete code with some comments.
// Create the map
var map = new GMap2($('#indexamp'));
var point = new GLatLng(lat, lng);
map.setCenter(point, zoom);
// Loop over the definition lists picking up coordinates
var n = 0;
$('dl').each(function() {
var lat = parseFloat($('span.lat', this).text());
var lng = parseFloat($('span.lng', this).text());
var point = new GLatLng(lat, lng);
// Create the marker with custom images
var markerIcon = new GIcon(G_DEFAULT_ICON);
markerIcon.image = 'marker_default.png';
markerIcon.iconSize = new GSize(23, 30);
markerIcon.shadow = "marker_shadow.png";
markerIcon.shadowSize = new GSize(50, 30);
markerIcon.iconAnchor = new GPoint(11, 29);
markerIcon.infoWindowAnchor = new GPoint(11, 14);
var marker = new GMarker(point, {icon: markerIcon});
// Change the foreground image when hovering over a definition list
// Note that the actual id's have not been created yet.
var no = this.id.substring(3); // Exclude the prefix
$(this).hover(
function() {
marker.setImage('marker_selected.png');
// Bring this image to foreground
$('#mf_' + no)[0].style.zIndex = 1;
},
Truncated by Planet PHP, read more at the original (another 933 bytes)
WordPress is a great CMS, but implementing some features within your theme can require a little lateral thinking. The content for your page or post is usually output by the theme code using a single function call:
the_content(args);
But what if you need to split the content into two or more blocks? That might be necessary if your theme requires multiple columns or sections on the page. WordPress provides a get_the_content() function to return content as a PHP variable, but how do you determine where the divisions occur? There are a few solutions on the web, but most involve either:
h2 headings. Unfortunately, that requires the content author to know a little html and it’s not very versatile — you couldn’t allow two headings in one column.The WordPress <!--more--> tag may offer a better solution. It’s normally used to split a long article into two or more pages, but not all themes use that facility and it only works for WordPress posts by default (not pages). Using the <!--more--> tag offers several advantages:

To split your content, locate your theme folder (wp-content/themes), edit or create a functions.php file and add the following function within a <?php … ?> block:
// split content at the more tag and return an array
function split_content() {
global $more;
$more = true;
$content = preg_split('/<span id="more-\d+"><\/span>/i', get_the_content('more'));
for($c = 0, $csize = count($content); $c < $csize; $c++) {
$content[$c] = apply_filters('the_content', $content[$c]);
}
return $content;
}
You now need to locate the theme files which call the_content() within the WordPress loop. You should find it in single.php and page.php since these are used to display single posts and pages respectively. It may also be found in index.php, archive.php and search.php, however, these normally show more than one article so be careful how multiple content blocks are handled.
Once you’ve found the relevant code, comment out the_content() and call the split_content() function. It returns the content as an array; each element contains a single content block split at the <!--more--> tag, e.g. $content[0], $content[1], $content[2] … etc. The html can then be output as required, e.g.
Read the rest of this page »</p>');
// split content into array
$content = split_content();
// output first content sections in column1
echo '<div id="column1">', $content[0], '</div>';
// output remaining content sections in column2
echo '<div id="column2">', implode(array_shift($content)), '</div>';
?>
I hope you find it useful.
<script src="http://adscluster.aws.sitepoint.com/openx/adjs.sp.php?region=14&did=adz&adtype=horizontal" type="text/javascript">Related posts:
Recently, php|architect announced that they were extending the early bird pricing for the TEK-X conference being held this year in Chicago, IL. As someone who has been and will be going this year, this conference represnts a great opportunity for anyone who hasn’t gone to a PHP conference to attend one.
There are some good reasons that you should be attending.
Before I attended a conference, I had no idea what others were thinking with regards to PHP. The first big conference I attended was ZendCon and it was there that I discovered an entire world that I knew nothing about – the greater PHP community. But more than that, I discovered Really Smart People(tm) that I could interact with, be friends with, and who shared my passion for technology.
If you’ve put off attending a PHP conference, or simply are on the fence, you should seriously consider attending TEK-X this year. The conference itself has a great lineup, but I also know several people who are going to be there that are bright, talented and very enthusiastic about the PHP world.
That’s a great reason to go.
No, I’m not talking about a break-dance move that will magically give you extra PHP performance. I’m referring, rather, to a new open source project announced by Facebook. HipHop is a “source code transformer” designed to reduce CPU and memory usage by transforming your PHP code into C++ code.
To understand why this helps, you need to know a little bit about how PHP works. PHP is a scripting language, like Ruby, Python, and Perl. This is great for developer productivity, as there’s no need for the code to be compiled. The trade-off for this flexibility is in performance, with a scripting language requiring more CPU power and memory than a compiled language such as C++. What HipHop does is transform your PHP code into true C++ code, which can then be compiled into machine code. This is not the sort of thing you would do while developing, but when you are deploying your work you can compile it into the superior C++ code.
HipHop Performance Boosts:
The performance boosts that Facebook has seen is based on its own real-world experience, with over 90% of Facebook servers being converted to HipHop code in the last six months. The benefits released were split into two categories, the Web tier and API tier, and the benefits witnessed for each. The web tier reduced 50% of server load with the same amount of connections, and the API tier saw a 30% decrease, even with a twofold increase in traffic. The difference is explained by the web layer requiring more presentation logic and more abstract information (related information) than the API tier.
What’s the catch?
You’ll have to avoid a few PHP functions, such as eval() and create_function(). Because of the dynamic nature of these functions, the HipHop team was unable to transform them into C++ code; however, these functions are rarely used in most PHP applications in general.
Currently your HipHop code has to run through a custom-written HTTP server bundled with HipHop; however, using HipHop code with Apache is high on the development road map.
While HipHop will increase the performance of your PHP code, it’s not necessarily going to be the silver bullet for your performance woes; for example, if your bottleneck is in your database performance, HipHop will be unable to help you. There’s no need to worry about it making your code slower though, as the entire PHP runtime has been emulated in a way that even the most complicated code will run at the same speed as pure PHP code.
Where can I find it?
HipHop will be released very soon to the open source community, but in the meantime you can read the full write-up on the Facebook blog, or view the Facebook presentation.
What do you think?
I’m interested in doing some benchmarks and seeing how HipHop performs with the SitePoint codebase. Do you think you’ll be checking it out when it’s released?
Related posts:
By now probably everybody that is connected to PHP world knows about Facebook’s HipHop.
So here are my thoughts about it.
1. This is a very cool and exciting technology. There were multiple attempts to do this in various ways, and from what it looks, HipHop is the most successful and appealing. I know doing these things is not easy – I tried something like that myself somewhere back in 2006 but was unable to go past very basic examples (I also made a mistake of choosing C instead of C++ as target, which I now think was not a smart decision). And the progress and support for almost all of the PHP magic is definitely great. There still are unsupported areas, but mostly are dark corners into which not many people venture (or should venture, at least ![]()
2. I do not see it as a replacement for php.net code or Zend Engine. The mainstream of PHP development still happens in the community around php.net and I do not think it is going to change anytime soon. I also see the fact that HipHop engine basically re-implements all the extensions as a serious disadvantage, for which the solution should be sought, even though I completely understand the technical reasons for doing so. I do not know which kind of the solution but while for the company like Facebook it might be OK to “freeze” certain set of extensions and features and maybe catch up periodically, I think it is obvious how such model can be a problem for the wider adoption.
3. If we talk about broader adoption of this technology in a wider PHP world, there are some serious challenges to consider:
4. I also see certain danger potential in the success of this project. The danger
Truncated by Planet PHP, read more at the original (another 2948 bytes)
The first beta version of the PECL/Cairo extension has just been released. This version includes support for loading arbitrary fonts via Freetype, cloning matrices, and has a rather large set of bug fixes. If you've been using 0.1.0 for anything at all I'd really recommend an upgrade. Windows builds will appear soon over at perisama.net for all the major PHP variants courtesy of Elizabeth M. Smith. Many thanks to Mark Skilbeck for helping get this release working on Windows!

Well we all have read the announcement and chatted, twittered or whatever about it. I agree thats its cool this is being open sourced. I do fear however this means that there is no one less company looking after APC (mainly leaving just Yahoo then?). For now I think this is mainly interesting for "researchers" willing to work on improving the compatibility and more importantly the workflow around HipHop. I do not expect that anyone can really get a meaningful return on investment who makes this their business anytime soon (unless they can sell people on the hype), besides FB of course.
Overall I am not so impressed with the numbers. Even a 50% speed gain across the board .. what does that really mean? Lets say Facebook spends one third of the request (and I expect this to be even lower) on network and disk I/O, then this means that they managed a performance increase by a factor of 4 in the pure PHP processing parts. Note that I talked to some of the guys at the presentation and they said that the noted 50% speed up was not a result of switching the webserver (the binary generated by way of the C++ transformation includes a multi threaded webserver).
This is of course a nice speedup but wouldn't we expect at least a 2 fold .. or more increase if we could transform our PHP code into a C extension? This approach seems a lot more feasible for the masses. Like we could just drop in a ext/symfony or ext/ZF and thanks to autoloading magic our setup would continue to run unchanged. While it might not get that 4 fold speed up .. I would be willing to wager that it would get a 2-3 speed increase in the pure PHP processing.
So again I welcome any company open sourcing stuff that solved real world problems, especially if they are also willing to support the community in understanding their solution. But to me this solution will only matter for the ultra large companies where every single percent of saved CPU cycles matter. For the rest of us I think we need to rely on APC for a bit longer. But maybe with this transformator out there, other people will start working on the much more feasible approach of writing a PHP Code to C extension transformator.
I've just released Xdebug 2.1.0beta2 which features a few small bug fixes only. With this release the Windows 5.3/VC6 binaries also return.
One of the bug fixes is in a new feature that allows you to configure that the debugger should connect back to the IDE running on the machine that initiated the HTTP request. This feature, that originally was contributed by Lucas Nealan and Brian Shire of Facebook, allows more easy use of multiple IDEs (users) working on the same code base. In order to enable this, set xdebug.remote_connect_back to 1. See the documentation for more information.
Of course, this feature should only be enabled if nobody besides authorized developers can access the machine on which the xdebug.remote_connect_back callback feature has been enabled. Instead of enabling this setting, you can also support multiple developers through the proxy functionality that the DBGp protocol supports. For more information on that, see Debugging with multiple users.
You can find the full changelog here and get the latest version from the download page.
This past weekend, Belgium was buzzing PHP all the way. PHPBenelux organized the first annual international PHP conference in Belgium and it can be called a true success. Attendees and speakers coming from all parts of the world made this event a true international conference and I was truly happy to be a part of it, this time as member of the organization.Truncated by Planet PHP, read more at the original (another 10292 bytes)
By now, you might have heard the details of HipHop, Facebook’s PHP-to-C++ convertor that was announced yesterday. Like most of you, I’m eagerly awaiting the release of the code so that I can play with it and learn in detail what it can do and what it can’t. For now, Marco’s post seems to have the most technical information in it so far.
I’m with Sebastian on this one. Whether or not you think Facebook’s HipHop is relevant to you, I think they deserve credit for having shared their particular solution with the wider community. (They’ll get extra credit when they actually release some code
) After all, they’ve built on top of open-source in the first place; giving something back to the community is part and parcel of being a good member of the community.
How many of you earn your living from open-source, but have never contributed anything back?
But that isn’t really what I want to blog about today.
I’ve been following the chat on Twitter about HipHop, and I think all the nay sayers have been overlooking an important point. HipHop has the potential to reduce the amount of power consumed in running a website. And surely that can only be a good thing for all of us?
If you don’t run your own servers in a data centre (for example you use a virtual server, or host on a shared hosting solution), then perhaps you might not be aware that the power required by each server in a rack is often a major factor in the overall cost of running the servers. Whether or not you believe in climate change, energy prices are on the rise. Whether or not you believe in peak oil, oil and natural gas supply issues are forecast to push energy prices up further. Taking steps to get more work done per unit of power consumed has been the focus of hardware manufacturers for several years now. Isn’t it time it also was the focus of the software community too?
CPU usage is only one aspect of the total power consumed by a server in a rack, but in my experience people tend to add more servers to their solution primarily because they need more CPUs running their web servers to handle more traffic. A reduction in the number of CPUs required will translate into a reduction of the number of servers required … which means a reduction in the amount of energy being consumed.
How can that not be a good thing, if it can be achieved?
I know the answer will be that PHP apps are not CPU-bound, that they spend much of their time waiting for results from the database. That might be true if you’re measuring a PHP app from the point of view of elapsed time, but what if you’re measuring the PHP app in terms of CPU cycles consumed? Every single PHP script has to run on a CPU, and has to get to the point where it’s sat waiting for the database. If HipHop means that each PHP script uses less CPU to get to the same point, that has to be a step in the right direction.
Until we can play with HipHop ourselves, it’s impossible to say whether it saves enough CPU cycles to allow us to use less CPUs and therefore less servers. Remember, you’ve still got the overhead of your operating system and web server to factor into the equation. And then there’s the energy cost of compiling your code in the first place during development; for seldom-visited websites, HipHop may increase overall energy requirements.
But it sure is nice to hope, isn’t it?
Disclaimer: Since Facebook Inc. is a customer of thePHP.cc, I might be considered biased. For the purpose of this blog posting, consider me taking off my "thePHP.cc hat" and putting on my "PHP Community hat".
Yesterday Facebook Inc. announced "HipHop for PHP", a source code transformer that turns PHP 5.2 code (minus some features) into C++ code that can then be compiled with g++, for instance, to a regular binary.
If you are following some key PHP community members on Twitter, you may have learned that a couple of weeks ago Facebook invited a select few to Palo Alto, CA to give them a sneak peek at the technology. This is one of the reasons why this announcement was preceded with a lot of rumors. I am not really interested in rumors (or conspiracy theories, for that matter), so I will focus on the technology and its impact here.
I am very happy — both as a "programming language geek" as well as an Open Source enthusiast — that Facebook Inc. decided to open source their solution to their problem. Understanding this is crucial:
Now what was their problem?
Facebook has a large code base that would take a long time (one to two years by my estimation) to refactor or rewrite in either PHP or another programming language to achieve the performance improvement that Facebook was looking for. During this time of refactoring or rewriting, Facebook would not have been able to innovate.
In the past, Facebook tried to achieve performance improvements by contributing to PHP as well as APC. Many PHP deployments benefit from this contributions today, but for Facebook they were simply not enough.
From this perspective it makes a lot of sense to dramatically change the way that they deploy and execute their PHP code: without major modifications to their existing code base they are able to run it with a CPU usage reduced by 50%. This is a sustainable solution for them as it allows them to benefit from PHP's advantages such as shorter development cycles and lower training costs — while at the same time, thanks to HipHop, reducing their data center costs.
Stefan Priebsch (also with thePHP.cc) makes the point that you need to rethink your PHP development before you can dance to the HipHop beat:
"HipHop executes PHP code bypassing the Zend Engine, so there is no guarantee that a program will behave exactly alike on PHP and HipHop. More and better automated unit and integration tests will be required to allow you to compare the results on PHP and on HipHop, and determine whether deviations are to be interpreted as a bug, or can be tolerated."
I could not agree more: As there is a real build — including a real compilation — with HipHop, best practices such as coding standards and continuous integration will be even more important.
In conclusion, I would like to welcome "HipHop for PHP" to the PHP ecosystem. Yes, it is not a solution for a problem faced by 99.9% of the PHP deployments out there. But this does not make it less interesting in any way.

My apologies to Ron Burgundy for the title of the post, but I’m just a fan of the wisest man to ever live.
As Marco and Illia and countless others have said, unless you don’t work with PHP or were in a coma, Facebook released HipHop for PHP , it’s open source, it’s awesome, it makes you go fast. It’s not for you. You, being the average PHP developer, systems administrator, hacker. A lot is being made of how CPU load went down by 50% etc, that’s a great number and on the surface very hard to argue with, but to really understand it, you must understand the problem a lot better. Facebook didn’t decide to write HipHop and use it in production because they had all this money laying around and felt like paying 3 engineers to work on something. They looked at other existing alternatives, implemented them, and when they maxed them out, decided to switch. HipHop Does Not:
Yesterday, Facebook released HipHop for PHP, a compiler which makes native code from PHP sources (via C++ and gcc). They promise twice the speed with that approach, something which helps you a lot if you have 1000s of servers like Facebook. I won't bore you with the technical details and what it can and can not do as Ilia already summed that up pretty nicely.
We at Liip will certainly look into this technology once it's available and evaluate if it would makes sense for some of our customers and project. As HipHop is not a drop-in replacement for your existing setup this is something which has to be planned and tested carefully. You have to change the way your servers are setup and the way you develop and deploy. It even needs a server restart, if you change some code, so badmouths can now claim that PHP is even more becoming like Java :)
A high amount of Switzerland's most visited sites run on PHP (and some of them are even done by or with us) and maybe HipHop could be useful for some of them, after all the usual optimizations (like APC, memcached, etc) didn't help enough. But for most websites (and more so for small ones), PHP's speed isn't really the bottleneck, it's the database or some other external dependency. And for these cases HipHop isn't the holy grail. So before you change all your setup to fit into HipHop's requirements, do some decent evaluations, what really is the bottleneck in your application and decide accordingly.
There’s been lots and lots of discussion regarding the Facebook “Hyper PHP” release of HipHop for PHP. This new technology is an in-production converter for PHP that takes PHP code, converts it into C++ code, and creates a complete binary that can be run on a server natively. Facebook claims improvements of up to 50%, and their model represents a shift in thinking about scripting languages like PHP.
Ostensibly, lots of people are going to be thinking about how this will benefit them and their organizations. Here are some thoughts on who will benefit and who will not benefit.
Who benefits
There are lots of benefits for producers of large-scale web applications written in PHP. The ability to convert PHP code into something else that is more efficient without having to retrain their developers will ultimately reduce server load and deployment costs.
In particular, anyone running a web application with more than two servers will certainly benefit, as there is likely the traffic necessary for such a large web application. With a 50% improvement, one could conceivably use only one server; however, for redundancy reasons, it’s likely a good idea to maintain at least two web servers.
Others who benefit include those who distribute PHP code to clients directly. The ability to deploy an application on a web server in a compiled format ensures that reverse engineering is more difficult and protects intellectual property. There is considerable debate as to whether or not compiled or obfuscated code is worthwhile; given that the product designed by Facebook must be efficient, the idea of distributing a PHP-based binary makes a lot more sense.
Who doesn’t benefit
For all the benefits, there is a large group of PHP developers that won’t benefit: the average, every day developer. There are a vast number of websites that have a single server and not very much traffic; there are also lots of sites that run on shared hosts, or sites that have multiple sites on the same server. Since HipHop runs one web application at a time (with a built-in webserver), it’s impossible at the moment to run more than one website on a box. This is obviously less than optimal for most folks, and will limit adoption.
Also, early adopters of PHP 5.3 won’t be able to use HipHop straight away. Currently, it supports PHP 5.2 (as most of Facebook is written in PHP 5.2), though there are plans to modify HipHop to support PHP 5.3.
Bottom Line
HipHop is still pretty awesome, and will certainly change the way PHP applications are developed. There are great opportunities here, and Facebook has certainly developed a revolutionary system. What will ultimately happen remains to be seen; regardless, it should be an exciting year for PHP development overall.
By now, unless you’re living under several hundred metres of rock, you’ve probably heard that Facebook has released HipHop for PHP, a tool that compiles PHP into C++ with some interesting claims of speed improvement. The thickness of unawareness-inducing rock may have to be lower to know that php|a and BP have announced our full support for the project with a number of initiatives that we’re going to roll out over the next few months.
I have known about this project for a little while—Facebook was kind enough to invite me, along with a few other community members, to their office for a demo a few weeks ago. They gave me a copy of HipHop to try out, and I have been playing with it for the last few days.
What it isFirst, a few random notes on how HipHop works. Haiping has done a great job of providing in-depth coverage in his post on the FB blog, so here are the CliffNotes:
HipHop has the potential to be an incredibly disruptive product in the PHP landscape. If your company runs a PHP application that requires more than two servers (you’ll want two just for redundancy), you have no reason not to explore using HipHop. If Facebook’s claim of a 50% reduction in CPU usage means you could, potentially, get rid of 1/2 of your PHP machines with a minimum of investment. You don’t need to be Facebook to draw a huge advantage from this technology. Perhaps this one-to-one reduction is not apt, but even 40% or 30%—much more realistic—is major, and a truckload and a half more than any other existing PHP-related product can offer at this point.
Clearly, this argument can be flipped around: you have every incentive to make sure that your application runs with HipHop—which could give Facebook a unique opportunity to exert significant control over the way PHP evolves.
You might, at this point, think that this is not the first attempt at a PHP compiler—in fact, there are other compilers commercially available. Heck, even I wrote my own experimental compiler several years ago (in fact, I had a discussion about my experience with some of the Facebook team members about this a while back, presumably while they were researching HipHop)—and that ultimately it won’t make a difference.
But HipHop is neither experimental nor unproven, and it’s free; it is used, in production, by the second-largest site on the Internet—and make no mistake about it, there is no smoke-in-your-eyes (not to mention other body parts) sleight of hand on Facebook’s behalf; their site is written in PHP by PHP developers, without the help of large numbers of custom extensions. In fact, their goal is precisely to allow their developers to continue using PHP—which they consider the nimblest web development environment—without compromising their ability to grow at the current pace in a financially responsible way.
If you think about it, that makes a lot of sense from a business perspective: PHP is simple, flexible and easy; with HipHop as a drop-in
Truncated by Planet PHP, read more at the original (another 826 bytes)
After many days of speculations all around the web about Facebook’s rewrite of PHP, today Haiping Zhao from the Facebook team has announced “HipHop for PHP”. The basic idea of HipHop for PHP is that it turns the code you write in PHP into C++ which then can be turned into machine code.
Even though there are others idea that have tried accomplishing the same goal as HipHop for PHP, I believe it is quite safe to assume that Facebook has a large enough user-base to produce code that is solid enough to run and can run well.
The announcement has been made on the Facebook blog earlier today, and tonight there is going to be the video tech talk that everybody can watch:
This evening we’re hosting a small group of developers to dive deeper into HipHop for PHP and will be streaming this tech talk live. Check back here around 7:30pm Pacific time if you’d like to watch.
A few questions come to mind even though we haven’t seen the code just yet. My main concern though is the one of buffer overflows and the security implications of turning PHP code into C++. As they say on the blog, it took nearly 18 months before having a relatively stable version and 3 developers. This is a very short lapse of time to develop a solution used by so many.
Another interest of mine related to this release is how does it compete with the likes of phc or roadsend php. If it does at all.
However I have noticed on their blog that Facebook has also developed HPHPi which seems to let you use HipHop but without having to actually compile your code before running it (The concept seems a bit like APC’s stat on and off switch from the few lines of description), which seems like a quite interesting idea for the development stages.
It's been a long time coming, but I finally have some working CalDAV code. The server has been tested with iCal 3.0 and 4.0 (Leopard and Snow leopard), Sunbird 1.0 pre-release and Evolution.
My main goal is to create a general-purpose CalDAV library, rather than a consumer-ready server app. I'm hoping people will be able to use this library to enable CalDAV functionality in their existing applications.
If you're interested in hacking around or testing, you'll have to grab a copy from subversion. Full installation instructions are available. Because of the alpha-stability nature of the code data-loss can occur, so beware!
It seems that I don’t blog much unless IDE’s are concerned; there is a good reason for this: IDEs are an integral part of my development process and when they suck, development sucks.
The story so far:This is the continuation of that story. In the last installment Netbeans 6.7 was a nightly build, it had gotten it’s OSX look and feel, and it was starting to get it’s remote debugging up and running.
Now, 6.8 has been out for almost 2 months, and things are really starting to gather steam. With the death of ZDE5.5 finally a reality, and PHP 5.3 code starting to become part of my work-day, I finally jumped 100% to Netbeans.
And let me tell you, Netbeans 6.8 is nothing short of amazing. Debugging with xdebug is now almost as easy as ZDE, it works instantly on 90% of my remote machines, but I have 1 cluster for which Netbeans simply *cannot* find the local source file, making it impossible to debug.
Watches, breakpoints (though, I haven’t figured out conditional breakpoints, if they are there), callstack and local variables work as you would expect (though watches/variables sometimes refuse to populate larger vars, I think this is xdebug config related). In addition, Netbeans supports arbitrary breakpoint groupings; these can be enabled and disabled as a group — very neat.
In addition, it has path mapping to help with remote/local file correlation; so it can find the local file to show the source during debugging — this stops the problem ZDE has where two files have the same basename() and it’s unable to choose the correct one.
However, a fully functional debugger is a minimum requirement. Netbeans 6.8 also has great support for PHP 5.3 (though it has some syntax support bugs), again another minimum.
So where does Netbeans shine? The single biggest answer to that, is PHPUnit support. Netbeans lets you specify your test folder, and abstracts it out of the project, so your tests are separated visually; this is a great minor addition. In addition, Netbeans can generate unit tests (this utilizes phpunit’s built-in functionality), and has a great UI for running tests.
You can run a single unit test by simply right clicking on the test and choosing Run, or you can test a whole project by right clicking on the project and choosing Test. Doing this will bring up the Test Results pane:
As you can see, it shows the number of tests, the test suite, and it’s test status; this can then be expanded to show individual test methods.
Further to this, you can have Netbeans capture code coverage information, if you have the xdebug extension installed locally. This then manifests visually in two ways; the first, is a summary:
The second, more impressive/useful way, is visually within each file:
You will also notice that this adds a set of buttons below the code, which can be used to run the test for just the current file (based on the typical phpunit file/test naming structure, I assume) and to re-run the entire test suite.
To me, this integration is phenomenal, and is changing the way I work. This is a great example of an IDE conforming to your workflow, and proving new ways to do things; rather than fighting you and requiring you to change to it’s needs and ideals.
Other things of note, Netbeans 6.8 has Symfony project integration, and 6.9 is including Zend Framework integration, if those things appeal to you — I have yet to play with either, so can’t comment on their usefulness.
I can, without doubt, confidently say, that despite the few bugs, and some still immature minor things, Netbeans is my recommendation for an IDE.
- Davey
Few days back I made some code commit (code check-in) to WINCACHE SVN depot on PECL. I committed the test infrastructure to test WINCACHE. The entire test code can be see inside the folder at [svn.php.net] . Let me explain how it works. In order to make it work first of all the binaries has to be compiled. This is the binary which is responsible for driving the test suite, I call it as a kind of test driver. I have already committed the the Visual Studio solution file which is at location [svn.php.net] . However the solution file is meant for Visual Studio 2008 and may not be compatible with previous versions of Visual Studio. If you are using an old version of Visual Studio you may need to create a new solution/project file (simply chose ‘WIN32 Console Application’ while creating the solution/project file). After creating a new solution just add the C++ source/header files present at [svn.php.net] to the solution/project. Compile it in Visual Studio and the binaries should be made. This builds one executable which is named ‘test_wincache.exe’. You can either compile Release/Debug build but I always prefer Release build. Here is how you can use the binaries to test WINCACHE.
What the code does?
Truncated by Planet PHP, read more at the original (another 1752 bytes)
Today I have released phpUnderControl version 0.5.1. It's a bug fix release that closes several issues open since a long time. First of all I would like to thank Sebastian Marek who was the main contributor to this releases, so a big thankyou to you.
Truncated by Planet PHP, read more at the original (another 2141 bytes)
Whilst everyone else was over at PHP Benelux 10 (which sounded like a great conference according to the Twitter feedback!), I was up in Morecambe, at the Technique|NorthWest training event organised by Northwest Vision and Media and run by The White Room. A huge thanks to Paul Collins for inviting me up at the last minute to run the PHP workshop on the Saturday, and I’d love to be involved in further events like this.
I had a great time at the event, and I was delighted to see how the North West of England is trying to build and support a digital economy, instead of simply leaving it to chance. If only South Wales had such an initiative!
Perhaps the most interesting thing I took from the weekend was the large disconnect between the people who attended and many of my friends on Twitter. If you listen to the Twitterarti, you’d think that Adobe Flash is a technology that has run its course and is now in terminal decline (mostly because the iPhone and iPad do not support it, plus Adobe not seen as exactly a bastion of innovation these days). And yet, by far the most popular workshop at Technique|NorthWest was the Flash workshop. To these people, Flash is not only still relevant, but in their industry it is still the only real option for delivering online advertising campaigns.
Food for thought.
PS: I also took some photos of Morecambe before the Saturday workshops started.
Am kommenden Donnerstag, den 04.02.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in München statt (Mannhardtstraße 6, S-Bahn Isartor).
| time | room | topic | speaker |
|---|---|---|---|
| 10:45-11:30 | Janson | Promoting Open Source Methods at a Large Company | Brooks Davis |
| 13:15-13:45 | AY | Packaging Java Software for Debian | Thomas Koch |
| 13:40-13:55 | Ferrer | CiviCRM: Common goals of FOSS and Not For Profit Organisations | Xavier DUTOIT |
| 14:00-14:45 | H.1308 | The Maemo Community Council: a case-study in governance | Dave Neary |
| 14:00-15:30 | Guillissen | LPI exam session 1 | Klaus Behrla |
| 14:00-14:45 | Janson | What is my system doing - Full System Observability with SystemTap | Mark Wielaard |
| 14:30-15:00 | H.2213 | Building Federated Social Networks on XMPP | Tuomas Koski, Simon Tennant |
| 15:00-15:45 | Janson | Ganglia: 10 years of monitoring clusters and grids | Bernard Li |
| 15:00-15:30 | H.2213 | XMPP and the Social Web | Alard Weisscher, Laurent Eschenauer |
| 15:30-16:00 | H.2213 | PubSub Gone Wild: Info Sharing at Mediamatic | Ralph Meijer |
| 16:00-17:30 | Guillissen | LPI exam session 2 | Klaus Behrla |
| 16:00-16:15 | Ferrer | SIP Communicator: Skype-like conf calls with SIP Communicator | Emil Ivov |
| 16:20-16:35 | Ferrer | Kamailio (OpenSER) 3.0.0: redefinition of SIP server | Daniel-Constantin Mierla |
| 16:40-16:55 | Ferrer | asterisk: An introduction to Asterisk Development | Mark Michelson |
| 17:00-17:15 | Ferrer | csync: Roaming Home Directories | Andreas Schneider |
| 17:30-18:00 | H.2213 | Jingle Nodes: An Open Alternative to Skype | Tiago Camargo |
| 18:00-18:30 | H.2213 | Multi-User Jingle: Voice and Video Conferencing with XMPP | Dafydd Harries, Sjoerd Simons |
| 18:15-19:00 | H.1302 | Spacewalk: Linux Systems Lifecycle Management | Marcus Moeller, Sandro Mathys |
| 09:15-10:00 | H.1302 | Linux distribution for the cloud | Peter Eisentraut |
| 10:00-10:45 | Janson | RepRap - Manufacturing for the Masses | Adrian Bowyer |
| 10:30-12:00 | Guillissen | LPI exam session 3 | Klaus Behrla |
| 11:00-11:45 | AW1.120 | My life with HBase | Lars George |
| 11:00-11:45 | Janson | Tor: Building, Growing, and Extending Online Anonymity | Andrew Lewman |
| 12:15-13:00 | H.1302 | Cross distro packaging with (top)git | Thomas Koch |
| 12:15-13:00 | H.1308 | Shared libraries in Debian | Sune Vuorela |
| 13:00-14:30 | Guillissen | LPI exam session 4 | Klaus Behrla |
| 13:15-14:00 | AW1.120 | CouchDB, a database designed for the web and more | Benoit Chesneau |
| 14:00-14:45 | Janson | Large scale data analysis made easy - Apache Hadoop | Isabel Drost |
| 15:00-16:30 | Guillissen | LPI exam session 5 | Klaus Behrla |
| 15:30-16:15 | H.1308 | Continuous Packaging with Project-Builder.org | Bruno Cornec |
| 15:30-16:15 | AW1.120 | Comparing the MapReduce way in CouchDB with the SQL way in a RDBMS | Stéphane Combaudon |
| 16:15-16:45 | AW1.120 | Designing a scalable content management system on NoSQL technologies | Evert Arckens |
| 16:15-17:00 | H.1308 | Debian Secrets: power tools for power users | Wouter Verhelst |
The January issue of PHP|Architect just got published, and I'm in it!
I've written an apparent 5-page article about SabreDAV. The process was a lot of fun. It's definitely quite different from blogging, where quick and dirty is the rule rather than the exception. I hope I get the chance to do this again (all provided if there's another subject I feel knowledgeable enough in).
So if you get a hold of a copy, I would be very interested in your feedback! The magazine is in PDF form these days, so subscribing and downloading is quick and easy =).
Last year, I ran a series of polls via Twitter to try and learn a bit more about your plans to move to PHP 5.3, and whether or not you actually followed through. A huge thank you to everyone who voted!
I’m not talking at any conferences this year, so I’ve published the planned PHP 5.3 adoption talk online for anyone who’s interested in what the PHP user community told us via these polls. As well as the raw data, I’ve included an analysis of what the data might mean, and some talking points about what the PHP Group might want to do differently when PHP 6 (or PHP 5.4 if there is one) is released.
You can find the talk online at Slideshare, along with all of my older talks. I hope you find it useful and informative.
Php 5 3 Adoption View more presentations from stuartherbert.
Late last month, I received some bad news about web2project...
It turns out that web2project was vulnerable to a handful of select Cross Site Scripting (XSS: definition) vulnerabilities. While the attack vector was pretty specific to being an already authenticated user, it had the potential to be a major problem in a poorly configured system.
On the positive side, I say "was" because within 10 days of being notified of the problem - and the same day the vulnerability became public - we had a patched release out the door and available to users. We've spent the past month since encouraging them to upgrade. Of course, we further benefit from the fact that although the vulnerability does affect us, we're not named in the report.
On the negative side, it did take us 10 days to close the vulnerability. The patch itself was available a few days earlier via Subversion but it might not have been enough. Further, we didn't explicitly notify our users of a need to upgrade but since it was rolled with a handful of other major fixes, it appears that many people have upgraded already. Once again, we benefit from the very specific attack vector.
To make this process easier and faster in the future, as of v1.3, we can already detect if upgrades have been uploaded but not applied. For an upcoming release, we're implementing a Drupal/WordPress-style means of notifying existing administrators thatan upgrade is available. In the meantime, watch this space or web2project's page on Sourceforge.
HTTP/1.1 200 OK
Date: Fri, 29 Jan 2010 15:30:34 GMT
Server: Apache
X-Powered-By: PHP/5.2.12-pl0-gentoo
Set-Cookie: WCSESSID=xxxxxxxxxxxxxxxxxxxxxxxxxxxx; expires=Sun, 28-Feb-2010 15:30:34 GMT; path=/
Content-Encoding: gzip
Vary: Accept-Encoding
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html PUBLIC "-//W3C//DTD html 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Ramblings of a web guy</title>
.
.
So, all those lines before the html starts have to come first. HTTP headers are where things like cookies and redirection occur. When a PHP script starts to send html out to the browser, the headers are stopped and the body begins. When your code tries to set a cookie after this has started, you get the "headers already sent" error message.
LinuxTag is the most important place for Linux and open source software in Europe. Last year, LinuxTag had over ten thousand attendees, and over 300 speakers. This year, the 16th LinuxTag will be June 9-12, 2010 at the Berlin Fairgrounds in Germany.
LinuxTag seeks exciting and suitable proposals for presentations in the conference tracks. The Call for Papers ends today.
I am proud to be a member of the LinuxTag Program Committee. Although a lot of proposals have already been submitted, there are some topics missing that I’d personally like to see covered. So, if you’re up for a last minute submission, get your inspiration from the following list:
I can’t promise that your talk will be accepted if it covered one of the above topics. The review process is of course a joint effort of the whole Program Committee. Anyway, it’s definitely worth a try. Of course, any other topic I did not think of is also highly welcome.
Go here to submit your LinuxTag proposal.
According to a recent post from the Google Blog, Unicode nearing 50% uptake on the web. A rather steep graph as well:
This is pretty good news. I've had the 'pleasure' of working with a number of integration project where the 3rd party was still using iso-8859-1 (aka latin-1). Usually when this is the case, its not by choice but because of their software's default settings (Browsers, MySQL, etc.). I for one hope non-unicode charsets will soon be a thing of the past.
One other note in the post was about ligatures, such as fi and the dutch ij. If this is the first time you heard about these, you might be surprised to see that you can (likely) only copy-paste ij as a whole, and not just the i or j. It's one unicode character, not two. It just made me wonder: what kind of software would generate these, and more importantly why?
This entry isn’t about PHP.
It’s about where those of us who develop for a living, PHP or otherwise, see ourselves in the future.
From time to time I do some soul searching and think about where I’ve been and where I’m going. With a tough few months in the books, I wanted to take some time and figure out my next moves, and where I’m heading.
Soul searching isn’t easy, because it requires us to examine ourselves, and in particular, our mistakes, to decide whether or not what we’re doing is appropriate and good. Soul searching means reexamining every hard decision that we made and thinking about whether or not we decided rightly. And it means taking a hard look at where we said we were going, and whether or not we actually got there.
I’ll be doing some soul searching this weekend as I think about the direction I want to go. And then I’m going to employ my resources to get there.
CairoForPHP is an application that demonstrates several functions of the Cairo implementation for PHP. It uses a technique with which, from the same source, it can run both as a desktop application with PHP-GTK and as a web application in a webserver, thus demonstrating how PHP-GTK can be used as "just one" method of output and integrated into multi-platform, multi-environment applications.
$this->db->select() accepts an optional second parameter. If you set it to FALSE, CodeIgniter will not try to protect your field or table names with backticks. This is useful if you need a compound select statement.
I’ve started playing with Ruby recently, and one of the things that got my attention in Ruby were iterators. They are different inside from regular loops but work in a similar way, and looks like people (at least ones that write tutorials and code examples
) like to use them. For example, you can have:
arr = {"one" => 1, "two" => 2, "three" => 3}
arr.each do |key, val|
print "#{key}: is #{val}\n"
end
which iterates over a Ruby hash and prints:
three: is 3 two: is 2 one: is 1
So it got me thinking – suppose I wanted to do something like this in PHP (suppose I don’t like regular loop-y iterators for some weird reason). Naturally, I wouldn’t get it in the same concise form as Ruby does, since I can’t change the syntax. But I could get the essence. Let’s try it. First, the main iterator:
class RubyIterator {
protected $_body;
public function __construct($body) {
if(!is_callable($body)) {
throw new Exception("Iterator body should be a callable");
}
$this->_body = $body;
}
public function yield()
{
$args = func_get_args();
call_user_func_array($this->_body, $args);
}
}
Next, less try to make some class that uses it:
class RubyArray {
protected $_arr;
public function __construct(array $a)
{
$this->_arr = $a;
}
public function each($body) {
$iter = new RubyIterator($body);
foreach($this->_arr as $k => $v) {
$iter->yield($k, $v);
}
}
}
and then:
/*
arr = {"one" => 1, "two" => 2, "three" => 3}
arr.each do |key, val|
print "#{key}: is #{val}\n"
end
*/
$arr = new "/>Truncated by Planet PHP, read more at the original (another 6795 bytes)
[Updated to add IRC and Google Groups links]
I don't know if it's just me, or whether everyone in software development finds issue tracking software frustrating and/or broken in some way. They're all either way too complicated to set up, configure or use (the Bugzilla's or the Jira's), or have annoying "features" (such as Trac's you-lose-your-edits-if-someone-else-changed-something).
We've been using Trac at Message Systems for several years now and have been enjoying its pragmatic approach of keeping the interface simple but expressive; just enough structure to be helpful but not too much that it intrudes. We've added/modified a couple of plug-ins to it to help track time and draw some graphs, but it has otherwise served us well.
However, we've got a couple of projects that have started to converge and overlap and it's frustrating to visit the two different portals to interact and stay on top of things. As we scale up our development teams even further (we continue to have bigger and bigger plans!) this will prove to be more widely frustrating.
Enter mtrack; on one hand it's a clone of many of Trac's features (possible due to their pragmatic BSD license), but on the other it has some refinements in terms of its workflow. What's important to me is that it is built to work with multiple code repositories and allows breaking out information on a per project basis. It also tries hard to avoid losing your wiki or ticket edits if someone else updates things while you're working.
To PEAR or not to PEAR — PEAR2 is taking a while and I sometimes think that everyone associated with PEAR is busy elsewhere. Since a little competition never hurt, I'm especially excited about these recent developments.
With the release of Pirum, I'm really excited to see two public PEAR channels that aim to make PEAR a standard to deploy and manage your applications and libraries. One is PEARhub and the other is PEAR Farm. I think I'm gonna stick with PEAR Farm for a while, so this blog entry focuses on things I noticed when I first played with it.
PEAR vs PEAR FarmA lot of people mistake these new channels for the wrong thing. They think that this will eventually replace PEAR. I don't think it will — ever.
While I really welcome the idea that people push PEAR's channel for a standard to distribute apps and libraries (PHPUnit, ezComponents, Zend Framework, Symfony, etc.), it's also very obvious that these open channels will never be the same.
For an idea of what I mean — take a look at open code repositories around the web and especially when it comes to PHP, it's very obvious that while there's a lot of code, most of it is utter crap. (There I said it!)
And no one wants to rely on it when reliability is an objective.
The PEAR Coding Standards were not invented because it's so great to tell people how to write code. But a lot of people need this guidance. While they have a lot of ideas about how to implement a feature or a cool algorithm, their passion does not extend to test coverage or even little documentation. And that's where these sometimes frowned upon coding standards come in handy because they ensure that the code in PEAR is maintainable — which is really just the tip of the ice berg for professional software engineers and I'll save the rest for another blog post.
Let's get to itRegardless of the fact that there always only few steps, PEAR setups tend to not work for or look complicated to a lot of people. Here are a few tips on how to get started. We'll assume pear itself is installed (apt-get install php-pear).
Instead of what is written in the FAQ - suggested steps to get started. ;-)
pear channel-discover pearfarm.pearfarm.orgpear install pearfarm.pearfarm.org/pearfarm-betaThe package.xml is a configuration file for the PEAR package. It's pretty long, and since XML is so verbose, it's a turn off to many. PEAR Farm suggests to create a spec instead, so it can create a package.xml for you. This is pretty convenient, but there are also a few gotchas.
pearfarm init (inside the code repo)If you're doing it for the first time, it will issue a warning about a configuration file being created — ignore it and move on.
Continue by editing the .spec file with description, summary, maintainer and whatever else is a suggested edit inside it.
Then, feel free create a package.xml:
pearfarm buildThis will leave you with a package.xml file in the same directory. Mission accomplished!
These are a few things you should edit before you pearfarm push:
If you use git and happen to have a .gitignore, pearfarm will add .gitignore to the package.xml as well.
pearfarm adds a baseinstalldir attribute to the top most entity. Assuming your package is Foo_Bar and you have Foo/Bar.php in your repository, it would install into /usr/share/php/Foo_Bar/Foo/Bar.php, instead of Foo/Bar.php. I'd suggest you remove it and instead namespace in the package name right away — YourName_FooBar.
Does it work? Always pear package-validate before you push!
Does it install correctly? Feel free to pear install Package-x.y.z.tgz and check if the files installed ok (pear list-files pearfarm.pearfarm.org/Package)
A package.xml can have files with different roles, while the standard is php, there's also doc (for documentation) and test for tests. When the package.xml is generated from the .spec, all files get php by default, that's why I'd go through the list in to double-check that all files have appropriate roles set.
Another thing to take care of (imho), would be — somet
Truncated by Planet PHP, read more at the original (another 585 bytes)
If you came here for advance information or predictions about Apple’s much discussed table, I am afraid I have neither. In fact, I am fairly sure that what I am about to tell you is unlikely to happen, so, there you are.
On the other hand, I have certain hopes for the product and one, in particular, is something that I haven’t seen anyone in the media discuss: could the Jesus Tablet revolutionize the way we buy and use wireless data?
Everyone agrees with the fact that the tablet will have some kind of 3G or 4G wireless cellular connectivity, but they all seem to take for granted that network access will be provisioned the same way it is done with the iPhone.
The tablet, however, is not a phone—quite the contrary—and, therefore, it’s perhaps a good idea to ask whether Apple may not be looking for ways to create an even more captive market.
To understand what the implications might be, one only needs look at the Kindle. It hasn’t occurred to me until recently that the killer feature of Amazon’s reader is not the e-ink screen, or the vast selection of books—it’s the fact that it makes accessing a cellular network completely seamless: there are no contracts for you to sign (except the one with Amazon), no data fees to pay (except the ones you pay to Amazon as part of your purchases) and—most importantly—no roaming fees to deal with.
In other words, even though it doesn’t look like one, the Kindle is a cell phone that works the world over through a single provider that is not your cellco. In fact, looking at Amazon’s recent announcement of its revised royalty scheme for the Kindle, you can see that they are planning to charge $0.15/MiB for data transfer, regardless of where the user is in the world. To put things in perspective, the lowest price that is available to me while roaming in the States is $1/MiB—and that’s if I pay a $10 monthly fee to get it reduced from $6/MiB, if I sign a long term agreement and if I agree to pay on top of my regular voice and data plan.
Compare this experience with the absolute hell that dealing with your current cellular company is, and you will see that there is an opportunity, for a sophisticated player, to create a wave of unprecedented disruption in the wireless market.
If Apple were to sell the tablet and make a data plan available through Apple, a number of really important things would happen:
The disruption of this approach would be nearly total: because customers purchase service from Apple, the underlying network provider becomes little more than a curiosity, and it’s not unthinkable for our friends from Cupertino to eventually set up their own global wireless network.
Of course, I have no illusion that it’s highly unlikely for any of this to happen—I mean, the wireless companies cannot possibly be so shortsighted to let this happen, right?
Right?
Image credit: Tablets by swimboy1
<script src="http://static.zemanta.com/readside/loader.js" type="text/javascript">
The new release of WinCache Extension for PHP - version 1.0.1 – is available for download. This is a servicing release that has fixes for bugs reported in v1.0. In particular the following fixes and changes have been made in this release:
The new release is available for download from the extension’s home page at: [www.iis.net] . The source code for the extension is available on PHP PECL page here: [pecl.php.net] . The documenation for the extension can be found at [www.php.net] .
I recently asked user of WINCACHE to give feedback on soon-to-be-released bits of WINCACHE 1.0.1. We got mails from lot of people who came forward to help us with the testing. I would like to thank all of you there who helped us in testing the critical fix. I am still getting request for new binaries which is overwhelming. Based on the user’s feedback (which was all positive) we decided to release WINCACHE 1.0.1 today. I would advise everybody using WINCACHE to switch to the new stable version even if you are not seeing any problem with current builds. This version has got a critical fix and is good enough reason to upgrade to the newer bits.
Upgrade is supported from Microsoft Web Platform Installer if one is using PHP5.2. The new binaries can be downloaded from link at [sourceforge.net] . The main download link contains the WINCACHE 1.0.1 binaries for PHP 5.2. Binaries for PHP 5.3 version can be found at [sourceforge.net] . Right now we are releasing only non-thread-safe bits of WINCACHE only. Anyone interested in thread safe version will be required to build the extension from downloading the sources from [pecl.php.net] .
The release contains below fixes:
Thanks for the patient reading and till we meet again ‘Good Bye’.
Don.
Finally found some footage of the Inner Join / Outer Join database song Craig Campbell and I created for the Schematic Tech Summit in September 2008! (The contribution was: lyrics about 50/50 and 100% of music is original and written by Craig.)
Link to the footage: Inner Join / Outer Join
And the lyrics:
Craig: “Hey Maggie, I think this song’s going to be in A major…”
Maggie “Major?! but I just met’er!”
inner join outer join
do you really know the difference?
inner join outer join
a null could ruin your existence
it doesn’t matter which you choose
whichever database you use
oracle, mysql [and postgres!]
i’ve got a story i should tell
about inner and outer joins
CHORUS
do those phrases sound like gibberish
like bubbles from a talking fish?
or german or italian
or japanese or french or dutch
or maybe klingon?
CHORUS
focus on integrity
and your database will feel pretty
do you want an epic fail
or do you want your app to scale
and reach to Jupiter
where aliens can run queries
to make sure you have your foreign keys
have your ON DELETE CASCADE
relations come to aid!
your world is normalized
CHORUS x 2
In the next few months, I will be speaking at the following conferences:
PHPBenelux Conference 2010 is the first annual conference by the PHPBenelux usergroup. It is organized in Antwerp on Saturday January 30th. I will be giving a keynote titled "The PHP Universe".
PHP UK Conference is PHP London's fifth annual conference and held on Friday February 26th at the Business Design Centre. I will be talking on PHP on the D-BUS.
ConFoo (formerly PHP Québec) is the first edition of the Confoo.ca Conference. From March 10th to 12th 2010, international experts in Java, .Net, PHP, Python and Ruby will present solutions for developers and project managers the Hilton Bonaventure Hotel, located in downtown Montréal. I will be talking on Advanced Date/Time handling with PHP.
Hope to see you there!
Recently, I realized that despite talking about Karl Fogel's book - "Producing Open Source Software" - numerous times over the past year[1][2][3], I've never written a review of it. So without further ado, here we go.
I originally picked up my copy in mid-2007. It took me a couple months to get to it, but once I did, it rocked my professional world. To be clear, Karl Fogel is an early (founding?) member of the Subversion Version Control System.
Karl starts off talking about the beginning an Open Source project and the things - both community and technical - that are required to get things rolling. If you're participated in an even moderately active/successful open source project, none of this will be surprising, but having all of it enumerated clearly never hurts. If you go with something like SourceForge, Google Code, Launchpad, or Microsoft's CodePlex, you'll have version control, forums, some release management and bug tracking immediately. Honestly, getting the technical infrastructure setup is just plain simple.
The more important portion to me was the other "half" of the book where he discusses the team dynamics side of things.
First of all, he talks about basic Political and Social Structure of the team itself. While he lays out some general principles, the more important and valuable stuff is in his specifics. How are important decisions made? How do community members become team members? What roles and responsibilities does a team member have over a random community member?
Next, in Communications, he talks about all the day to day things we have to deal with. Difficult users, the proper tone, how to diffuse arguments, and generally how to keep things on topic are all covered. Does it all work? Nope, not all the time. But some of it definitely might work some of the time. Regardless, it's a good overview of tips and tactics interspersed with real world examples from the Subversion project.
Finally, there is detailed discussion of Managing Volunteers. This is where the vast majority of projects have problems and the reason is obvious. Very few developers - no matter how sharp they are - know how to motivate people, engage a community, and delegate tasks. Most of us confuse communications and evangelism with marketing... which realistically, I guess they are the same. Doh.
This was highlighted for me last fall at ZendCon when one person asked a panel "Do you think it's appropriate for a project to ask their users to go vote in [technical] polls?" If a project's leadership isn't supposed to engage and occasionally direct their community towards goals complementary with the project, I'm not sure what the point is.
So overall, almost every single idea struck me as both blindly obvious, incredibly powerful, and almost always missed. And the single best part about this entire book... about 90% of it applies to any project or technical community. Yes, I don't care if you're working on an Open Source project, an internal project, or a commercial shrink-wrapped application. You can use almost any idea from this book and apply it immediately.
When I started reading this book, I was active in DCPHP, working with a startup, and on the verge of leaving dotProject. This book crystallized many of my concerns and thoughts about what a community and project could and should be, so I set out to take the best ideas from the book and apply them to each of the communities that I participate in. It's been one of my primary motivators in unconference organizing and web2project and I don't hesitate to recommend this one to anyone who needs to make their project successful.
Overall, I give it a 10.
By the way, all of "Producing Open Source Software" is available under a Creative Commons license at ProducingOSS.com.
I haven’t been blogging very much for some time now; since the car crash my weekends have mostly been spent recovering from the long commute to and from work during the week. But I do tweet a lot, and thought it would be a good idea to update my website to show more of a lifestream rather than just the blog.
Storytlr has been getting a few mentions recently, such as this story on Arstechnica, since its authors decided to release it under the Apache license. Based on Zend Framework, Storytlr is relatively simple to install, but not yet as polished as Wordpress has become.
My first impressions are that it has promise, but that it’s not yet a 1.0 release in terms of quality. That surprised me, given that the guys used to run a business based on this, but full credit to them for placing the code under an open source license so that the community can keep it alive.
The Google project … I wouldn’t say it was dead, but at the time of writing it hadn’t been updated for over six weeks. There’s also a github project from the Storytlr authors, and jmhobbs has an active clone of the Storytlr project where he’s busy adding some much-needed polish. I’ve cloned the project too, and I’ll commit fixes and improvements (such as improving the Twitter plugin, and a new podcasting plugin) there as and when time allows.
I hope others pick up Storytlr and start contributing fixes and improvements too. I think it has the potential to be worth the effort.

This blog posting is in German as the event it relates to is German-only. Sorry for the inconvenience. Our next training event in English will be in Montréal in March.
Der 1. PHP SUMMIT ist eine neue und einzigartige Veranstaltung mit dem Anspruch, alle wichtigen Themen von PHP in kompakter Form zu vermitteln. Hier können Sie drei Tage lang, jenseits der ausgetretenen Pfade von klassischen IT-Trainings im Unterrichtsstil mit Übungsaufgaben und Lernkontrolle, insgesamt 18 intensive und interaktive Power Workshops erleben.
Sämtliche Workshops beziehen sich auf die tägliche Projektarbeit und zeigen Ihnen den produktiven Live- Einsatz von Tools und Methoden. Hohe Interaktion mit den Teilnehmern, Live-Coding statt vorgefertigter foo/bar Beispiele, Informationen über neueste Trends in der PHP-Entwicklung — alles gewürzt mit einer guten Prise Humor — das sind die einzigartigen Merkmale des PHP SUMMIT. Darüber hinaus profitieren Sie vom geballten Wissen und der Praxiserfahrung der drei Experten von thePHP.cc: Sebastian Bergmann, Arne Blankerts und Stefan Priebsch.
Melden Sie sich noch heute an, um sich Ihren Platz zu reservieren!
Wrote an article on DevZone about migration script from php 5.2 to 5.3. This little script can save some time when you consider to move your codebase to run under 5.3 (which you should
).
This script doesn’t do everything I’d like it to do – specifically, I’d like to make it try to figure out all kinds of messy reference scenarios, but I’m not sure how yet. And if you have other idea, please comment there or here. It’s on public git, so you can take it and modify if you wish.
Tagged: migration, PHP, php53
Truncated by Planet PHP, read more at the original (another 614 bytes)
Over time, the PHP DateTime object has become one of the best objects available to PHP developers. This object has grown since early PHP 5 into a robust class that has the ability to do lots of great things.
Recently, I was exploring some of the functionality provided by the DateTime object as of PHP 5.3 (and wishing that Ubuntu had PHP 5.3 as a package distribution). Here are some of the new things in PHP 5.3 that are really cool.
Note: you can read the manual on the DateTime object here.
DateTime::add() and DateTime::sub()
The add() and sub() methods are about adding or subtracting the number of days, months, years, etc. from a DateTime object. The interface is a bit clunky, requiring you to pass in a DateInterval object. However, this still provides an easy way to modify a DateTime object.
For example, let’s say we wanted to add 3 weeks to our DateTime object:
<?php
$dt = new DateTime(); // Set to now.
$dt->add(new DateInterval('PW3'));
echo $dt->format('n/j/Y'); // Outputs 3 weeks from today's date.
?>
How is this an improvement over using the DateTime::modify() method? It improves on it in one specific way: it’s object-oriented. Rather than passing a string you have the ability to pass an object.
DateTime::diff()
One of the coolest PHP 5.3 features introduced was the ability to diff two DateTime objects. This returns to you a DateInterval object, which contains the details of how different the objects are.
$dt1 = new DateTime('August 3rd, 2004');
$dt2 = new DateTime('August 10th, 2006');
var_dump($dt1->diff($dt2));
The result that you get looks like this:
object(DateInterval)[3]This can be extremely useful in determining the time difference between two objects.
DateTime::getTimestamp() and DateTime::setTimestamp()
Sometimes it’s just useful to be able to grab the Unix timestamp from the DateTime object. But prior to PHP 5.3, to do so required some clunky code using strtotime() and a formatted date string. PHP has fixed this, and you can now use these getter and setter methods to get the Unix timestamp.
I get a lot of forum posting in our IIS forum asking how to develop PHP application using Microsoft SQL Server. Today I am going to explain basics of developing PHP application on Microsoft SQL Server. Let me start by stating one thing, developing PHP application on Microsoft SQL Server is really easy. The extension which glues the two world namely PHP and Microsoft SQL Server is called ‘Microsoft SQL Server Driver for PHP’. Some important characteristics of this driver are:
This driver is replacement of old PHP MSSQL driver. So if you have enabled this extension, you may as well disable php_mssql.dll extension in your php.ini file. In order to disable the old MSSQL driver simply comment the below line in your php.ini file (put ‘;’ in the beginning of the line).
extension=php_mssql.dll
The old MSSQL driver is not supported by Microsoft as it takes dependency on some deprecated libraries, so it is a good idea to do the new development using new SQL Server driver. Also porting your existing application to the new SQL Server driver should be easy and is advisable from my side unless you are not planning any enhancement/development in that piece of code.
One can use Microsoft Web Platform Installer too to get the latest driver. The SQL Server driver can be found under ‘Database’ link inside ‘Web Platform’ tab. The installation comes with different version of driver to support different version of PHP as well as thread safe and non-thread safe appetite of it. The naming convention should tell you this. For example the DLL named ‘php_sqlsrv_53_ts_vc9.dll’ means this DLL should be used with thread safe version of PHP 5.3 built using VC9 compiler. Please use appropriate version otherwise PHP will not load the DLL at runtime. The installation also comes with a help file (CHM file) which contains lot of useful information pertaining to installation, usage as well as all the API well documented.
I hope this will help you getting started with developing PHP application on Microsoft SQL Server. Thanks for the patient reading and till we meet again ‘Good Bye’.
Thanks,
Don.

Getting PHP with SSH support is not an easy task in Snow Leopard. If you need it, here’s a hackish way to do it, until Sara or Mike get around to patching the ssh2 in PECL.
Requirements:In an ideal world, all you should’ve had to do is just run sudo pecl install ssh2-beta, if you do this, it’ll fail even after you’ve met the dependencies above.
To make your life easier, go ahead and run that command, and let it fail. Once it fails, you’ll need to patch the downloaded file.
In my case, I had to go to /private/var/tmp/apache_mod_php/apache_mod_php-53~1/Build/tmp/pear/download/ssh2-0.11.0
Have fun with the docs: [php.net]
PS: I’m running Snow Leopard 10.6.3 so my paths may be different than most people running 10.6.2. (yes 10.6.3 will have 5.3.1)
A recent work project required me to write a PHP script to interact with a remote SOAP service. Part of the service provider’s recommended practices entailed using a slightly dated software package called wsdl2php, which generates a single PHP file containing classes corresponding to all user-defined types from a specified WSDL file.
The issue I ran into was due to all the generated PHP classes being housed in a single file. I had to process two WSDL files that had several identical user-defined types in common. As a result, I couldn’t simply include the two PHP files generated from them because PHP doesn’t allow you to define two classes with the same name.
Looking at its source code, modifying wsdl2php to change this behavior was not a very appealing option. Attempting to consolidate the two WSDL files into one with no redundant user-defined type declarations seemed futile as well. Instead, I resolved to split the generated PHP files such that each class was contained in its own file. This would also allow me to use an autoloader to determine which of the classes I actually needed for the particular service call I was making.
Due to the number of classes, splitting the classes into separate files by hand would have been tedious and time-consuming. I decided to tap into my previous experience with the tokenizer extension to throw together a CLI script that would handle this for me. Once I got it working, it clocked in at just over 50 LOC with comments and whitespace. You simply call it from a shell and pass it the PHP file you want to split and the destination for the split class files.
I thought it might be useful for others needed to process similarly formatted source code, so I threw it into a github repository for anyone who might like to take a look. I’m open to suggestions for improvements to implement if enough people find it useful. Feel free to file an issue on the repository if you happen to find a bug.
Am kommenden Donnerstag, den 28.01.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in München statt (Mannhardtstraße 6, S-Bahn Isartor). (Foto: [www.flickr.com]
I've got 3 posts or so queued up in my mind to write out, but some of them rather depend on doing other things first, so this will just be a quick note to say I have an article in the most recent php|architect magazine on the subject of "Vector Graphics with Cairo". This is a basic introduction to the PECL/Cairo extension which I've been helping out on for a while now. Thanks to Keith Casey for his input, to the folks at php|architect for letting me do it, and the long-suffering Elizabeth Marie Smith for putting up with all my stupid questions while working on this and other extensions!
Now, back to my regularly scheduled coding...
I don't know if it's just me, or whether everyone in software development finds issue tracking software frustrating and/or broken in some way. They're all either way too complicated to set up, configure or use (the Bugzilla's or the Jira's), or have annoying "features" (such as Trac's you-lose-your-edits-if-someone-else-changed-something).
We've been using Trac at Message Systems for several years now and have been enjoying its pragmatic approach of keeping the interface simple but expressive; just enough structure to be helpful but not too much that it intrudes. We've added/modified a couple of plug-ins to it to help track time and draw some graphs, but it has otherwise served us well.
However, we've got a couple of projects that have started to converge and overlap and it's frustrating to visit the two different portals to interact and stay on top of things. As we scale up our development teams even further (we continue to have bigger and bigger plans!) this will prove to be more widely frustrating.
Enter mtrack; on one hand it's a clone of many of Trac's features (possible due to their pragmatic BSD license), but on the other it has some refinements in terms of its workflow. What's important to me is that it is built to work with multiple code repositories and allows breaking out information on a per project basis. It also tries hard to avoid losing your wiki or ticket edits if someone else updates things while you're working.
I chose to implement mtrack in PHP rather than continuing to extend Trac in python. My primary reason for this is that I've seen web apps written with Perl and Python, and while there are certainly guru developers out there that can build some awesome apps, those languages don't really lend themselves to web development and that limits the scope of potential contributors. While I can probably persuade some of my colleagues to code python web bits, I'll find it much easier to persuade more of them to code PHP web bits. I'm sure this property extends outside of our organization.
I’ve decided to leave Blue Parabola. My last day there will be Tuesday February 16. I’d like to thank Keith Casey and Marco Tabini for choosing me to be part of the team. It’s been a privilege to work with them and I’ve learned a great deal.
As for what’s next, I’ll be starting at K-fx2. (Nope, no funemployment for me.) There, I’ll be developing Zend Framework applications and helping to streamline development processes and infrastructure.
Thanks to all my friends and family who’ve provided support during this transition. I’m looking forward to what the next year holds.
Together with my friends and partners from thePHP.cc, Arne Blankerts and Stefan Priebsch, I will be giving an "Advanced PHP Development" training in Montréal in March.
If any of these questions made you blush with embarrassment, it is high time that you attend this training!
Learn how to turn bad code into good code and become better, more professional PHP developers. No question goes unanswered when we pull up an editor and explain best practices while we code a sample application live.
The PHP Days Montréal are a one-of-a-kind classroom training experience where all three thePHP.cc trainers will be present at all times. As the training is scheduled right before the ConFoo conference and the topics covered complement its presentations, the PHP Days Montréal are the perfect preparation for attendees to get the most out of the conference.
Register now to secure your seat as the number of attendees is limited to ensure a beneficial learning environment.
There certainly is a lot of buzz about Apple's rumored Tablet product. Daring Fireball writes:
If you’re thinking The Tablet is just a big iPhone, or just Apple’s take on the e-reader, or just a media player, or just anything, I say you’re thinking too small — the equivalent of thinking that the iPhone was going to be just a click wheel iPod that made phone calls. I think The Tablet is nothing short of Apple’s reconception of personal computing.
What I find most interesting are the view that the Tablet may bring new computer interaction paradigms. Again from Daring Fireball:
Our “desktop” computers’ human interfaces haven’t fundamentally changed since 1984 — keyboard and mouse/trackpad for input, overlapping draggable resizable windows on-screen, and a hierarchical file system where you create and manage “document files”. Have you ever sat back, scratched your chin, and wondered when the computer industry will break free of these current interfaces — which can be a hassle even for experts, and downright confusing (e.g. click vs. double-click) for the non-experts? Surely no one expects the computer interfaces of, say, 50 years hence to be based on these same metaphors and input methods. What’s the next step?
A touchscreen tablet isn't really suited for the WIMP paradigm as for example text entry is quite difficult, and you probably want larger, thumb-friendly user interface elements. This is where Microsoft's Tablet PC initiative failed, trying to bring the regular WIMP user interface to the tablet.
Instead what seems to be happening is that all the Wiis, iPhones, and N900s are now heading us towards a post-WIMP world. Instead of indirect manipulation by mouse and keyboard we can now interact with our applications using the more natural ways of touching things on screen or moving the device around.
This innovation will not be limited only to mobile APIs, web applications can already now know whether user is accessing them via a WIMP system or a touchscreen device thanks to CSS media queries and Javascript orientation events in latest Firefox.
The user interface innovation that is arriving thanks to these new interaction possibilities is quite promising, though it will probably take a while before we know what things actually work, and what are just fun demos.
If you're thinking about new kinds of user interfaces, it might be a good time to read papers like Noncommand User Interfaces (Jakob Nielsen, 1993) and Magic Ink (Bret Victor, 2006).
I certainly am as we are in the process of defining a new kind of CMS UI for Midgard 2.
Update: Gizmodo has a very nice article on Jef Raskin's information appliance concept and the evolution of GUIs.
The web is a great place for people to express their opinions, on just about any subject. Even the professionally opinionated, like movie reviewers, have blogs where the public can comment and respond with what they think, and there are a number of sites that deal in nothing more than this. The ability to automatically extract people's opinions from all this raw text can be a very powerful one, and it's a well studied area - no doubt because of the commercial possibilities.
Opinion mining, or sentiment analysis, is far from a solved problem though. People often express more than one opinion "the movie was terrible, but DeNiro's performance was superb, as always", use sarcasm "this is probably the best laptop Dell could come up with", or use negation and complex devices that can be hard to parse "not that I'm saying this was a bad experience".
On top of this, expressions of sentiment tend to be very topic focused - what works for one subject might not work for another. To use a well worn example, it's a good thing to say that the plot of a movie is unpredictable, but a bad thing to say it about the steering of a car. Even within a certain product, the same words can describe opposite feeling about different features - it's bad for the start-up time on a digital camera to be long, but it's good for the battery life to be long. This is why a great deal of work, particularly in product reviews, is spent in classifying which element of a product is being talked about, before starting the opinion mining process.
At the moviesWe'll start with a simpler approach, and look at movie reviews. Luckily for us these are fairly easily available on line from places like Rotten Tomatoes and IMDB, and indeed a convenient data set of sentences expressing positive and negative opinions has already been compiled. We're using opinions expressed on the sentence level in order to give ourselves a little more granularity - while most movie reviews are longer than this, they will also usually express more than one opinion, and keeping our document unit smaller helps us avoid muddying the waters.
The data is supplied as two files, one for positive opinions and the other negative, with one sentence per line, which makes it easy to parse. To actually extract the opinion, we're going to make use of a classic and well known tool, a Naive Bayesian classifier. These were all the rage for spam filters a couple of years back, and are still a hugely popular way of doing filtering. They have the advantage that they're easy to implement, pretty effective, and quick to classify with.
Naive BayesBayesian classifiers are based around the Bayes rule, a way of looking at conditional probabilities that allows you to flip the condition around in a convenient way. A conditional probably is a probably that event X will occur, given the evidence Y. That is normally written P(X | Y). The Bayes rule allows us to determine this probability when all we have is the probability of the opposite result, and of the two components individually: P(X | Y) = P(X)P(Y | X) / P(Y). This restatement can be very helpful when we're trying to estimate the probability of something based on examples of it occurring.
In this case, we're trying to estimate the probability that a document is positive or negative, given it's contents. We can restate that so that is in terms of the probability of that document occurring if it has been predetermined to be positive or negative. This is convenient, because we have examples of positive and negative opinions from our data set above.
The thing that makes this a "naive" Bayesian process is that we make a big assumption about how we can calculate at the probability of the document occurring: that it is equal to the product of the probabilities of each word within it occurring. This implies that there is no link between one word and another word. This independence assumption is clearly not true: there are lots of words which occur together more frequently that either do individually, or with other words, but this convenient fiction massively simplifies things for us, and makes it straightforward to build a classifier.
We can estimate the probability of a word occurring given a positive or negative sentiment by looking through a series of examples of positive and negative sentiments and counting how often it occurs in each class. This is what makes this supervised learning - the requirement for pre-classified examples to train on.
So, our initial
Truncated by Planet PHP, read more at the original (another 29822 bytes)
I have had some serious issues with one of my servers these last days. But finally things are starting to get back to normal. It seems /var was full due to mysql wreaking havoc for no particular reason. This lead - curiously enough - to network problems. If one of the discs failed because of these events or if it is somehow the original problem causing all this I really can’t tell…
Anyway, instead of quickly fixing the problem, I took the time to set up a new server running Zend Server CE with PHP 5.3. It feels good to finally move to 5.3 as well as trying out Zend Server in a production environment.
Now if I only had time to try out the new Zend Server 5.0. I’m especially curious about the job queue management. As I’ve more or less lost two days and two nights I guess that’ll have to wait.
I can’t make any claim to the title of veteran conference speaker. Not yet, at least. However, I have done it once before at ZendCon in 2008 and I’ll be doing it again at php|tek this year. I thought I’d take a blog post to give out a few tips to any prospective first-time speakers based on my first speaking experience. I’m assuming there that you’ve already decided on a particular conference that you want to attend, you’ve submitted a session proposal, and you’ve been accepted.
First, in addition to the other things you should do before attending, be ready to give your presentation before you get on the plane. You should start on your slides as far in advance as possible. Don’t put it off or wait until the last minute, because it will likely be more work than you anticipate. This includes making sure that any live demos you intend to give will run as expected. Syntax errors and crashing web servers look very bad to the audience.
One of the reasons for this is that you’ll want to practice your talk out loud. It’s one thing to put the material onto slides, but it may sound different when it’s actually coming out of your mouth and going into the crowd. You may find stumbling points, places where you stutter or get caught off-guard when transitioning from one topic to another. Try to organize the presentation such that it matches your natural flow when talking about the topic without any slides at all.
Which reminds me, learn from the masters. People like Marco Tabini have spoken before and have a wealth of knowledge that they’ll share fairly freely most of the time, especially if alcohol (or, in Marco’s case, an espresso) is involved. Look at books like Presentation Zen by Garr Reynolds. Take the time to hone your presentation skills before you have to make your delivery.
If you’ve been to a conference before, you’ve probably already learned about my next point the hard way. Don’t depend on wifi internet access availability. Why not? Because the vast majority of the time, it will suck. There won’t be enough IP addresses, someone will do something to hog bandwidth and make latency skyrocket, it will find some way to refuse to work. Save local copies of files, write a minimal daemon to simulate a remote server, do whatever you need to do to avoid it.
That point goes hand in hand with this one: test your equipment early and have a Plan B. In particular, hook your laptop up to the projector in the room in which you’ll be speaking (or to a test projector, if the conference hosts provide one and prefer you use that) to make sure it can display your slides. Ben Ramsey was gracious enough to loan me his Macbook at ZendCon because my Sony Vaio refused to work with the projector and the time-sensitive situation did nothing but add to my speaking nerves. Make sure you don’t end up in the same spot.
Lastly, don’t let critical reception deter you from speaking again. I got pretty negative feedback the first time around, but I took it in stride. While I know I have plenty of room for improvement, I’m still going to give it another shot. Do your very best, then strive to be better.
Hope you enjoyed this blog post and gleaned something useful from it. If you’ve got any of your own speaking tips, please feel free to add a comment on this post. If you’ll be attending php|tek, I look forward to seeing you there!
There has been several instances where people using WINCACHE have reported problem while running it on the actual production server. They have complained that WINCACHE works very well on development server but the users can see a crash (or different symptoms of it) while actually deploying it on a live production server. I am pasting some of the forum links where these kind of problems have been reported:
As one can see there are various symptoms of this. Users can start getting a blank page or PHP can stop responding. And eventually there will a crash report in the Windows Event Viewer which will be something similar to:
Faulting application php-cgi.exe, version 5.2.11.11, time stamp 0x4ab13019, faulting module php_wincache.dll, version 1.0.819.0, time stamp 0x4a8e6f87, exception code 0xc0000005, fault offset 0x000029be, process id 0x37c, application start time 0x01ca3d975761fce0.
The developer on the team was finally able to figure out the actual problem. As per him,
Crashes were happening because refcounts of global aplist filemap and global opcode cache filemap were going out of sync. When a local opcode cache filemap get created, this process doesn’t increment refcount of filemap which holds global opcode cache but still increment the refcount of filemap used to store global aplist. As new php-cgi processes gets created and killed, this difference in refcounts keep going high and reaches a point where refcount for global opcode cache hits zero but global aplist is positive. At this point all opcode cache offsets in global aplist are invalid. Now the next php-cgi process which gets launched creates a new global opcode cache filemap and but uses existing global aplist. This process will crash when it uses old opcode cache offsets from the aplist because those are not valid for brand new opcode cache. I have fixed the bug by making global aplist set opcode cache offsets to 0 when we detect that a new global opcode cache is created.
This has been a very critical fix. Since I was never able to reproduce it, I would like this to be validated by all of the user’s out there who have seen the crash. Please take time to validate this critical fix. If you want to get the binaries please write a mail to one of the email id specified below specifying whether you are interested in PHP 5.2 or PHP 5.3 version of WINCACHE DLL. The email ids to reach for is:
I am on vacation till the end of this week and hence I will prefer to use first two mailing ids.
I would personally like this fix to address all the crashes being observed in WINCACHE by the users above. It is very important for you all using WINCACHE and seeing the above bad behavior to look at the new binary, try it and report any problem if it still persists. We want to address all the above crashes which will eventually be packaged/bundled together and released as WINCACHE 1.0.1. So please come forward and help us. We did test it on Ruslaan’s server ( [www.ruslany.net] ) and now it is no longer crashing (It does use to crash before). So we do have some sort of validation on our side.
This fix closes the bug at [pecl.php.net] . The actual code for the fix can be found at [svn.php.net] for people interested.
Happy testing and thanks for helping the WINCACHE team. And till we meet again ‘Good Bye’.
Thanks,
Don.
Check out a review of The Definitive Guide to SugarCRM: Better Business Applications and all of the available SugarCRM books on Sander Van Hooft’s blog. He recommended my book as the book to read for any SugarCRM developer, especially if they want to get deep into the MVC framework.
Thanks Sander for the great review of the current state of SugarCRM books!
<?php
if(DEV){
$server = "localhost";
} else {
$server = "10.1.1.25";
}
?>
; db.ini
[myconfig]
myconfig.db.mydb.db = mydb
myconfig.db.mydb.user = user
myconfig.db.mydb.pass = pass
myconfig.db.mydb.server = host
<?php
/**
* Creates a MySQLi instance using the settings from ini files
*
* @author Brian Moon
* @copyright 1997-Present dealnews.com, Inc.
*
*/
class MyDB {
/**
* Namespace for my settings in the ini file
*/
const INI_NAMESPACE = "dealnews";
/**
* Creates a MySQLi instance using the settings from ini files
*
* @param string $group The group of settings to load.
* @return object
*
*/
public static function init($group) {
static $dbs = array();
if(!is_string($group)) {
throw new Exception("Invalid group requested");
}
if(empty($dbs["group"])){
$prefix = MyDB::INI_NAMESPACE.".db.$group";
$db = get_cfg_var("$prefix.db");
 Truncated by Planet PHP, read more at the original (another 4107 bytes)
Since PHPUnit 3.4.0 a new extension point for interacting with issue tracking systems (TTS) based on the test results has been added to PHP's first choice xUnit framework. The extension point has been introduced by an abstract PHPUnit_Extensions_TicketListener class, which allows developer to add tailor-made ticket listeners supporting their favoured TTS. Currently PHPUnit ships with a single ticket listener for Trac as it's still the used TTS for the framework itself. As I start to become more and more accustomed to use GitHub for some of my exploratory projects and hacks, the following blog post will contain a GitHub_TicketListener implementation and a showcase of it's usage.Annotating tests with ticket meta dataAs you might know, it's considered to be a best practice to write a test for each new ticket representing a bug and drive the system under test (SUT) till the issue is resolved. This extension of test-driven development is also known as test-driven bug fixing. To create a relation between these tests and their associated tickets, PHPUnit provides a new @ticket annotation which will be analyzed before each test is run. The following code listing shows such an annotated test.<?phpPeeking at the GitHub_TicketListener implementationThe current version (3.4.6) of PHPUnit has a pending issue regarding the abstract TicketListener class, so the first step is to apply an 'exploratory' patch, which might break the functionality of the shipped Trac ticket listener but will enable the use of the one for GitHub's TTS.
require_once 'PHPUnit/Framework.php';
class ExampleTest extends PHPUnit_Framework_TestCase
{
....
/**
* @ticket 2
* @test
*/
public function shouldGuarantyThatTheSutHandlesTheIssueCorrectly()
{
// test code
}
....
<?php
require_once('PHPUnit/Extensions/TicketListener.php');
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
/**
* A ticket listener that interacts with the GitHub issue API.
*/
class PHPUnit_Extensions_TicketListener_GitHub extends
PHPUnit_Extensions_TicketListener
{
const STATUS_CLOSE = 'closed';
const STATUS_REOPEN = 'reopened';
private $_username = null;
private $_apiToken = null;
private $_repository = null;
private $_apiPath = null;
private $_printTicketStateChanges = false;
/**
* @param string $username The username associated with the GitHub account.
* @param string $apiToken The API token associated with the GitHub account.
* @param string $repository The repository of the system under test (SUT) on GitHub.
* @param string $printTicketChanges Boolean flag to print the ticket state
* changes in the test result.
* @throws RuntimeException
*/
public function __construct($username, $apiToken, $repository,
$printTicketStateChanges = false)
{
if ($this->_isCurlAvailable() === false) {
throw new RuntimeException('
Truncated by Planet PHP, read more at the original (another 8040 bytes)
public class AnimatedLabelFeedback extends ImageCycleFeedbackBase {
private CLabel label;
public AnimatedLabelFeedback(Shell parentShell, CLabel item, Image[] images) {
super(parentShell, images);
label = item;
}
public void initialize(AnimationEngine engine) {
background = label.getParent().getBackground();
display = label.getParent().getDisplay();
}
public void saveStoppedImage() {
stoppedImage = label.getImage();
}
public void setStoppedImage(Image image) {
label.setImage(image);
}
public void showImage(Image image) {
if (!label.isDisposed()) {
label.setImage(image);
}
}
}
label = new CLabel(parent, SWT.SHADOW_NONE);
Image[] images = loadAnimatedGIF(parent.getDisplay(), "icons/obj16/animated.gif");
AnimatedLabelFeedback feedback = new AnimatedLabelFeedback(parent.getShell(), label, images));
animation = new AnimationEngine(feedback,
-1, // endless
100 // delay between frames in milliseconds);
animation.schedule();
private void loadAnimatedGIF(Display display, String imagePath) {
URL url = FileLocator.find(Activator.getDefault().getBundle(),
new Path(imagePath), null);
ImageLoader imageLoader = new ImageLoader();
imageLoader.load(url.openStream());
images = new Image[imageLoader.data.length];
for (int i = 0; i ImageData nextFrameData = imageLoader.data[i];
images[i] = new Image(display, nextFrameData);
}
}
Dispose animation engine when it's not needed anymore (usually in dispose() method):animation.cancelAnimation();
Since the v1.2 release in early December, it's been a bit of an adventure... in the first week after the release, we got a couple major bug reports. Another few days resulted in a few more. Another day, another bug. In the first two weeks, we received a total of 7 bugs that ranked from major to critical. All in all, it was a bad time. Conveniently enough, none of the bugs were particularly complicated or deep, so we were able to quickly resolve each of them and eventually release a v1.2.1. And after receiving word of a small issue requiring another merge, v1.2.2 shortly after the New Year.
While a few members of our community were understandably upset, I was impressed that the bugs were found so quickly and resolves just as quickly. I couldn't put words to this well until I read Karl Fogel's post "Bug Growth is Proportional to User Growth, and Bugs are not Technical Debt." Wow, that Karl is a smart guy. More on that topic later.
For v1.3 we have quite a few features and fixes on the way:
First, we've written some Views Helpers. These helpers handle auto-linking fields that have url's in them or even email fields. On the other side of things, we've added validation for email and url fields. If something is supposed to be a url, it will be.
Next, we've moved the Upgrader into the System Admin. By doing this, we can make sure only Administrators can upgrade a system. Further, we've added a warning message in case someone deployed an upgrade but didn't run the script.
Next, we've added CSS "minification". Through some creative manipulation of our Phing script, when our download package is created, it compresses the CSS. We were able to trim 33% from both the download packages and the installed application. We've tracked down a few other places and can probably drop another 20-30% of the package the same way.
Finally, we're spending quite a bit of effort on character encoding and internationalization. If you use web2project exlcusively in English, you haven't noticed any problems. If you use German, Russian, or a variety of other languages, you've noticed issues in the Gantt charts and the PDFs. Unforuntately, to resolve this one, it takes a lot of effort:
On a related note, we've also been working on compatibility. v1.2 was the first version of web2project to formally support IIS7 but v1.3 is going to push this even further in at least one major direction.
Stay tuned...
var win = XN.xnew({
xtype : Gtk.Window,
type: Gtk.WindowType.TOPLEVEL,
listeners : {
'delete-event' : function (widget, event) {
return false;
},
destroy : function (widget) {
Gtk.main_quit();
}
},
set : {
set_border_width : [ 10 ],
resize : [300, 300],
show_all : []
},
items : [
Truncated by Planet PHP, read more at the original (another 5487 bytes)
Please shell out a few minutes to help the IKS Project identify business needs for semantic CMS by participating in a survey. The results will help the EU-funded project to work towards an Open Source interactive knowledge stack.
There are two different sets of questions, depending on your background:
Thanks for participating in the survey and please spread the word!
A short while ago, someone popped into the PEAR irc channel on efnet and asked about installing Statusnet – which is a “open source micro messaging platform that helps you share and connect in real-time within your own domain.” It’s what powers identi.ca and similar micro-blogging services.
Specifically, this person wanted advice on installing the six or so PEAR packages on which this software depends; eight if you include the optional ones.
Foreseeing a number of people wanting similar help, I thought it would be best to create a metapackage to bundle these PEAR packages together – at the least it would mean only one “pear install” command would be required and it would reduce the number of potential mistakes that could be made.
Following my own instructions in the “Dependency Tracking (Meta Packages) with PEAR” section in the PEAR documentation, I quickly came up with Statusnet_Statusnet-0.1.1.tgz.
Install it via “$pear install [short.ie] for the moment – as the location of where it’s being hosted may change during the week.
Am kommenden Donnerstag, den 21.01.2010 findet wieder ein öffentlicher Vortrag im Mayflower Büro in München statt (Mannhardtstraße 6, S-Bahn Isartor).
Recently I have devoting my attention towards other projects like djtechtools.com and un-informed.org/un-i.org away from php.net. That is not to say I have stopped following whats going on or that I do not care anymore. Its just that I feel that I can make more of a difference in these other projects. Also it might just be sort of a phase thing. I am sure one day I will become focused on php.net stuff again. Until then I hope others will pick up the slack and make sure that PDO gets love, at people diligently follow up on todo items mentioned on internals and that someone else picks up wiki.php.net and takes care of some regular maintenance stuff. Like there is a new version of dokuwiki out that fixes some issues, adds some features and adds PHP 5.3 support. If you are interested drop me a line or submit a comment. Who ever sticks around for a while and gives the wiki some love will obviously get commit access with that ever so shiny @php.net email alias.
I'm a bit delinquent, but this is my first post of the year, and sticking with tradition, it's a chance for me to record highlights from the previous year. This is my seventh consecutive year doing this; it's hard to believe I've been blogging consistently for that long.
I used to speak at more than a dozen conferences each year, and it negatively affected the quality of my talks and the quality of my life. My speaking schedule for 2009 was much better:
PHP UK I gave the last talk at PHP UK, and although it wasn't considered a keynote, it sure felt like one. It was one of my favorite talks for numerous reasons. I had just spent a few hours drinking Persian tea in the sun at a café with Jon and Jon, so I was both relaxed and energized. The stage had no podium, so I felt very connected to the audience. (It also helped that the auditorium was shaped like a bowl.) The feedback was also extremely kind; people thought the talk was inspiring, even better than expected, mind boggling, and the highlight of the conference. (One person even suggested it saved the conference.) Perhaps more surprising than the quality of the feedback was the quantity, thanks mostly to the ubiquity of Twitter. To those who said nice things, thank you so much. It really helped lift my spirits. I capped off my visit to London with an Arsenal match. (It was yet another draw; they're doing much better this season.) PHP Québec Almost immediately after returning from the UK, I was off to Montréal for the annual PHP Québec conference, one of my favorites. I enjoyed all the usual delights, including viande fumée at Schwartz's. I was very happy to be giving the closing keynote, and even happier about how many people were there and all of the nice feedback on Twitter and elsewhere. I managed to get a photo of the audience participating in a change blindness experiment, which I later used in a change blindness demonstration, just to be meta. :-) php|tek The annual php|tek conference was back in Rosemont (not too far from Chicago), and it was every bit as fun as expected. I was able to celebrate my birthday at the Map Room, where Sean played beer host, and everyone had a great time. (I know I did.) I also managed to make it downtown, where I tried Chicago-style pizza for the first time. It was pretty good, but it just can't compete with New York-style pizza. (I still love going to Grimaldi's for lunch when the line's short.) My talk was a big hit as well, but I didn't have quite as much energy as when I gave it at PHP UK. OSCON San Jose is no Portland, and that one fact made this OSCON a little underwhelming. It has often been my favorite conference of the year, but not this year. Luckily, Andrei convinced Helgi, Jon, Sean, and me to stay in San Francisco. As a result, some of my best memories were of places like Samovar, 21st Amendment, and Russian River. In the evenings, I learned a lot about grids, leading, and vertical rhythm from Jon while watching him prepare his talk. The tutorial I gave with Sean went really well, although it was a little rough around the edges, and my talk was a big hit. ATruncated by Planet PHP, read more at the original (another 5532 bytes)
Coming this March, I’ll be premiering a new at confoo.ca entitled “Making software management tools work for you“.
The inspiration for this talk came from seeing soo many talks about using the gazillion different tools out there, from version control and bug tracking to project planning and collaboration. Each talk does a great job at introducing the tool and talking about how it works. The big void I hope to fill is to how to evaluate and develop your processes, and then how to pick the right tools to make support your process. I’m going to draw on experiences I’ve had in working with different types of team, and hope to illustrate that there is no “silver bullet” of management tools, but rather that tools should compliment the process your team has in order to achieve true efficiency.
Be sure to register by January 22 to get in on the early-bird $200 of offer. Big thanks to the organizers of the conference for accepting my talk; I’m really excited to hear the feedback from it.
There are lots of projects heading over to Git these days. It’s not hard to see why: Git offers great merging support, distributed version control, and a great playground. Spots like Github even offer centralization crucial to large open source projects. But when it comes to the corporate world, Git may not be ready for prime time.
Corporate America needs a centralized version control system. Subversion still offers this: Subversion centralizes the repository and simply checks out a working copy (versus Git, which gives you a complete repository). Corporate America still needs to have cannonical version numbers, and the ability to see the progress of a product over time as a single line – not a bunch of branches and independent repositories.
Git is a great piece of software. It is fantastic for distributed version control. It is my opinion that when it comes to corporate work, Subversion will still continue to win out
I've spent some time lately working on a project involving data-flow analysis for PHP.
This analyzer will basically model your code as control flow graphs, in which it will assign types and let them flow through control structures. When reaching stability, it will check that the operations done of the values are sound type-wise. It will also do some structural checks.
For more details, I suggest you read the technical report that you can find here:
[project.colder.ch]
You can also find a presentation I gave recently about it: [github.com]
This project is in an early stage, a prototype, but still gives some results!
If you try it out, no need to report and tell me "Hey this fails and this and this", I know. It's not supposed to work for every input code yet! However, I would happily accept any contribution!
You will find the github project page here: [github.com]
ps: I just missed the 1 year "no-news anniversary", damn!
A new Gartner report about PHP - PHP: Past, present and Future is mentioned in the last Zend newsletter. Even though I remain somewhat sceptical towards similar reports it is good to see that even Gartner is catching up. What they say actually do have an impact.
"PHP has been a cornerstone technology on the Web for more than a decade. While its adoption among mainstream IT organizations has been limited in the past, many corporate application development (AD) projects are discovering the unique benefits of PHP."
One particular advice is especially interesting for large companies.
"Consider PHP as a supporting technology in a broader portfolio of AD technologies, where it can provide a specialized toolset for building Web graphical user interface (GUI) front ends to service-oriented architecture (SOA) back-end services."
PHP is a fantastic tool for building rich web applications. It’s extensibility makes it versatile and extremely easy to integrate with modern integration solutions as Web Methods, legacy systems or just about any database technology.
To me - this has always been where PHP really shines.
Shipping code that works is crucial to retaining the support of customers and high quality in your application. While it’s impossible to ship code without any bugs at all, it is possible to control for as many as possible, and fix as many known issues as there is time. These strategies are designed to ensure that code works when it is shipped to the end user.
Employ testers.
Developers have a tendency to test their code only with expected data. Testers, on the other hand, aren’t developers themselves; instead, they will use data that you don’t expect and find bugs that your users might otherwise experience.
Hiring testers is a tough sell in many development teams, especially small ones. It is possible to have testers that have other functions – that is, they might be in another department or moonlight as testers. But with teams larger than 5 developers, having a full time tester is a crucial component of good development practices.
Write unit tests.
Every developer makes mistakes at some point. Having unit tests in place will help find these mistakes by showing you where a class breaks. It makes refactoring easier as well, since you can refactor and know that if your unit tests pass, there’s a good chance that you did it properly.
Unit testing should be built into the process of code development from the beginning of a project. However, if you’re starting from someone else’s project and the project doesn’t have unit tests already, simply institute a process of fixing bugs after you’ve written a unit test that identifies the bug. Eventually you’ll have unit tests for most of the application.
Write functional tests.
Unit tests are great, but they’re not enough. Knowing that one function takes an array and creates an object is fine, but what happens with the next function, and the one after that? Introducing functional tests: testing against expected behavior.
There’s a subtle difference between these two concepts. Unit tests test a specific component of the code: a single method, function, or clause. Functional testing, on the other hand, tests expected behavior: does clicking that button actually result in a refreshed page? Does my controller actually invoke the action properly? More than one method might be acted upon with functional testing.
A lot of this testing is done by the testers; however with applications like Selenium you can conduct some automated functional tests. On a small team that doesn’t have testers, or on a large team where there might be a challenged set of resources, automated functional tests can help reduce the testing burden.
Work unit testing into your build process.
We talked about integrating your build process with a continuous integration server. With build engines like Phing, it’s possible to automate the unit testing process (and even the functional testing process to some degree).
Each time you make a build for release, you should know that all the unit tests pass. If they don’t, there’s a problem that should be addressed before the build is completed.
Use continuous integration to know when tests began failing.
To hit on the same theme, a solid continuous integration server will automatically run your tests and alert you as soon as the first one fails. This helps prevent regression – the introduction of bugs into code that worked in previous releases. The time to discover regression isn’t when the build is due and the team is ready to go, it’s right after a commit, and continuous integration will help with this.