Seagull is a PHP framework that is gaining popularity. One thing that it is lacking is AJAX support, but you can hack something together by going through the source files. Note that this should be fixed in the future because Seagull is being made more flexible, and will be able to support different output formats automatically.
I used the Rico (or OpenRico) AJAX Javascript library to handle all of the hard work, but the backend was lacking XML (or whatever arbitrary format) output. I wanted to stay within the framework for the output, because Seagull is handling things like user login, sessions, and permissions. If you don’t need this, just write a PHP script that outputs XML. 
Normally when you make a custom class for Seagull, you extend the SGL_Manager class. We don’t want to this, because the data would then be passed to the Flexy template which is expecting HTML, and it’s a big mess.
Instead, we want to create functions that simulate how the SGL_Manager class works, in our own custom class.
So the functions we need are:
- Constructor
- validate($req, &$input)
- _action((&$input, &$output)
- process(&$input, &$output)
- display($input, $output)
The constructor sets up the variables in the class. The _aActionsMapping variable must be set up here to dispatch the action to the correct page. If this doesn’t make sense, read up on creating custom Seagull modules.
Validate is required to process the page. It also sets up any variables that were POSTed as form values, or in the URL.
Your _action function is where things get done. Make sure you set the content type: header(’Content-type: text/xml’);. The data is output here with an ‘echo’ statement. Remember to format your XML properly. Firefox is great for debugging at this point because it will barf on bad XML.
The process function is copied from the SGL_Manager class but modified so that it doesn’t go through flexy:
function process(&$input, &$output)
{
SGL::logMessage(null, PEAR_LOG_DEBUG);
$conf = & $GLOBALS['_SGL']['CONF'];
$className = get_class($this);
// don’t perform checks if authentication is disabled in debug
if ($conf['debug']['authenticationEnabled']) {
// setup classwide perm
$classPerm = @constant(’SGL_PERMS_’ . strtoupper($className));
// if user has no class perms check for each action
if (! SGL_HTTP_Session::hasPerms($classPerm)) {
// …and if linked methods to be called are allowed
foreach ($this->_aActionsMapping[$input->action] as $methodName) {
// allow redirects without perms
if ($methodName == ‘redirectToDefault’) {
continue;
}
$methodName = ‘_’ . $methodName;
// build relevant perms constant
$perm = @constant(’SGL_PERMS_’ . strtoupper($className . $methodName));
// redirect if user doesn’t have method specific or classwide perms
if (! SGL_HTTP_Session::hasPerms($perm)) {
SGL::raiseMsg(’you do not have perms’);
SGL::logMessage(’You do not have the required perms for ‘ .
$className . ‘::’ .$methodName, PEAR_LOG_NOTICE);
// make sure no infinite redirections
$lastRedirected = SGL_HTTP_Session::get(’redirected’);
$now = time();
SGL_HTTP_Session::set(’redirected’, $now);
if ($now - $lastRedirected < 2) {
PEAR::raiseError('infinite loop detected, clear cookies and check perms',
SGL_ERROR_RECURSION, PEAR_ERROR_DIE);
}
// get default params for logout page
$aParams = $this->getDefaultPageParams();
SGL_HTTP::redirect($aParams);
}
}
}
}
// all tests passed, execute relevant method
foreach ($this->_aActionsMapping[$input->action] as $methodName) {
$methodName = ‘_’.$methodName;
$this->$methodName($input, $output);
}
}
display is an empty function since we already did the displaying though the action function.
At this point, you will be able to point your browser to your custom module’s URL and get an XML page. After that, make sure your Rico code is pointing to this URL and you should see it show up in your page!