I’ve been reading up on node.js a bit recently. And I’ve been thinking on the problem of AJAX with regard to PHP and all her frameworks. Before I was introduced to node.js I’d already taken some steps to try to address this problem in my ongoing framework project (which I never seem to get done), but studying node really opened my eyes some to what was going on because, for the most part, node.js is essentially what I’m gunning to build in PHP. But it runs counter to not only the assumptions of all the major frameworks I’m familiar with, but also PHP itself.
PHP assumes that the browser is going to request a document. This core assumption is why PHP is an embedded language at heart. You take an HTML document, and inject some content into it with a PHP script. Over time the language has evolved, the HTML is shunted into template languages, and MVC frameworks are layered into the language.
The problem with AJAX is that it allows the browser to ask for a piece of a document - or worse even no document at all. PHP just isn’t set up for this and neither is any framework I know of (even my own). While I started moving in this direction it wasn’t until a few days ago that I found myself staring in the face and recognizing the core loop code of Gazelle/PNL for what it was, and event dispatch loop.
And the problem will get worse. Web socket connections are something PHP and especially it’s frameworks are wholly not ready to deal with. Part of this is overhead - it takes a bit of time to load in, parse and set up the framework on each request, work that is duplicated on every request.
The Event Paradigm
PHP is (or at least can be written in the style of ) an object oriented programming language. Most such languages however are event driven. PHP, not so much. There are events, and PHP has the tools to implement the Subject/Observer pattern, but the language is not event driven. Gazelle/PNL was originally scoped to be an event driven MVC, but I’m not beginning to realize that the core mechanism that I have for it - it’s event dispatch - would be better served as a PHP extension written in C for best performance - something beyond my keen to do. I can emulate it in PHP, but long term it needs to exist in a manner that it stay resident and sleep between browser requests. The shutdown/start up loop is CPU waste and a scaling constraint for both the language and programs on it.
I’m a bit lost now. I’m going to continue looking at node.js and see what I can learn. But I’ll admit I’m lost and much of my prior structral work isn’t going to fly. I’m also debating whether or not it would be more effecient to just use node.js rather than imitate it in PHP.
Thoughts?
Actually - this might help.
/**
* Start and parse the queue.
*/
public function parse( $url = '/' ) {
$this->parseURL($url);
// Let the heartbeat commence.
do {
// Get an event.
$event = array_shift($this->queue);
try {
// If the event is a page, assign it and clear the queue and responses.
if ( $event instanceof Page ) {
$this->startPage($event);
}
$result = $event( $this->page );
} catch ( Exception $e ) { // Uh oh - error page time.
/*
* If the page is an error page, we need to elevate to fatal
* exception or run the risk of getting caught in a loop.
*/
if ($this->page instanceof ErrorPage ) {
throw new FatalException($e->getMessage);
} else {
/*
* Resolve gracefully. Note that these errors can be cause
* by user interaction - 404 not found pages pass through
* this mechanism.
*/
$ep = $this->dataDispatcher->getSetting('core', 'errorPage');
$this->startPage (
new $ep( $e, $event, $this )
);
}
}
// An event may return multiple events, especially pages.
if (is_array($result)) {
foreach ( $result as $r ) {
$this->route($r);
}
} else { // Handle just the one result.
$this->route($result);
}
} while( count($this->queue) > 0);
/*
* Now as our last step we give the page to the responseDispatcher
* for the handling of the reply.
*/
$this->responseDispatcher->respond();
}
My whole framework is built around this function, which loops over an event stack created by parsing the URL information provided by the browser. When the events all resolve, the response gets issued. But couldn’t this be btter placed lower down?