Skip to content

Home

Back from Paris

I'm back home from my Paris trip; it was a long day of travelling, but it all went smoothly. On the train from Gare du Nord to Charles de Gaule I saw a burnt out wreck of a truck; perhaps it was from the rioting, but I couldn't say for sure. This was the only sign of unrest that I saw on the whole trip; a big contrast from the country-on-fire images broadcast via CNN. Admittedly, I only saw a limited section of the Paris area while I was there, so who am I to make a sound judgement?

I've updated the PDO slides from my presentation at Forum PHP 2005. These slides are from the long version of my talk, rather than the shorter 45-minute version that I gave there.

After a slightly shaky start, the trip turned out to be a success. The start was shaky because the service at my hotel wasn't all that great; apparently just giving my surname was not good enough for them to find my reservation, so I had to scrabble around my email (lucky that I had my IMAP mailbox sync'd to my HD!) to find additional information. After then waiting for the english speaker to finish his cigarette break, I could finally confirm my reservation. I then had to wait for my room to be made up. Not the best service I've ever had; I think they probably assumed that I'd come from England that morning, when in fact I'd been travelling from the USA since the day before. Oh well.

The hotel was ok though, and they had free wifi access for guests. It was WEP protected and when I asked about the WEP key, the guy at the desk said he didn't have any more boxes. Strange. The next night I was lucky and managed to obtain a box... it turns out that they use a little box with a wifi-to-ethernet bridge in them; one end of the box plugs into the AC outlet in the wall, and the other into your ethernet port. Interesting approach; it means that they don't need to worry about giving out their WEP keys, can provide service to people without wifi cards and that they don't need to plumb in wired ethernet either.

I've arrived at Forum PHP

I'm sitting in the soundproof booth at the Forum PHP in Paris. I've been up for more than 24 hours straight (don't you just love timezone shifts!) so I'm feeling pretty tired. Contrary to the doom and panic mongering that was on CNN while I was waiting at the airport in Atlanta (that's the airport with the really long walk between the domestic and international concourses), Paris doesn't seem like it's about to be torn down by rioters; seems pretty peaceful and not tense at all. I've been told that the unrest is mainly in the suburbs, and was mostly outside of Paris itself last night.

I've also heard pretty bad things about Charles de Gaule airport, but found it to be quite empty and easy to navigate when I arrived just before 7am local time; maybe I've just been lucky :)

While I'm here, I'll be giving my PDO talk and sitting in on a Q&A panel with the other PHP big wigs that are also here (Rasmus, Zeev, Andrei and Zak). After the conference itself, we'll be holding a meeting to hammer out some of the finer details for PHP 6; the other other PHP big wigs are making their way to Paris after the PHP conference that is concurrently underway in Frankfurt.

pecl4win

I don't know if you're all aware of pecl4win.php.net. This new service, graciously provided by Emini A/S, continually builds PECL extensions against the various different branches of PHP so that you can very easily find the latest version of a given PECL extension to match the version of PHP that you're running.

Edin Kadribasic from Emini has been looking after the official Windows build of PHP (he builds our Windows distribution) for some time, and this service is his latest innovation; thanks Edin!

PDO 1.0RC2 released via PECL

I released the next release candidate for PDO tonight. You can find the full changelog here. There are two changes of note (I can't take credit for these, you can (blame|thank) Ilia and Marcus):

  • Changed PDO_XXX constant names into PDO::XXX and renamed pdo_drivers() to PDO::getAvailableDrivers()
  • Removed the "final" attribute from the PDO and PDOStatement constructors, making it significantly easier to extend PDO in your apps. You'll probably want to look at PDO::setAttribute(PDO::ATTR_STATEMENT_CLASS) if you're doing that sort of thing.

I also released the next installment for the various drivers; mostly bug fixes here and there. The biggest patch was making LOBs work for the OCI driver.

You can find the updated packages in PECL, and find pre-compiled Windows extension DLLs at pecl4win.

Enjoy!

Trying out feedburner

I've redirected my feeds via FeedBurner so that I can get some idea of how many people are reading this stuff. If this causes some burps and "re-runs" of my earlier posting in the various aggregators out there, I apologize.

I've also added a limit on the number of items that wind up in my feed, so you won't have to fetch my entire blog history when polling for new articles.

The feedburner migration should be transparent; no action should be required by subscribers; the URL is the same.

LOB support added to PDO_OCI in PHP 5.1 CVS (finally)

[update: corrected information about STRINGIFY_FETCHES]

It's been a looong time coming, but it's finally here. Here's how to insert a BLOB via PDO_OCI:

<?php
   $db = new PDO("oci:", "scott", "tiger");
   $db->beginTransaction(); // Essential!
   $stmt = $db->prepare(
       "INSERT INTO blobtest (id, contenttype, blob) ".
       "VALUES (:id, :type, EMPTY_BLOB()) ".
       "RETURNING blob INTO :blob");
   $stmt->bindParam(':id', $id);
   $stmt->bindParam(':type', $type);
   $stmt->bindParam(':blob', $blob, PDO::PARAM_LOB);
   $type = 'image/gif';
   $id = 1; // generate your own unique id here
   $blob = fopen('/path/to/a/graphic.gif', 'rb');
   $stmt->execute();
   $stmt->commit();
   ?>

This will suck the contents of the graphic.gif up and store it into the newly inserted row. This syntax most closely matches the generic blob insert syntax that I talk about in my PDO presentation, there are two differences that are peculiar to Oracle. The first is the RETURNING blob INTO :blob that's tacked onto the end of the INSERT query. The reason for this is that Oracle stores "LOB Locators" rather than LOB contents in its table rows.

A LOB Locator tells Oracle where it stashed the actual LOB contents without making the table rows overly large, and allows some clever optimizations when manipulating LOBs. You can't just conjure up a LOB Locator though, so you need to insert a brand new empty LOB into a table and then fetch it's locator back out before you can start modifying it. (If you're coming from a mysql background, you can think of the locator as being something like a mysql auto-increment field; you need to insert a row before you find out what the value of the field is.)

Rather than issuing 2 queries just to make an insert, Oracle provides the RETURNING ... INTO syntax as a shortcut; it's equivalent to SELECTing the columns back out again, but it bundled up into a single query, saving the effort of parsing multiple queries and the overhead of multiple network round-trips to get everything where it needs to be.

This means that the :blob parameter is actually an output parameter, even though it smells like an input parameter. There's some intuitive magic at work here; if you bind a stream or a string to a PDO::PARAM_LOB parameter, the PDO_OCI driver will assume that you want to store the contents of that stream-or-string into the LOB that gets returned after the execute. So, that's what it does. Post-execute, all the LOB parameters are checked to see what PHP-space variables were bound, and data is written to the LOBs. This has an important implication; if you're doing this, you'd better have a transaction open, otherwise your new LOBs will be committed as part of the execute--before the PDO_OCI driver can write the data into the LOBs.

So, we can insert just fine. What about binding a LOB for output? Here's how:

<?php
   $db = new PDO("oci:", "scott", "tiger");
   $db->beginTransaction(); // Essential!
   $stmt = $db->prepare(
       "INSERT INTO blobtest (id, contenttype, blob) ".
       "VALUES (:id, :type, EMPTY_BLOB()) ".
       "RETURNING blob INTO :blob");
   $stmt->bindParam(':id', $id);
   $stmt->bindParam(':type', $type);
   $stmt->bindParam(':blob', $blob, PDO::PARAM_LOB);
   $type = 'image/gif';
   $id = 1; // generate your own unique id here
   $blob = null;
   $stmt->execute();
   // now $blob is a stream
   fwrite($blob, "GIF89a");
   ...
   fclose($blob);
   $stmt->commit();
   ?>

OK, this sample is still inserting data into the LOB, but it's doing it by binding the LOB for output, and giving you access to the LOB stream so that you can manually do things with it. The same approach will work if you issue a query that returns an existing read-only LOB. This syntax is closer to the traditional oci8 extension LOB support, except that the LOB is mapped as a PHP stream, so that you can use all the usual PHP streams functions to work with it.

LOBs are also handled for simple SELECTs that return rows with LOB columns. The PDO_OCI driver returns each LOB column as a stream; no data is transferred from that column until you start to read from it:

<?php
    $stmt = $db->prepare('select blob from blobtest where id = ?');
    $stmt->execute(array($id));
    $row = $stmt->fetch();
    var_dump($row);
    var_dump(stream_get_contents($row[0]));
    ?>

this will output something like:

    array(2) {
      ["BLOB"]=>
      resource(7) of type (stream)
      [0]=>
      resource(7) of type (stream)
    }
    string(886) ".....BLOBDATAHERE..."

Notice that I'm using stream_get_contents() to transform the LOB stream into a string. If you're writing a portable application (good luck!) you need to be prepared to handle columns coming back as a stream, even if you didn't explicitly bindColumn and ask for it to be delivered as a LOB. If you're not looking forward to handling that dynamically, you might be interested in setting the STRINGIFY_FETCHES database attribute:

<?php
    $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
    // now ALL non-NULL columns will be converted to strings when fetched
    ?>

This will convert all columns to strings, regardless of their original type, when fetches. This does not include NULL columns. This does NOT translate data being inserted. Use your brain before deploying this setting!

Zend Framework

There's a lot of speculation flying around about the Zend Framework; some positive, some not so positive. I'm getting a little bit sick of hearing people spread misinformation about it; I know that official news on the framework is pretty sparse, and that the speculation is mostly as a result of that lack of information, so I'm going to say a few words to try to improve the situation.

So, why yet-another-framework? Clearly, it's useful to have a standard library of components that you can drop into your applications. Why is Zend getting behind this? One of the major reasons is that, as PHP attracts larger and larger businesses, there is a greater need for such a component library. One big problem for big business is that it's pretty much impossible for them to determine just how "legal" the existing libraries are.

What do I mean by this? When you have an anyone-can-commit-or-submit policy, you have no idea where the newly contributed code has come from. How do you know for sure that it wasn't stolen from someone's place of work, or taken from an application without respecting its license? (eg: "borrowing" some code from a GPL app and shoving it into a BSDish framework, without changing the BSDish code to GPL).

It makes a lot of sense to control the repository and build-in accountability as part of the submission process. By having contributors sign an agreement that forces them to take responsibility for the code they commit, the framework and its users are now insulated from any potential legal recourse that might arise. And because the people committing the code are aware of that liability, they'll take greater pains to ensure that their code is legally allowed to be contributed. The end result is "Clean IP", and is immediately much more appealing to anyone that takes their business seriously.

Of course, you need some kind of accountable body to take care of the paperwork for the submission process, both in terms of processing new contributors and to be there in case of some kind of audit. If you're a business that takes legal matters seriously, are you going to trust a bunch of guys that probably haven't even met each other in real-life to maintain clean IP, or a company backed by other PHP related businesses?

Aside from clean IP, there are also questions of code reliability an stability; is the code any good, is the API going to be subject to wild changes between releases, what kind of testing and QA procedures are in place? Can you trust that they'll be adhered to?

So, there are a lot of business reasons behind the decision to create the Zend Framework, what about technical merit? Contrary to some of the hot air that's been blowing around the blogs, there is code already, and it's actually pretty good. Here's a directory listing from my CVS checkout, to give you a taste of what's already implemented:

   % ls                                                                          
   CVS            ZDBAdapter      ZLog             ZTemplate
   ZActiveRecord  ZException.php  ZPageController  ZUri
   ZController    ZInputFilter    ZSearch

There are plans for AJAX, SMTP, and web services components, among others. As you can probably deduce from the names, the components already implemented include the ActiveRecord pattern, some glue for MVC, flexible logging and templating and a security related input filtering class are also present. ZSearch provides document indexing capabilities, to make it easy to implement custom search engines for arbitrary documents stored in arbitrary storage containers.

One of the goals for the project is to keep every clear and simple to use, without forcing you to adopt the entire framework throughout your application; it doesn't impose itself on your app, and doesn't require any configuration files to deploy and use.

I'm not going to reveal any more about the code than this right now; one of the reasons that the code isn't open at the moment is to keep the initial work manageable and focused--too many cooks spoil the broth, as we they say.

So there were have a bit of a sneak peek and some background on the Zend Framework. It's undergoing active development, with multiple code and documentation commits going in daily. I can't give you any more detail on the schedule, you'll just have to stay tuned.

Upcoming PHP-on-Windows webcasts next week

One of the people that I met at ZendCon was Joe Stagner, who's been using PHP since before he started work at Microsoft. Joe gave a talk entitled "PHP Rocking in the Windows World" which went down quite well. I'm sad to say that I missed it--I got caught up talking to a bunch of people and lost track of time.

Joe is running a series of PHP-on-Windows webcasts next week on MSDN:

MSDN Webcast: Comparing PHP with ASP.NET

MSDN Webcast: Building and Running PHP Applications on Windows

MSDN Webcast: Extending PHP Applications Using Microsoft Technologies

Back from ZendCon

So, I'm back from ZendCon. I was unsure how this business focused conference would turn out, and I'm glad to say that it seemed to go down quite well. There were a lot of "biz" sessions and that made it feel like there wasn't much technical content at the conference proper--but that was compensated for by the technical tutorials that took place on tuesday.

One of the things I really like about conferences is the opportunity to meet people face to face. Aside from the usual PHP conference circuit crowd (you know who you are!) it was good to see some faces that I haven't seen since my last visit to SF (php{con west 2003). It was also good to put faces to names and voices that I'd only previously dealt with over email, telephone or even just through reading RSS feeds.

I did a lot of "networking" at this conference compared to others that I've attended, having had some good, positive discussions with folks from Oracle, IBM, Microsoft and others about what they're doing, what we're doing and some general plans for the future--nothing top secret or earth shattering (that I know of!) just positive :)

I think one of the biggest things to take home from the conference (besides the swag) is the message that big business recognizes PHP as platform for big business. The presence of these big names at the conference not only helps to improve the perception of PHP as an "Enterprise" platform, but also helps to validate the efforts of everyone that has contributed to PHP (usually on a volunteer basis) over the last 10 years--well done to us all!

PDO Slides from ZendCon

(hmm, I could have sworn I posted these the other day; maybe the wifi cut out just as I hit "save")

You can find the slides from the PDO talk here.

While I'm here talking about PDO, I wanted to give you a heads up. PDO 1.0RC2 will move from PDO_XXX style constants to using class based constants like PDO::XXX. The reason for this change is that it will fit in with namespace support in PHP when it is implemented.

Yes, this should have been changed before 1.0RC1: Sorry.

This change has not yet been made to the packages available via PECL, but is present in the PHP 5.1 branch--including PHP 5.1RC3.

[yes, this text is pretty much a rip off an earlier blog entry I made]