3
May
3

NodeJS as a PHP Frontend

I had a conversation the other day with a friend of mine who is a PHP programmer about the possibility of using JavaScript (specifically, Node) as a routing front end for PHP. Recalling that Node has an API for child processes, I looked into it.

It turns out, this is extremely easy:


var http = require('http'),
    spawn = require('child_process').spawn;
http.createServer(function (req, res) {
    var php = spawn('php', ['foobar.php']);
    php.stdout.on('data', function (data) {
        res.writeHead(200, {'Content-Type' : 'text/html'});
        res.end(data);
    });
    php.stderr.on('data', function (data) {
        res.writeHead(500, {'Content-Type' : 'text/plain'});
        res.end(data);
    });
}).listen(8080, '127.0.0.1');

If you wanted to do URL routing, you could use a library like Express:


var express = require('express'),
    spawn = require('child_process').spawn;
function route(file) {
    return function (req, res) {
        var php = spawn('php', [file]);
        php.stdout.on('data', function (data) {
            res.writeHead(200, {'Content-Type' : 'text/html'});
            res.end(data);
        });
        php.stderr.on('data', function (data) {
            res.writeHead(500, {'Content-Type' : 'text/plain'});
            res.end(data);
        });
    };
}
var app = express.createServer();
app.get('/', route('index.php'));
app.get('/users/', route('users.php'));
app.listen(8080);

Not only can this let you use Node’s speed and the strengths of JavaScript to route URL’s for PHP, but it can be used with any language (for example, instead of running the PHP interpreter, you could run the Python interpreter). Node can easily prove itself as a routing front end for web applications, and is very well suited to create customized load balancers.

I’m toying around with a pair of libraries to spawn PHP processes from Node, using a JSON document as arguments to the PHP application, and a PHP library to handle incoming arguments. Ultimately, however, this is so trivial that it can be implemented easily by anyone.

Of course, there are drawbacks. While this would be a much more efficient and flexible method of URL routing for PHP applications, the memory usage would be intense. Many times that of a PHP application running in Apache or another traditional web server. While I haven’t looked into enough, it’s likely that this could prove to be a bottleneck that would prevent a method like this from scaling for large applications without a complex, multi-server, load-balanced server infrastructure. Although, Node lends itself rather well to that!

Nevertheless, this is an interesting experiment, it’ll be fun to see what comes of it.

Enjoyed reading this post?
Subscribe to the RSS feed and have all new posts delivered straight to you.
  • http://profiles.google.com/joshuaswift Joshua Swift

    Very interesting. Keep up the good work.

  • Chad Dore

    Do you know what might cause php to stop streaming output as soon as it hits the tag?  Using node it will output standard html pages just fine but chokes on the php tag for some reason.  If I pass the page to php directly at the command line, bypassing node, it processes the whole page.

  • http://twitter.com/coreyschram Corey Schram

    When you do res.end(data) in the on(‘data’, …) then you’re ending the response from Node. When PHP hits the tag it’ll stop outputting a response to process the PHP. Because of that, you’ll do res.end(…) with just the first portion of the output.

    I found this out later on, after making this post. You’ll need to wait until the ‘exit’ event is thrown for the process, then you can can call res.end(“”); or similar. Then for the ‘data’ event you’ll just use res.write(data).

Celadon theme by the Themes Boutique

Page optimized by WP Minify WordPress Plugin