nphp


Installation and basics

Structure

Nphp applications are usually started in index.php file, which acts as main entry point for each request. When deploying the projects it's best if you rewrite all incoming requests to this file. It makes urls human readable and hides technology used.

Only file that has to be imported is nphp.php - it takes care of importing everything else. In case of installation with composer you only have to require vendor/autoload.php for all your libraries installed with it.

Application's entry point requires only instance of Nphp_Application or class inherited from it. Method start() has to be called on that object. You can find out more about Nphp_Application objects in next section.


Response/request lifecycle

When Nphp_Application's start() method is called, it tries to match requests's URL with regular expressions found in routes array. Upon match, new object is constructed from class that is mapped from matched URL. This object has to implement Nphp_ControllerAbstract abstract class. Application object then calls method that corresponds to HTTP request's method - for example: if browser requesed page with GET method, get() will be called. Request, that is of Nphp_Request class, is passed as only argument to that method. Method has to return either string or Nphp_Response object. This process is also shown on flowchart below.



mod_rewrite and rewrite rules

As written before, index.php is main entry point for applications, so it makes most sense if all requests are rewritten to pass through it. It makes URLs easily readable. This is possible with mod_rewrite on Apache and similar rewrite tools on other HTTP servers. Of course it shouldn't be forgotten to expose folder with static files. Below is example of such configuration for Apache, it can be either put in .htaccess file to be stored with full project or in virtual hosts configuration.

RewriteEngine On

RewriteRule ^static/.+\.(jpg|gif|png|ico|css|js)$ - [L]
RewriteRule ^(.*)$ index.php [QSA,L]

Application object

Properties

Different properties of Nphp_Application object allow various settings for application, from turning debugging on and off to setting custom error pages. Most of the properties can be also set with similarly named methods.

List of all properties:

routes
array, maps regular expressions to controller classes
request
Nphp_Request, contains all request data needed in controllers
debug
boolean, default FALSE, if set to TRUE, debugging page will be displayed instead of error page and correct HTTP response code
prefix
string, prefix that will be automatically added to all routes if application is not located directly on domain or subdomain
For example: "/prefix" to match requests on http://example.com/prefix/*
error404
Nphp_Response, response that is returned when error 404 is encountered, only when debug is set to FALSE
By default, instance of Nphp_Response404 is returned, it accepts string when creating, which is returned content, HTTP response code is set to 404. Feel free to extend or reuse same class for your custom error pages.
error500
Nphp_Response, response that is returned by controller when internal server error occurs, same as error404, only when debug is set to FALSE
By default, instance of Nphp_Response500 is returned, it accepts string when creating, which is returned content, HTTP response code is set to 500. Feel free to extend or reuse same class for your custom error pages.
disableDebugToolbar
boolean, disables debug toolbar on pages, all output will be display on rendered pages, default PHP behavior, more in debugging
startRequestTime
float, Unix time when request started, used to calculate load time on debug toolbar

Methods

For the most part public methods have same functionallity as properties.

List of all methods:

__construct ()
constructor, sets up defaults for properties and sets up request object
setRoutes ( array=[] )
sets up routes array, that maps regular expressions to controller classes
setDebug ( boolean=FALSE )
sets debug property, if set to TRUE, debugging page will be displayed instead of error page and correct HTTP response code
setPrefix ( string="" )
sets prefix property, prefix that will be automatically added to all routes if application is not located directly on domain or subdomain
For example: "/prefix" to match requests on http://example.com/prefix/*
bootstrap ( Nphp_Request )
performes additional actions needed by each controller, gets executed right before controller's method (get, post, ...) is called. It can return either nothing or Nphp_Response object (which becomes available in controllers as response property of request object)
start ()
has to be called in application's entry point file (most commonly index.php), actually starts request/response cycle, calls bootstrap method, matches URL with routes, creates controller object, calls correct method, handles errors and returns error responses if needed, sets HTTP headers, adds debug toolbar to pages if enabled. It also calls autoload($className) method, which can be added to only load controller classes needed by application when routing is done

Request object

Request object, which is instance of Nphp_Request, gets automatically passed to controller methods. It holds data of incoming request, such as URL, HTTP method, sent form data, cookies data, etc. Most of properties and methods are just aliases of built-in PHP objects and methods, they are just conveniently available in OOP manner.

Full list of properties and methods available on request objests:

url
string, path part of the URL that was requested
method
string, HTTP method of request
response
Nphp_Response, default response object that will be used for server's response, it's used for setting response headers (content, code, cookies, ...)
args
array, array of arguments from regular expression matches in routes
For example if you have '^/edit/(?P<user>\w+)/(\d+)/$' => 'EditUserController' in your routes and you access /edit/testuser/7/, args will look like:
Array
(
["user"] => "testuser"
[1] => "testuser"
[2] => 7
)
cookies
array, array of cookies, alias of $_COOKIES
files
array, array of uploaded files, alias of $_FILES
post
array, array of POST variables, alias of $_POST
get
array, array of GET variables, alias of $_GET
request
array, array of all request variables, combined POST, GET and COOKIE variables, alias of $_REQUEST
session
array, array of session variables, alias of $_SESSION
is_xhr
boolean, set to TRUE if X-Requested-With header is set to "XMLHttpRequest", supported by modern JavaScript libraries
setSessionValue ( key=Object, value=Object )
sets value of PHP session variable, shortcut for $_SESSION[key] = value;
getSessionValue ( key=Object )
returns value of PHP session variable, same as $value = $_SESSION[key];
removeSessionValue ( key=Object )
unsets PHP session variable
removeSessionValue ( key=Object )
boolean, returns TRUE if PHP session variable (key in session array) exists
addMessage ( message=Object )
adds flash message to current session, more info available here
getMessages ()
array, gets and deletes all flash messages from current session, more info available here

Extending application

Default application class is enough for small projects, but slightly bigger projects usually need more common objects needed in each request, that have to be available in controllers. One such example is database connection and another initialization of templating engine. Best option and most object oriented approach is subclassing Nphp_Application class and extending it for your own needs.

You're free to overwrite application's constructor, but be sure you call parent's __construct method.

Most useful method for setting up everything is bootstrap, which is called every time just before controller's method is called. It gets passed one parameter - which is default request object. It can either return nothing or your own response that has to be Nphp_Response object. It will be used further on in each controller method call.

Another useful method which you can use is autoload. It gets called when URL path is matched to routing array and match is found. Controller's class name is then passed to it as a string and that can help you load appropriate class. It can return string with new name of class to import.

Example of such extended class and its usage:

class MyApplication extends Nphp_Application {

    public function __construct() {
        parent::__construct();
        // additional constructor code
    }

    public function __destruct() {
        // useful for closing database connections, file references, etc.
    }

    public function bootstrap($request) {
        $request->newParameter = "this will be available in controller";  
        return $request->response;
    }

    public function autoload($class) {
        require_once("controllers/{$class}.php");
    }

}

$application = new MyApplication();
$application->start();

Routes

Simple regular expressions

Routes are represented as simple PHP array object, mapping paths to controller classes. When each request is processed, it first gets matched, in order, to each element in this array. Matching is done with preg_match method, so regular expressions can be used for matching.

Examples of simple expressions:

$app->setRoutes(array(
    '^/$' => 'IndexController',
    '^/news/$' => 'NewsController',
    '^/news/1363/$' => 'NewsController'
));

It is recommended to start each route with ^ and end with $, they are special regular expression characters, representing start and end of string, respectively.


Data from URL

Applications sometimes require dynamic urls, for example we created controller for editing blog posts, now we want it to be accessible and get blog post ID from url: /blog/edit/123/. Because routes are regular expressions, the solution is simple - we match ^/blog/edit/(\d+)/$. (\d+) matches at least one number so this will match our path. This match result (number) will be available in controller as $request->args[1], which we can use for setting up database query.

Named matches can also be used - in example above we could use ^/blog/edit/(?P<blogid>\d+)$. In this case match data would be found in $request->args["blogid"].

More info on PHP's regular expressions can be found on their official page


Controller classes

Abstract controller

Controller classes that routes are mapped to have to extend Nphp_ControllerAbstract, either directly or indirectly. This means it can be used as a base for your own controller abstract classes where additional features that are shared among controllers are implemented. Most basic example is extending nphp to support templating engine of your choice or create method to convert data to JSON format for your API.

In each instance of our controller we have to create methods that match HTTP methods we want to support on that URL. For example if we want server to respond only to GET methods create get($request) method. You're free to implement any method you want, as long as it's supported by your HTTP server. There is special method that responds to any method: all($request).

Default controller has only few properties and methods:

_application
Nphp_Application, application that called this controller
request
Nphp_Request, another way to access request object
render ( template=string, context=array )
Nphp_Response, method that takes template name, which is PHP file, as a string, extracts variables from context array so they're available in template and returns response with rendered template set as content
redirect ( url=string )
Nphp_ResponseRedirect, returns response object that creates HTTP redirect (302) to specified url

Example of simple controller class that accepts GET and POST methods:

class IndexController extends Nphp_ControllerAbstract {
    public function get($request) {
        // output simple text
        return "Hello world!";
    }
    public function post($request) {
        // redirect to index
        return $this->redirect("/");
    }
}

Request data

Each controller needs access to data that was sent with request and most of it is accessible from request object that is passed to methods as parameter or available as controller property: $this->request. This data can be used to create database queries and other logic usually found in controllers.


Return types

Controller methods can return two different types of objects. First is Nphp_Response object and other is simple string. If string is returned, nphp will construct new response object with default values. If Nphp_Response is returned its data will be used when sending response.

When request object is created, it also creates default response object, which can be used to manipulate response in controllers - for instance if we want to change output headers.


Response object

All response objects have some properties and methods for convenience. Values that are always needed by nphp have default values but feel free to change them. Here is list of these properties:

code
integer, HTTP status code, default is 200
headers
array, array of strings, headers that will be sent with response, there is one in by default: "Content-type: text/html; charset=UTF-8"
content
string, already rendered content that will be sent as body
cookies
array, array of current cookies that were sent with request, alias of $_COOKIES
newCookies
array, array of new cookies that will be sent with response, each cookie has to be in specific form, it's recommended to use addCookie() method of response object
setCode ( code=integer )
sets code property, which is HTTP status code for response
setHeaders ( headers=array )
sets headers property, which is array of strings - headers to be sent
addHeader ( header=string )
adds header to headers property
setContent ( content=string )
sets content property, that is rendered body
addCookie ( name=string, value=string, expire=integer, path=string, domain=string, secure=boolean, httponly=boolean )
helper method for setting new cookies, they get addded to newCookies array and then set with setcookie() PHP method. Only name is required, check PHP's setcookie for defaults and options

There are few special types of builtin response objects:

  • Nphp_Response404 - same as basic response class but with code set to 404, used for missing pages
  • Nphp_Response500 - same as basic response class but with code set to 500, used when server error occurs
  • Nphp_ResponseRedirect - is used for redirecting users to different URL, code used is 302 (Found), which is common way to perform a redirection. Its constructor accepts new URL/path as paremeter

Redirects can be used as shown above in controller example or with Nphp_ResponseRedirect object:

class IndexController extends Nphp_ControllerAbstract {
    public function get($request) {
        return new Nphp_ResponseRedirect("/redirect/path/");
    }
    public function post($request) {
        return new Nphp_Response404("This page is missing.");
    }
}

Templates

Nphp doesn't have templating engine built in as we leave choice of engine to the users. For simple templating you can use basic PHP. You only need PHP file with template and call render() method of you controller class.

PHP template file (template.php):

<html>
    <head>
        <title>title</title>
    </head>
    <body>
        <?= htmlspecialchars($username) ?>
    </body>
</html>

Controller using template.php:

class IndexController extends ControllerAbstract {
    public function get($request) {
        $context = array("username" => "John Doe");
        return $this->render("template.php", $context);
    }
}

Template paths are always relative to the folder containing file with $application->start() - so usually index.php.


Messages framework

This framework is used when we want to send message to current user - for example notification that account was created, item deleted, etc. This messages are added to session in one controller and then read in another. When they're read they're automatically removed from session as nphp assumes they were displayed. They work best in combination with some JavaScript that makes them visible and then closes after some time.

Messages are added and read from request objects:

$request->addMessage("User registration was successful!");
$messagesArray = $request->getMessages();

Custom templates

Set up engine

Even though nphp supports basic PHP templates, this is usually not enough for bigger projects, so we encourage the use of other templating engines. There are plenty out there, but in this example we're going to use awesome Twig templates.

First step in setting up this engine, after downloading the source, is to set up Twig loader and environment so they're available in each request. This is done in our extended application class' bootstrap method:

// require Twig's autoloader
require_once("Twig/Autoloader.php");
// use filesystem loader - it loads templates from specified folder
$this->twigLoader = new Twig_Loader_Filesystem("templates");
// empty settings - we can specify default charset and other options here
$twigSettings = array();
// build environment from loader and settings - this is main object used to render templates
$this->twigEnvironment = new Twig_Environment($this->twigLoader, $twigSettings);

Global variables

Another thing most projects use are some common variables that are needed in every page rendered, so it's best to have them defined in one place. Good examples are URL for static content, version of application, ...

We do this by creating global context which will be later added to each controller's context, just before rendering:

$this->globalCtx = array("staticUrl" => "http://static.example.com");

Extend controller abstract

Last part needed is our own render() method in controllers we're going to use. Simplest way is to extend Nphp_ControllerAbstract and overwrite existing method. Make sure your controllers are inheriting from your new abstract class.

abstract class MyControllerAbstract extends Nphp_ControllerAbstract {
    public function render($template, $context) {
        $context = array_merge($context, $this->_application->globalCtx);
        return $this->_application->twig->render($template, $context);
    }
}

Use is really simple:

class IndexController extends MyControllerAbstract {
    public function get($request) {
        $context = array("localVariable" => 1234);
        return $this->render("index.twig", $context);
    }
}
<html>
    <head>
        <title>title</title>
    </head>
    <body>
        <img src="{{ staticUrl }}/logo.jpg">
        {{ localVariable }}
    </body>
</html>

Debugging

Debug page

While it's certainly possible to use debugger with nphp, there's another built-in tool that makes developers' life easier - debug page. When debug option of application is set to TRUE and error is encountered on page you'll get nice debugging output, with full stack trace, local variables and settings.

Output variables

Nphp disables all normal PHP output so only content that is returned from controller methods is sent as response body. Normal output counts everything that is output using echo, print_r(), var_dump() and similar functions and constructs. Instead of output everything is buffered and later either discarded if debug is set to FALSE or displayed in nphp debug toolbar if it's set to TRUE. Debug toolbar button is displayed at the right side of pages and can be pressed to show toolbar contents: PHP output and time it took to display the page. This toolbar can be disabled with setting application's disableDebugToolbar() to TRUE.


Project skeleton

Download

Skeleton is project created to provide bootstrapping of new nphp projects. It uses Twig templates, as shown in example in this documentation, YAML file for various configuration settings and PDO for database layer. Files are split to folders, as described in structure.

You can use it by either cloning github repository or using composer. Make sure you install all dependencies:

This is done automatically if you use Composer.

Links and specific instructions coming soon.


Structure

Coming soon.