Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

file 210 lines (153 sloc) 6.399 kb

Pod, a simple Web Server Interface for PHP [WIP]

Show me the source code!

— You, just now.

No. There is no source code yet. I'm practicing Readme Driven Development here. But don't turn away! I really appreciate your Feedback on this, so please stay, read it and send your feedback to @yuri41 or submit an Issue to the Issue Tracker.

Everything is up for discussion (including the name)!


Pod, the socket for holding the bit in a boring tool.

Wordnik

Pod is a simple interface between the PHP Application and the Web Server. Pod is a port of the Rack Specification, with some things done the "PHP way".


I want to thank Christian Neukirchen for the Rack Specification and the Python Community for PEP 333 (and PEP 3333). These are great examples of very well written Specs and were a big help and inspiration.

Mission

  • Pod aims to provide a simple specification for an easy to implement interface between PHP applications and servers.
  • Provide an interface common to all web frameworks.
  • Provide an interface for middleware components which can be shared between web frameworks.
  • A common library which handles web server inconsistencies via Handlers.

Aside: Why $_SERVER is flawed

The $_SERVER variable has one big flaw: it's entirely up to the server which keys exist and what the values contain.

$_SERVER is an array containing information such as headers, paths, and script locations. The entries in this array are created by the web server. There is no guarantee that every web server will provide any of these; servers may omit some, or provide others not listed here.

http://www.php.net/$_SERVER

Most of $_SERVER is taken from the CGI Specification though, but there ain't any obligatory contract, which specifies what must be there and what values the application can expect.

Benefits for Web Server Authors

  • A well though-out and tried Spec, which is also successful in other languages, like Ruby, Python and Perl.
  • Simple to implement, the environment is a simple PHP array, containing key value pairs.
  • Makes more efficient implementations possible, because the application can be loaded once and then the callback can be used to pass requests to the application.

Benefits for Application Authors

  • Provides consistent request data, independent from the underlying Web Server.
  • Enables framework independent middleware components which can be used to share common components between multiple PHP web applications, for example Routing, Mounting of multiple applications, Session handling and much more.
  • Enables mending of multiple applications without server configuration.

Benefits for Framework Authors

  • Framework authors can focus on whatever features which make their framework special, instead of writing the same dumb workarounds for different web servers over and over again.
  • Common interface to share HTTP components (e.g. Routers) with other frameworks.

Install

Pod is installed via Composer. To install it, add this to your composer.json:

# composer.json
{
    "require": {
        "chh/pod": ">=1.0.0,<2.0.0dev"
    }
}

Then run in your project directory:

# If you don't have composer already:
% wget http://getcomposer.org/composer.phar

# Download into the "vendor/" directory
% php composer.phar install

Usage

Like Rack, Pod distinguishes between two kinds of components:

  • Apps: do the hard stuff.
  • Middleware: Sit in a chain and modify the Pod Environment, before it reaches the Application. Execution stops when a Middleware component returns a response.

Each component in Pod follows a simple interface: the Callback. This means that they can be implemented by:

  • named Functions
  • anonymous Functions
  • Classes implementing __invoke()

Each callback takes exactly one argument (the environment) and returns an array of three elements:

  1. status, HTTP status code as Integer.
  2. headers, Array of header => value pairs.
  3. body, the response body as Array of Strings, Resource or Iterator.

A very minimal application could look like this:

# app.php
<?php

function helloWorldApp(&$env)
{
    return array(200, array(), array("<h1>Hello World</h1>"));
}

To serve this application the traditional way, put this into your index.php:

# index.php
<?php

$pod = Pod\Builder::load("pod_config.php");
# Serves the App as normal PHP app.
$pod->launch();

# pod_config.php
<?php

require_once(__DIR__."/app.php");

$this->run("helloWorldApp");

Pod will then call your app and send your response back as HTTP response.

Middleware components follow the same interface as Applications, the only difference is that they sit in a chain in front of the application.

A simple middleware which overrides the Content-Type with the format in a format parameter could look like this:

# FormatOverride.php
<?php

class FormatOverride
{
    var $formats = array(
        'html' => 'text/html',
        'json' => 'application/json',
        'xml'  => 'application/xml'
    );

    function __invoke(&$env) 
    {
        $query = $env['QUERY_STRING'];
        parse_str($query, $params);

        if ($format = @$params['format'] and isset($this->formats[$format])) {
            $env['HTTP_CONTENT_TYPE'] = $this->formats[$format];
        }
    }
}

Then register it in the chain:

# pod_config.php
<?php

require_once(__DIR__."/FormatOverride.php");

$this->register(new FormatOverride);

Servers

Servers should provide a Handler to interface with applications.

Handlers should implement a run method which takes any Pod callback. The run method should provide the initial environment, invoke the callback and send a HTTP response back to the client.

Something went wrong with that request. Please try again.