Blog Posts

The light has not set on PHP

I ran across a blog post entitled "Why the Light Has Gone Out on LAMP" earlier today, and felt compelled to respond.

First, a rant: somehow, this article got posted on Slashdot. I've never heard of the guy who posted it, and some quick googling shows that he's a pythoner. He's simply fueling the language wars, and the slashdot post opened up a huge debate that need not have occurred. I think it was irresponsible of the Slashdot editors to post it.

In the post, the author makes an analogy of using PHP + MySQL as the equivalent of using BASIC, and then uses a quote that claims BASIC "has become the leading cause of brain-damage in proto-hackers."

I'm sorry, but using a language doesn't cause brain damage. And there are many levels to programming. And using Python, Ruby, C, C++, Java, etc., does not automatically make you a better programmer than those using one of "those other languages". You can write crap code in any language. You can also write great code in just about any language.

Programming takes practice; programming well takes a lot of practice. You get better at it by learning more about programming practices, and applying them to your language. Part of programming is also learning when a particular language is suited to a task, and when it isn't. Python works for the web, but it's not particularly suited to it; similarly, you can write web servers in PHP, but that doesn't mean you should.

Stop the language wars already! Stop writing incendiary pieces about a language you don't use regularly or never gained particular proficiency in, and code already!

Continue reading...

Cgiapp2 Tutorial 1: Switch Template Plugins at Will

This is the first in a short series of tutorials showcasing some of the new features of Cgiapp2. In this tutorial, you will see how easy it is to switch template engines in Cgiapp2-based applications.

Continue reading...

Phly Darcs Repository online

A darcs repository browser is now online for the Phly channel.

If you're not familiar with darcs, it's a revision control system, similar to GNU Arch and git; changes are kept as patch sets, and repositories are branched simply by checking them out. This makes darcs repositories very flexible, and incredibly easy to implement. Static binaries are available for most systems, which makes it easy to install on systems to which you have no administrator rights.

A perl CGI script is shipped with darcs, and provides a web-based repository viewer. It utilizes darcs' --xml-output switch to create XML, which is then transformed using XSLT. However, there are some issues with the script; it is somewhat difficult to customize, and makes many assumptions about your system (location of configuration files, repositories, etc.). To make it more flexible, I ported it to PHP, using Cgiapp2 and its XSLT template plugin and Phly_Config.

I have released this PHP darcs repository browser as Phly_Darcs, which contains both a Model and Controller, as well as example XSLT view templates. It is currently in beta as I'm still developing PHPUnit2 tests for some of the model functionality, as well as debating the ability to add write capabilities (to authenticated users only, of course).

Update: fixed links to internal pages to use absolute urls.

Continue reading...

Cgiapp2 2.0.0 FINAL Released

After several months of testing and some additional work, I've finally released the first stable version of Cgiapp2.

It is available at both the Cgiapp site as well as via my Phly PEAR channel.

There were a ton of changes while creating the Cgiapp2 branch. From the release notes:

The 2.x series of Cgiapp completes a PHP5 port of Cgiapp2. PHP5 compatibility changes include visibility operators for all properties and methods, declaration of many methods as static and/or final, and the use of exceptions for catching run mode errors. Most notably, though, is the fact that Cgiapp2 is now an abstract class, with one abstract method, setup(); this enforces the fact that you must subclass Cgiapp2 in order to create your application.

New features include:

  • Callback hook system. Cgiapp2 is now an observer subject, and has hooks at several locations within the application. Additionally, it provides a method for registering new hooks in your applications. The callback hook system replaces the plugin system introduced in Cgiapp 1.7.0.

  • Template engines are now relegated to plugin classes, and should implement the Cgiapp2_Plugin_Template_Interface. Shipped template engines include Smarty, Savant2, Savant3, and XSLT.

  • Improved and more extensive error handling, which has been expanded to exceptions as well. Cgiapp2_Exception and Cgiapp2_Error are both observable subjects, with interface classes for implementing observers. This allows the developer to tie into exceptions and errors and perform actions when triggered (Log and Mail observers are implemented for each).

  • Cgiapp2_FrontController class. This is a simple front controller that dispatches to public static methods in registered classes. Included is a 'page' controller for handling static pages.

I have included migration notes, for those migrating from the 1.x series of Cgiapp; there is very little that you need to do, but some PHP5 changes necessitate some compatability breakages, and the new callback hook architecture and the ability to separate the template engines into plugins introduced some slight changes as well.

In testing the release, I have been writing some apps that take advantage of some of the new features, and I will be writing some tutorials in the coming weeks.

Continue reading...

Always check the version before release

Last week, I had someone bring to my attention that the SPL's Countable interface was actually first released in PHP 5.1.0… which means I needed to update the PHP dependency on Phly_Hash. I also needed to do so on Phly_Config as it depends on Phly_Hash. I released 1.1.1 versions of each yesterday; the only change in each is the PHP version dependency.

Continue reading...

Phly_Struct? no, Phly_Hash...

After some discussion with Paul and Mike, I was convinced that 'Struct' was a bad name for Phly_Struct; structs are rarely if ever iterable, and one key feature of Phly_Struct is its iterable nature.

The question is: what to name it? Associative arrays go by a variety of names in different languages. In Perl, they're 'hashes'; Ruby and Javascript, 'collections'; Python, 'dictionaries'. I ruled out Phly_Dictionary immediately, as (a) I don't want it to be confused with online dictionaries, and (b), it's too long. The term 'Collection' also feels too long (although I write things like Cgiapp2_ErrorException_Observer_Interface, so I don't know why length should be such an issue), as well as unfamiliar to many PHP developers. Hash can imply cryptographic algorithms, but, overall, is short and used often enough in PHP circles that it makes sense to me.

So, I've renamed Phly_Struct to Phly_Hash, and updated Phly_Config to use the new package as its dependency. In addition, I've had it implement Countable, so you can do things like:

$idxCount = count($struct);

Go to the channel page for instructions on adding Phly to your PEAR channels list, and grab the new package with pear install -a phly/Phly_Hash, or pear upgrade -a phly/Phly_Config.

Continue reading...

Introducing Phly_Struct and Phly_Config

I often find myself needing a configuration module of some sort — for storing application parameters, bootstrapping, template variables, what have you. I typically will either:

  1. Create a PHP file that creates and returns an array, and suck that in via include, or
  2. Create an INI file and suck it in via parse_ini_file, or
  3. Create an XML file and suck it in via SimpleXML.

The first method gives great flexibility of structure and types, but isn't portable to other languages (well, not easily; you could turn it into JSON, or serialize it, etc). The second method (INI files) is handy because the syntax is so concise, and can translate to other projects in other languages easily if necessary; however, you can only easily go two levels deep (using [sections] in the file). The third method is very portable, and allows nested structures — but doesn't allow usage of many specific PHP types.

I find, however, that each has their place. The problem, however, is: once I bring them into my project, how can I access them? Better yet, would there be a way to bring in configurations of many types and still access them all in the same way?

Not happy with solutions out there, I did the only logical thing: I reinvented the wheel, and added some new tread of my own.

Continue reading...

mbstring comes to the rescue

I've been working with SimpleXML a fair amount lately, and have run into an issue a number of times with character encodings. Basically, if a string has a mixture of UTF-8 and non-UTF-8 characters, SimpleXML barfs, claiming the "String could not be parsed as XML."

I tried a number of solutions, hoping actually to automate it via mbstring INI settings; these schemes all failed. iconv didn't work properly. The only thing that did work was to convert the encoding to latin1 — but this wreaked havoc with actual UTF-8 characters.

Then, through a series of trial-and-error, all-or-nothing shots, I stumbled on a simple solution. Basically, I needed to take two steps:

  • Detect the current encoding of the string
  • Convert that encoding to UTF-8

which is accomplished with:

$enc = mb_detect_encoding($xml);
$xml = mb_convert_encoding($xml, 'UTF-8', $enc);

The conversion is performed even if the detected encoding is UTF-8; the conversion ensures that all characters in the string are properly encoded when done.

It's a non-intuitive solution, but it works! QED.

Continue reading...

PHP Library Channel

I've been working on Cgiapp in the past few months, in particular to introduce one possibility for a Front Controller class. To test out ideas, I've decided to port areas of my personal site to Cgiapp2 using the Front Controller. Being the programmer I am, I quickly ran into some areas where I needed some reusable code — principally for authentication and input handling.

I've been exposed to a ton of good code via PEAR, Solar, eZ components, and Zend Framework. However, I have several criteria I need met:

  • I want PHP5 code. I'm coding in PHP5, I should be able to use PHP5 libraries, not PHP4 libraries that work in PHP5 but don't take advantage of any of its features.
  • I prefer few dependencies, particularly lock-in with existing frameworks. If I want to swap out a storage container from one library and use one from another, I should be free to do so without having to write wrappers so they'll fit with the framework I've chosen. Flexibility is key.
  • Stable API. I don't want to have to change my code every few weeks or months until the code is stable.
  • I should be able to understand the internals quickly.

So what did I choose? To reinvent the wheel, of course!

To that end, I've opened a new PEAR channel that I'm calling PHLY, the PHp LibrarY, named after my blog. The name implies soaring, freedom, and perhaps a little silliness.

It is designed with the following intentions:

  • Loosely coupled; dependencies should be few, and no base class should be necessary.
  • Extendible; all classes should be easily extendible. This may be via observers, interfaces, adapters, etc. The base class should solve 80% of usage, and allow extensions to the class to fill in the remainder.
  • Designed for PHP5 and up; all classes should make use of PHP5's features.
  • Documented; all classes should minimally have excellent API-level documentation, with use cases in the class docblock.
  • Tested; all classes should have unit tests accompanying them.
  • Open source and commercial friendly; all classes should use a commercial-friendly open source license. The BSD license is one such example.

Please feel free to use this code however you will. Comments, feedback, and submissions are always welcome.

Continue reading...

Cgiapp 1.9.0 released

I released Cgiapp 1.9.0 into the wild last night. The main difference between 1.8.0 and 1.9.0 is that I completely removed the plugin system. I hadn't had any users reporting that they were using it, and, in point of fact, the overloading mechanism I was using was causing some obscure issues, particularly in the behaviour of cgiapp_postrun().

As usual, you can find more information and links to downloads at the Cgiapp site.

Continue reading...