PHP Itch to Scratch: Object Notation

Marco Tabini, co-founder of php|architect and Blue Palabora, posed an interesting topic: Is PHP running out of itches to scratch?

I think it’s fair to say that the pace at which PHP core is being developed has slowed down considerably over the past couple of years, while the development of many projects based on it, like programming and application frameworks, has sped up and continues to grow at a fast pace.

He goes on to point out some of the reasons for the slow down of development for the PHP Core. But at the end, he states it ultimately boils down to find a better way to bring features build downstream back upstream.

The risk facing us, as I see it, is not that Drupal, or WordPress, or whoever may decide to fork PHP or abandon it altogether. Rather, the problem is that there is no real way for these projects to provide upstream positive feedback to PHP core.

As I pointed out that the meeting that Cal references (I was the instigator of the discussion), core developers can’t improve PHP if they don’t know what needs improving, and downstream developers are forced to resort to needlessly duplicate functionality that they could instead feed into and pull out of core. This, in turn, would enable the latter to focus on what really makes their projects unique and make the whole PHP ecosystem better in the process.

So I thought I would do my part by first my blogging about a few “itches” I’d love to see scratched. My first itch would be some form of Object Notation for PHP.

JavaScript Object Notation

One of the great features of JavaScript has been it’s Object Notation, which has spread across other platforms in the form of JSON. What makes it so nice is you can quickly pass basic objects in your code in a very OOP fashion. My favorite use is for passing settings to a given function. In the jQuery library, you can do the following:

var url = '/example/ajax/url';
// You can use the short hand $ variable, or you can use the full jQuery variable.
jQuery.ajax(url, { success: function(data){ alert(data); }, cache: true });

Now, if you look at the ajax function documentation, you will see it has as of this posting 33 different options. All of them are defaulted one way or another, and so you only need to pass exactly what you’d like. On the function declaration side, it has something similar to this:

jQuery.ajax = function(url, settings)
{
    var defaults = { cached: false, success: null, error: null /* ... declare / build defaults */ };
    settings.extend(defaults);

    /* Continue Execution */
}

What this allows is as more settings are required, the default can be set and code already implementing this function will continue to work normally. So a developer can easily override a setting, and pass only the parameters they need, with few keystrokes.

The Current PHP Way

With PHP, you only really have two options: first, is to use many arguments, and second, use an array. While they can get the job done, it isn’t as graceful.

Function / Method Arguments

If you use arguments, you might have a basic function or method that starts off with three arguments:

class Telephone
{
    public function CallPerson($name, $number, $onAnswer)
    {
        /* ... continue execution ... */
    }
}

However, lets say as the project moves on, more methods are added to give more granular control over “calling a person.”

class Telephone
{
    public function CallPerson($name, $number, $onAnswer, $redial = false, $redailAttempts = 3, $onBusySignal = null, $logConversation = null, $seeWhatIMean = 'I hope so.')
    {
        /* ... continue execution ... */
    }
}

It can become very difficult to manage. Also, if I want to set an anonymous function for $onBusySignal, but keep the defaults for $redial and $redialAttempts, I have to go to the declaration and see what their defaults are. Later, if I want to change the defaults, I have to go back through my code and see where I had to pass extra default arguments just to set an argument that was further down the line.

Using Arrays for Settings

While this is a much better approach for functions that will had many settings, it isn’t as clean or nice to implement. Using the same example of our class Telephone and CallPerson method:

class Telephone
{
    public function CallPerson($name, $number, $settings)
    {
        $defaults = array("onAnswer" => null, "redial" => false, "redialAttempts" => 3, "onBusySignal" => null, "logConversation" => null);
        $settings = array_merge($defaults, $settings);
        
        /* ... continue execution ... */
        
        if($settings["redial"] == true)
        {
            /* do something special */
        }

        /* ... continue execution ... */
    }
}

Now, one issue you’ll run into is using Arrays is more keystrokes. Not only do you have the 6 key strokes for declaring “array(” but each key is wrapped in a set of quotes, the “=>” linking between key and value is two key strokes instead of 1 for “:” in JavaScript. While others might not find it as big of a deal, it is amazing how much of an impact that can make on someone. Especially if this method will be used commonly among the application. A developer might put off implementing an array for settings and use arguments for more and more granular, until they end up with a situation like our first example.

You run into the same problems while passing settings to the method:

$telephone = new Telephone();
$telephone->CallPerson('Marco', '437-555-3920', array("redial" => true
    , "redialAttempts" => 10
    , "onBusySignal" = function($tel){ /* code to spam Marco with twitter messages to get off the phone */}));

Also, another thing with Arrays in PHP they do not pass by reference, but by value. So if you had some code to check validity of your settings and make changes, it won’t pass them back unless you explicitly pass by reference.

Proposed PHP Object Notation Example

Now, what I would love to see is the following:

$telephone = new Telephone();
$telephone->CallPerson('Marco', '437-555-3920', { redial: true, redialAttempts: 10, onBusySignal: function(){ /* code */} });

Now, to keep with conventions, I would think it a good option to use “=>” instead of “:”, since “:” isn’t used anywhere else in PHP in this fashion. But with the prevalence of JSON, I think people would understand “:” easily knowing they were dealing with object notation.

I would expect the code above to perform the same as if I did the following:

$settings = new stdClass();
$settings->redial = true;
$settings->redialAttempts = 10;
$settings->onBusySignal = function(tel) { /* code here */ };
$telephone = new Telephone();
$telephone->CallPerson('Marco', '437-555-3920', $settings);

Once again, I realize it is possible to achieve the same effect by either using an array or an object like above. My biggest reason for my suggestion is it is convient for the developer. With the new anonymous (lambda) functions in PHP 5.3, I think this would be another nice thing to open up patterns in programming that would just be easier to use.

My two cents on an itch I’d like to see scratched. As always, there might be things I’m overlooking that either a) provide functionality a lot closer to what I want that I know about, or b) challenges into implementing an object notation into PHP. But I do believe if it were possible, it would be very convenient for developers using PHP. So let me know your thoughts.

Justin is currently the Director of Development for the Deseret News. He is active in the Utah Open Source community. He is an advisory member of the Utah Open Source Foundation, and helps with the anual Utah Open Source Conference. He primarily focuses on PHP, MySQL, Redis, HTML, CSS, jQuery, and JavaScript. When he gets the time, he enjoys to play jazz piano. Read More

Tagged with: , ,
Posted in Programming