Easiest PHP View Layout Pattern Technique

With MVC frameworks one of the most common patterns is that the controller will wrap all your views in a container template, usually called the `layout`.

Although it's easy to wrap one file within another, wrapping one file *around* another isn't something that comes naturally to PHP.

There is actually a very easy way to do this though, which leaves the layout file completely independent of any specific framework.

The technique uses PHP output buffering system to accomplish the wrapping in just two lines.

Output buffering must be turned on before any content is sent. First the view fragment is included and then the layout file must be included after that, there are no other requirements.

At the top of the layout file we just call ob_get_clean() and assign the contents to a variable, this will get the entire contents what has been rendered so far. Further down in the layout file, where ever is necessary, you just print out that variable.

This provides a very lightweight approach to the pattern. If PHP's output buffering had a means to get the contents buffered in the previously included file then this would just be a one line technique.

Client Server Form Submission Architecture - HTML Upgrade Technique

Form handling is probably one of factors that influences server and client side architecture the most. It also has a strong affect on the user experience. Unfortunately, the HTML standard doesn't provide any support for form errors.

On the server side we often need to litter our markup with template code that shows errors from the validation code. If we want to provide a decent user experience we need to show the error for an input item right next to that item. In order to do this there are generally three common approaches:

1) Litter the markup with template code redundantly duplicated for each form item. This involves a lot of extra manual work and is much less immune to changes. It's also messy and doesn't provide good separation between client HTML and server logic.

2) Use a server side class to encapsulate and send out the form markup, and dynamically send out the errors as it does so. This approach provides the least separation between server logic and client HTML, and also limits the structure of our forms, which can be key to enhancing user experience.

3) Use a server side DOM library to dynamically insert the errors near their input items. This can be a very inefficient approach, but is by far the best option if efficiency can be sacrificed. Unfortunately, because of the nature of most server side platforms, setting this up usually involves much more tighter coupling of the application parts on the server side, taken care of by more intrusive server side frameworks (which are harder to learn and customize).

4) Send the results of the form validation programmatically to the client (usually in JSON format), then use a client side side DOM library to insert the errors. This approach allows the greatest separation of concerns and can really simplify the necessary architecture on both sides. It does require a specific format to be decided on for the server response though. This obviously also provides the highest amount of caching, which is necessary for installable HTML applications.

5) Put all the the errors at the top of the form, using a `label` with a `for` attribute and `error` class, and then use javascript to gracefully upgrade the visual or structural position of the errors and the styling of the inputs. This is a really nice lightweight approach on the client side. It also means that you can achieve the better user experience without changing anything on the server side if you are just using templating to show the form result. Furthermore, if you want to have greater separation of concerns on the server side, then the form submission URL can be implemented independently as in the JSON case, but instead of dealing with JSON the same error labels can be returned and handled with this upgrade scheme on the client.


What's nice about the last approach with grouped error labels is that it fits well into the HTML mindset by using the for attribute to link it to attributes, and it also is the option with the greatest ability to cross over between the different approaches. Of course if the server API needs to work for non HTML based clients then it might be best to use the JSON approach.

A DOM inspired Web Server Application Framework

"Unprecendented control meets simplicity and functionality"

 

Designing toward a more ideal server

The Lightnode framework is designed around the ideas of attaining a more ideal web server platform, which should be easier to manipulate and understand than our traditional servers, while still providing all the functionality that we desire for rapid development.

Node.js provides a solid base to use along our path towards a more ideal web server platform, however, as noted, it achieves this by purposely avoiding the provision of high level functionality in order to avoid the need to address the design challenge of countering the complexity and reduced flexibility inherent in introducing higher level functionality.

This means that it is up to library authors to tackle the challenge of providing a framework that provides the desired functionality while maintaining simplicity, and flexibility and ease of manipulation.

Control through a DOM inspired Hierarchy

Lightnode addresses this challenge by conceptualizing server control in a manner inspired by our browser DOM, and with the most appealing conceptually coherency.

The user creates a hierarchy of server objects prior to when the server starts listening for requests. By creating a hierarchy of server objects, each object can be customized differently, and remains conceptually separate.

A simple delegation step is added to the server objects, where users can indicate how a request event is routed *down* the hierarchy. It is easy to route a request to some custom code outside of the server hierarchy.

A site can be served simply with just one server, or a separate server object can be created for each sub section of the site. Servers can also be created dynamically when a request comes in, including lazily created for the case where a non-existing server is requested from the hierarchy.

The servers in the hierarchy can be instances of the user's custom subclass of the lightnode.Server control class, or of it's file server subclass lightnode.FileServer.

Functionality

Lightnode currently provides this simple hierarchical delegation framework for control, as well as add-on utility of fast static file serving with http client side caching, and a design that is easy to setup virtual hosting or any other desirable or customized setup. Much more functionality is planned to be added in future, in order to provide a platform for flexible and simple rapid development.

 

lightnode github repo

The Lightnode Web Server

I've just released the first version of Lightnode, a NodeJS powered web server platform.

Lightnode is designed to take advantage of the potential that NodeJS makes available, in a offering similar to the traditional servers such as lighttpd or apache.

It follows from my opinion of some choices toward a more ideal web server. From that it focusses on transferring to you the unprecedented control the NodeJS provides, while achieving simplicity and desirable functionality.

The name come's from a desire to achieve a lightning fast static file server, capable of replacing the high speed lighttpd server, and lightweight in terms of understandability. It is largely centered around a simple, non-intrusive request delegation mechanism, and it's potential for hierarchical servers and customization of those server objects.

At the moment, Lightnode provides static file serving as well as a solid, non-intrusive framework for taming node's unprecented control both within the file serving system and for custom dynamic server applications. The static file server can easily serve virtual hosts, has http caching, directory indexing, customizable mime-types, customizable 404 'Not Found' logic, as well as the ability to by pass our routing and use the "send file" functionality directly. 

You can check out an overview of how it was optimized to achieve speeds equal to lighttpd. This is a very early release obviously, more functionality needs to be integrated still. Tutorials are likely to follow soon (update: checkout the github repo).

Benchmarking Static File Servers :: Lightnode + Lighttpd


For those who don't know, Nodejs does not come with static file serving built in (for good reason), user's therefore need to look to external modules to serve files statically.

Lightnode

I've just released lightnode, a static file server for node js, which aims to replace my usage of Lighttpd for serving static files for web applications. It's called lightnode for many reasons, the fact that it sounds like 'lightning' kind of tipped it - I really wanted to take advantage of node's speed, and it's designed to be a replacement for lighttpd which itself is very fast for serving static files. The other important reason for it's name is that it's meant to be lightweight in terms of concepts, so that it's easy to understand and manipulate, which I believe is a very important aspect to utilizing node as a file server. In this benchmark I'll go over the simple means through which lightnode attains it's speed, and give some pointers about writing efficient code for node.

Benchmarking

So far I've seen very few benchmarks for node js based static file servers, many of which are sub 500 line modules, so they have likely been created fairly quickly by their authors. Lightnode is no exclusion, except that I've created it to try take advantage of node's potential directly in comparison to the traditional server's such as Apache and Lightnode, so I intend to keep it around, and therefore it's important for me to know how efficient a node based static file server can be in production environments.

Here I've benchmarked my server against the super fast lighttpd, as well as against another node option, which is the connect framework's static file server module (I'm not a fan of the framework, but their static server made by one of the learnboost guys seems to have been the best of the bunch).

I created the first version of lightnode with all the features I wanted such as hierarchical servers and http caching - leaving request efficiency for later - then started the benchmarking.

I've used the apache benchmarking program (ab) and set it to send 10 000 requests over 100 concurrent connections. I've included the raw results in the my lightnode repo. The most important number that ab churns out is the milliseconds per request, which I'll focus on.

Pre-Optimization Comparison

Picture_5

At this first phase it performed quite poorly, but that was to be expected. I wanted to get a feeling for what optimizations were important and how important they were. 

Lighttpd was outperforming my pre-optimized server almost three fold, taking 19ms per request while lightnode was taking 56ms, Lighttpd was serving 5267 requests / second, whereas lightnode was serving 1769 requests per second. What was most concerning about this result however, is that all - except one - of the static file server modules published for node so far were doing the exact same thing as my server was, so they probably have this same performance.

I wanted to make sure that this result wasn't something that I was doing terribly wrong so I benchmarked another server. I decided to try the connect server because I hadn't looked at it's source yet.

Picture_7
   
I was quite surprised to see that the connect static server was actually as fast as lighttpd. When I checked out the source I realized that it was the only node server that was doing in memory caching of the file contents. Switching this caching off caused the connect server to perform the same as my server. 

It turns out that in memory caching of static file contents can increase performance three fold, and give you efficiency equal to the fastest servers out there. The memory usage for most sites would be very small, provided you choose not to cache the big files.

Picture_13

In general you want to stream the larger files and dynamic content, and you want to cache smaller files completely, especially in Node applications. The operating system does keep a cache of file access, however, it still needs to make a user land copy of that memory for each request a process makes for it. As far as I know, in the case of node, copying that memory into the javascript application involves an expensive data encoding operation, so you really want to cache node's data buffers in your code if your application logic will allow it.

However, all is not that well in the land of efficient static servers for node. In order for the connect server to cache the contents it has made the considerably undesirable tradeoff that any changes made to the file during the lifespan of the server are completely ignored. That means that you need to reset your production server every time you want even a small change to your static files to be reflected, potentially cutting off clients, and obviously an inconvenience to development. This is not how lighttpd achieves it's speed. What I've done for lightnode is create a simple caching system that still reflects changes immediately while achieving the same speed.

Lightnode's Serving Process

What lightnode, as well as all the other servers are doing every time they try to serve a file is calling stat() on the filename to see if it exists and when last it was modified. The file is then read in completely with readFile(). In the case of connect that file content is cached, and they then choose to avoid doing a stat() on any subsequent requests.

Caching Properly

One of the main efficiencies I was worried about for lightnode was doing that stat() on every request. It turns out that it contributes to an extra 10ms per request, the caching of the file contents contributes about 25ms, so they are both something that we want to avoid. However, seen as we are dealing in the range of milliseconds, and aiming to serve some 5000 requests per second, we shouldn't really be doing the stat on every request anyways, instead we should do it once and then only repeat it again a second or so later, at least for this application of serving 'static' files.

An Optimized Lightnode

It turns out that we don't need to avoid it on every request to achieve the same level of efficiency. Lightnode's caching mechanism will avoid calling stat if the last stat was done in as little as 0.5 seconds. This is sufficient to use as a development environment where files are changing and being viewed immediately, and achieves the same efficiency. The file content itself is cached and only refreshed when requested if the stat shows a change. This is a technique of stat caching and file contents caching is something that carries over to almost any re-use of file contents and something every node developer should know about to achieve better efficiency. 

The philosophy of node opens up a lot of potential to us that wasn't previously available, so we should get used to taking advantage of them. In a PHP application for example, it was much more difficult to be able to cache something for the lifespan of the server 
 (and is still conceptually at odds with the programming paradigm).

The optimized lightnode server is now performing almost equally with lighttpd with this work load. It's processing a request in 23ms (was 56ms) while lighttpd does it in 19, and it's serving 4348 request per second (was only 1769) while lighttpd does 5267 requests per second.

Picture_10

NodeJs static servers can be just as fast as other servers, and offer the potential for much greater flexibility and ease of use in comparison to traditional servers. With proper caching mechanisms there is no need for unnecessary tradeoffs and the server functionality is more suitable for production.

Check out the new lightnode server for nodeJS, other than lightning fast static file serving it offers a lightweight framework for control handling even in non-file server (dynamic) applications, which helps tame the immense flexibility that node provides.

An Ideal Web Server

Our web servers so far have not been ideal. They often require excessive configuration, have limited functionality, complex compilation processes for add ons, less than easy-to-understand request handling processes and the need to use low level language when we want to more customization, to name just a few issues on the negative side, the lack of achieving possibilities on the positive side is a different story. More importantly however, is that they don't offer very much help to us in actually creating dynamic applications. To create dynamic applications we often have to bypass our way through their complicated request handling, making it hard to integrate some application logic as we would like to. These are all issues that all developers have become used to. Our servers so far have been far from ideal.

I'd like to lay out a few design choices toward a more ideal web server.

1) Provide as a non-intrusive library

This maximizes utility and flexibility, and encourages a focus on being non-assuming of the user's desires.

2) Use a friendly programming language

The user's can then easily do whatever they wish to with the library, and have the language as a single conceptual center.

3) Desirable functionality

A library needs to be responsible for considering what functionality is desirable for the user's. This includes what should be provided directly, and what sort of things should be enabled for the user's or others to provide.

4) Simplified process logic

Providing desirable functionality is always offset against the simplicity with which it is achieved. A focus on non-assumption of the user's desires (and hard work to achieve it) should lead to logic that makes sense to their user's desires as opposed to the library's implementation. Simplified logic is crucial in allowing maximal ease of use for user's, as well as for flexibility and customizability. 

5) Simple non-intrusive framework for control

Based on the consideration of potential desires, as well as the simplification of logic required to achieve core functionality, a web server should provide a simple, non-intrusive and flexible framework for control. This should support user's both in using the functionality the server provides as well as in creating any external application logic. 

6) Instructable functionality

When the framework or processes provided by the server are not desirable, as much utility as possible should be provided as directly instructable lower level functionality.

These are choices that some software engineers concerned with architecture would know. So far we either haven't seen enough concern for providing a more ideal server, there hasn't been enough commitment, or the perhaps the lack of an accountable, empowered technical lead in previous efforts has hindered the ability to target these aims. 

As many staying up to date in this area will already know, the NodeJS http server (library) has taken at least the first two choices toward this more ideal server. The reasoning behind the choices however, seem to actually have been made not for the sake of a more ideal server in general, but for the sake of a more efficient server achieved through an evented IO library, which the javascript language is ideal for, given it's current use for evented systems in the browser. Credit must of course be given to the author of NodeJS regardless, as he has purposely focussed on good design in his work. It seems that the topic of efficiency is more highly regarded and easier to communicate and convince with than architecture itself, so even someone aiming for a more generally ideal server probably does better to turn to efficiency as an argument.

NodeJS however, is just a base library to create http servers. It isn't in itself a web server provision akin to the traditional servers. On this list it therefore starts to be lacking after the first two items. It doesn't consider much of the desires or functionality for web developers, things like static file serving, mime-type handlers, etc are out of the scope of NodeJS, and for good reason. Accounting for this functionality introduces inflexibility and works against simplicity, therefore NodeJS acts as a strong base for others to attempt accounting for this functionality while still achieving a great web server.

Lightnode

I've designed and just released Lightnode as an initial attempt toward a more ideal server, or at least to further what NodeJS has provided, such that it's more usable for web developers. You can read more about it here, and following my own advice I've written about it's efficiency, but that of course is not nearly it's greatest asset.