Ajax in the Stratos Framework

by Joshua Carnett

The Stratos javascript features are built upon the Dojo toolkit, which comes packaged with the framework. Using either the Stratos class or Dojo is as easy as importing the Stratos javascript into your site.

Import the Stratos Javascript

To enable the Stratos javascript features, simply place the following line into the HEAD of your HTML document:

<?php Stratos::executeView('Stratos:javascript.php'); ?>

This will import the Stratos class and the Dojo toolkit.

The Stratos Class

Because Dojo is such an extensive toolkit, the Stratos class provides only a minimal set of functionality to integrate Stratos and the Ajax features in Dojo. The Stratos class provides the following methods:

updateHTML

Stratos.updateHTML( id, action, args, beginCallback, endCallback, view )

callback

Stratos.callback( actions, args, beginCallback, endCallback )

printFlashes

Stratos.printFlashes( containerId, flashes )

callFunc

Stratos.callFunc( func, args )

The Basics

One of the most common things people do with Ajax is make a request and simply update the contents of an element in the page by setting its innerHTML property to the output of the request. This is extremely simple to do with Stratos with one line of javascript:

Stratos.updateHTML('elementIdToUpdate', 'Example/doSomething');

This call would request the Example/doSomething action on the server and place its view output into the innerHTML of the DOM element with the ID elementIdToUpdate. Keep in mind that when using Stratos.updateHTML(), your site's master view is left out.

A Quick Example

Ok, so that one line of code is kind of boring. Let's create an MD5 summer using Ajax so we can see how everything actually works.

First we'll start with our action:

actions/MD5Controller.php

<?php

class MD5Controller
{
    function index() {}
    
    function sum( $data = '' )
    {
        return array(
            'data' => $data,
            'md5' => md5($data)
        );
    }
}

?>

Now for the views:

views/MD5Controller.index.php

<form action="" method="post">
    <textarea type="text" id="data" name="data"></textarea>
    <input type="button" id="submit" value="Submit"
        onclick="Stratos.updateHTML('output', 'MD5/sum', this.form);"/>
    <hr/>
    <div id="output"></div>
</form>

views/MD5Controller.sum.php

<b>MD5 of '<?=$data ?>':</b> <?=$md5?>

Woah, that's crazy. Here's the master view:

views/overall-layout.php

<html>
    <head>
        <title>Ajax MD5 Summer</title>
        <?php Stratos::executeView('Stratos:javascript.php'); ?>
    </head>
    <body>
        <h1>Ajax MD5 Summer</h1>
        
        <?php Stratos::executeView(); ?>
    </body>
</html>

That's all it takes. When the button is clicked, Stratos will make a request to the MD5/sum action passing in the value of the textarea and putting the view output (without the master view) into the output DIV.

Our Example Revised

So maybe it's just me, but it seems kind of strange that we had to create two separate actions (one of which is empty) and the MD5Controller.sum.php view. Yeah, it works perfectly and this approach is great in lots of cases, but we can do a bit better using Stratos.callback().

Let's start by stripping down our action:

actions/MD5Controller.php

<?php

class MD5Controller
{
    function index( $data = '' )
    {
        return array(
            'data' => $data,
            'md5' => md5($data)
        );
    }
}

?>

I'm pretty sure we can't reduce that any further. Now for the view...

We won't need the MD5Controller.sum.php view anymore, so let's make some changes to our MD5Controller.index.php view:

views/MD5Controller.index.php

<form action="" method="post">
    <textarea type="text" id="data" name="data"></textarea>
    <input type="button" id="submit" value="Submit"
        onclick="Stratos.callback('MD5', this.form, null,
            function(data)
            {
                dojo.byId('output').innerHTML = data['result']['md5'];
            }
        );"/>
</form>

<hr/>
<div id="output"></div>

So the important line in the view is the one with Stratos.callback(), which basically says, "Hit the MD5 action on the server, call nothing when the request begins (that's the null), and process the return value with the given function. Using the inline function was just my personal preference -- you can set up the callback function however you want. Note that when using Stratos.callback() your views are not executed, but instead the actual return value of the method is passed back to the browser.

Stratos/Request

Now I know your little sister is standing next to you being all amazed at how your action method's return value was magically JSON encoded and sent over to the browser. Well I can barely even pull off card tricks, so you won't see much magic here. If you check out the code in the Stratos javascript class, you'll see that it doesn't call your action at all, but instead calls Stratos/Request. This is an action built into Stratos that provides REST web services for other actions. No kidding! Web services should never have to be manually coded (IMHO), and Stratos/Request certainly seems to make that a reality.

Stratos/Request provides the following methods:

getOutput

Returns the view output. By default, the master view is not included.

getString

Returns the printed return value of the action.

getWDDX

Returns the return value of the action encoded as WDDX. As of version 0.92, if the PHP setup on the server is not able to encode to WDDX natively, Stratos will attempt to use the PEAR XML_Wddx package. If neither the WDDX extension or the PEAR XML_Wddx package are available, an empty WDDX packet is returned.

getPHPExport

Returns the result of passing the action return value through PHP's var_export() function.

getPHPSerialized

Returns the result of passing the action return value through PHP's serialize() function.

getJSON

Returns the action return value encoded as JSON. For performance, this will use the json_encode() function if it is available. If it is not, a pure PHP JSON encoder will be used.

At the moment, there is no SOAP or XML-RPC interface. This is mostly because I'm not a big fan of either of these technologies; however, for those of you who do like them, they are coming down the pipeline.

Copyright © 2006-2007 Sephira Software, LLC. Be sure to check out Mashfest, a music festival site that we are working on.