New Releases!

It’s been a busy weekend playing catchup on bug reports and feature requests. These projects of mine have seen new releases yesterday and today as a result:

* Contact_Vcard_Build 1.1.1 (bugfixes)
* Contact_Vcard_Parse 1.31.0 (bugfixes)
* DB_Table 1.0.1 (bugfixes)
* Savant3 dev 4

The new Savant release bears a little talking-about. I don’t like breaking backwards compatibility even in a development release if I can help it, but there was one issue that required an architectural change related to error handling. That is the removal of error-handling resources (e.g., Savant3_Error_pear, et. al.), which is pretty significant if you use it. (Exceptions are a special case; see below for more on that.)

The original purpose of having error-handling resources was so that you could report and test for errors using your own framework-specific calls. While the Savant3 error resources would allow you to plug into those systems, the number-one complaint I got was that Savant3 still returned errors as Savant3_Error objects, which meant that you had to use Savant3 to check for errors, not the framework-specific error checker. That’s obviously a problem, as it doesn’t meet the original goal of being able to abstract error reporting and testing.

As a result, I have removed the error-handling resource infrastructure. Instead, if you want to use framework-specific error reporting and testing, you should extend Savant3 and override the error() and isError() methods. For example, if you wanted to use PEAR_Error handling, you would do something like this:

include_once 'Savant3.php';
class Savant3_Pear extends Savant3 {

    public method error($code, $info = array(), $level = E_USER_ERROR,
        $trace = true)
        if (! class_exists('PEAR_Error')) {
            include_once 'PEAR.php';
        $err = PEAR::raiseError($code, $code, $info, $level);
        return $err;

    public function isError($obj)
        if (! class_exists('PEAR_Error')) {
            include_once 'PEAR.php';
        return PEAR::isError($obj);

The difference between this and the previous (Savant2) error handler resource architecture is that the call to error() will return a PEAR_Error, not a Savant3_Error. In addition, while you can test for errors using the extended isError() method, you can use PEAR::isError() instead because the returned error object is a real PEAR_Error object. This applies to all frameworks that use their own error handling systems (which is, well, almost all frameworks, including Solar, which now bundles Savant3 as its default template system).

Exceptions are a special case; they’re native to PHP5, so they have native support in Savant3 now (instead of being an error handler resource). If you want Savant3 to throw exceptions, call setExceptions(true) and it’ll throw Savant3_Exception objects when errors occur.

For full change notes, be sure to visit the Savant3 website.

Changing Hosts for Solar: Complete!

Before I continue, please note that Clay Loveless volunteered the hosting services and has managed the transition in a most professional way (even though he is not a hosting provider, he’s a PHP guru). Clay set up the new services, including mailing list (with transition of archives and addresses), email accounts, Subversion repository, database, web with SSL, and PEAR channel server. He runs Killersoft and Pearified; you really should consider contacting him for your next PHP project, as his attention to detail and commitment to high quality service have been obvious throughout the transition process.

And now the cat is out of the bag; everything we gained in the transition is listed above. Point by point, the details are:

* Solar is still at, the API docs are still at, and bug reporting is still at

* The Subversion repository is now available for browsing and anonymous reading at You want to commit patches or add packages? Email me, the benevolent dictator of the Solar system, at pmjones at solarphp dot com — we’ll work something out.

* Clay set up a PEAR channel server based on Davey Shafik’s excellent Cerebral Cortex work. Although there are no packages loaded yet, they will end up at Look for more on that later. In the mean time, you can download the latest release at

Changing Hosts for Solar

Right now is hosted at TextDrive, which (a) costs money, and (b) is not too flexible. Through the generous good will of Clay Loveless, who runs, Solar will soon be hosted on another machine. Among the benefits will be SSL-based access to the Subversion repository, as well an honest-to-Zoroaster PEAR channel, which means we’ll be able to do some cooler stuff with installations and usage tracking.

This may entail a bit of confusion over the next few days. We’ll be moving the mailing list, so you may see an “unsubscribe” and then a new “subscribe” in your inboxes. Not sure yet if that’ll be necessary, but don’t be surprised if it shows up. Don’t know yet how to export the archives, but if we can save them, we will.

After that’s done I’ll post another update. The mailing list and Solar website may be flaky during transition, so if you need to contact me, use my “real” address at pmjones-at-mac-dot-com.

(p.s. Yes, PHP Tropics was excellent. I’ll write more about that later. 🙂

Hierarchy? We don’t need no steenkin hierarchy!

Really, if you’re not reading Ryan King on a regular basis, you’re missing a lot of good thinking. In this post, he points to work from Clay Shirky (a true visonary and excellent essayist).

Clay’s essay is about hierarchical organization versus user-defined relationships. This is one of the differences between Yahoo (who did a “big up front design” on their catalog to tell you where things go so that the stack “makes sense”) and Google (who don’t organize at all, they let you sift instantly through the stack). I quote:

Browse versus search is a radical increase in the trust we put in link infrastructure, and in the degree of power derived from that link structure. Browse says the people making the ontology, the people doing the categorization, have the responsibility to organize the world in advance. Given this requirement, the views of the catalogers necessarily override the user’s needs and the user’s view of the world. If you want something that hasn’t been categorized in the way you think about it, you’re out of luck.

The search paradigm says the reverse. It says nobody gets to tell you in advance what it is you need. Search says that, at the moment that you are looking for it, we will do our best to service it based on this link structure, because we believe we can build a world where we don’t need the hierarchy to coexist with the link structure.

A lot of the conversation that’s going on now about categorization starts at a second step — “Since categorization is a good way to organize the world, we should…” But the first step is to ask the critical question: Is categorization a good idea? We can see, from the Yahoo versus Google example, that there are a number of cases where you get significant value out of not categorizing. Even Google adopted DMOZ, the open source version of the Yahoo directory, and later they downgraded its presence on the site, because almost no one was using it. When people were offered search and categorization side-by-side, fewer and fewer people were using categorization to find things.

Read the whole thing.

Going To Cancun (Part 2)

Tomorrow I’ll be going to PHP Tropics as both a vacation and as professional development. Woohoo! 🙂

And on a professional note: If I have not responded to your emails to me about Solar, Text_Wiki, Savant, DB_Table, or any of my other projects, please accept my apologies. I’ve been horribly busy with my MBA classes and “real” (paying) work and family duties, so everything else has had to sit by the wayside for now. After I get back from Cancun I’ll be able to respond with my prior speed (such as it was).