Writing Scalable Applications with PHP

May 20th, 2004 by Xavier Spriet in

A follow-up to April's print article, "Real-World PHP Security".
Your rating: None Average: 5 (1 vote)

The first part of this article, "Real-World PHP Security", appeared in the April 2004 issue of Linux Journal and covered the subject of secure PHP development. This article takes you, the professional PHP developer, one step further, by providing detailed explanations and reliable source code that illustrate the steps to follow in order to develop successful PHP applications.

One day or another, every developer faces a situation in which he/she is responsible for extending the functionality of an existing application or prepare an application for an increase in use and traffic (scaling up). Our goal today is to make this process trivial by learning to develop applications based on a clean, elegant and modular design that is secure, reliable and flexible while keeping it all simple.

Please refer to Figure 1, previously introduced in "Real World PHP Security" and included below.

Figure 1. Our Application Model Diagram

Cleaning Up the Operating Environment

As a system administrator, you may have noticed how flexible PHP is in terms of error reporting and security. The php.ini file enables you to make considerable changes to the behavior of the PHP interpreter, which can lead to bad surprises for a PHP developer.

Before we start working on the logic of our application, we must ensure that our operating environment will behave in a predictable way. One of the things you must watch out for is PHP's magic_quotes_gpc directive, which, when enabled, escapes every single value in your GET, POST and COOKIE arrays. This may look like a great way to protect against SQL injections, but it becomes a hassle when working with binary data. Listing 1 illustrates how to detect if the magic_quotes_gpc directive was enabled and how to reverse its effect if necessary.

Listing 1. Cleaning Up the Operating Environment

Many other surprises out there waiting for you as you port your applications to different platforms. Generally speaking, you should become as familiar as possible with the directives available in php.ini. Also, use the ini_get() PHP function to find out if specific directives are enabled or not. You then are able to set up your environment in a predictable way without having to worry about the configuration of the PHP interpreter.

Database Connectivity

If you are developing a commercial application or would like your application to be as flexible as possible, one thing you should look into is using a database abstraction facility in your projects. Many database abstraction libraries are available, but PEAR::DB is a widely accepted standard that performs well, has great error handling and is quite reliable. DB currently supports 13 different database platforms. DB's documentation is quite extensive and can be found here.

Some may argue that using a database abstraction layer in your application can affect the overall performance. It does, though, bring the flexibility you need to scale your applications up to new levels and to release cross-database applications.

Although DB may not seem forgiving or friendly at first, the DB APIs are compliant with the PEAR standards, which makes its behavior predictable and allows developer to create wrappers easily.

As with any database API, the steps to perform operations on your database are as follow:

  • Establish a Connection to the Database Server: DB uses a DSN (data source name) to represent the parameters to use when establishing the connection. Many formats are supported; an example might look like this: mysql://dbuser:dbpass@localhost/db_name. You then can use DB::connect(&$dsn) to establish the connection.

  • Perform Error Handling: DB uses the PEAR standard for its error handling facility. This error handling system is well designed and is versatile enough to provide predictable error control for all PEAR packages.

  • Specify the Behavior of the Interface: This is where PEAR::DB truly shines. DB allows the developer to define how the package should operate in every aspect. Using the same interface, you can make DB work as a cursor-based result-set iterator or fetch your entire result-set in an ordered array, an array of objects or an associative array.

  • Execute Queries: Whether you want to execute a stored procedure or a simple query, DB provides simple methods that perform those operations on your database while still providing error handling. The query() method simply executes a query against your database and returns a PEAR error object if an error should occur.

  • Work with Result-Sets: DB offers many simple methods for working with result-sets and offers a myriad of data-structures to the developer, such as associative arrays, objects, indexed arrays and so on.

But DB also offers some higher-end methods to the developer, such as auto-prepare and auto-execute facilities that allow you to create templates for your SQL query and have DB handle the creation and execution of subsequent queries. It also can filter literals against special characters, regardless of the database server you are using.

Case Study: Real-World Application Design

In this section, we work on a simplistic PHP application that handles the creation and management of user accounts. Although the rest of this section is pure PHP code, it has been documented and tested extensively. This code illustrates every principle described in this article as well as the initial print article.

We use the following file hierarchy for our application, roughly based on the previous article:

/index.php (this is the only www file)
/config.inc.php (configuration file)
/lib (libraries, protected by a .htaccess)
/modules (module files, protected by a .htaccess)
/lib/config.inc.php (configuration file)
/tpl (templates, protected by a .htaccess)
/doc (project and APIs documentation)
/images
/classes (classes, protected by a .htaccess)
/misc (CSS style-sheets, JS files, etc...)

All of the PHP code for this work is contained in this tar ball along with a README file.

Conclusion

In this article, we have spent a great deal of time looking at a real-world project. A lot of documentation is available in the comments for the listings, so a quick look through the code should give you a clear idea of how it works.

The latest version of this sample application is available for you to download here. Instructions on how to install this sample application as well as the license for this code and the API documentation also are available at the same address.

__________________________


Special Magazine Offer -- Free Gift with Subscription
Receive a free digital copy of Linux Journal's System Administration Special Edition as well as instant online access to current and past issues. CLICK HERE for offer

Linux Journal: delivering readers the advice and inspiration they need to get the most out of their Linux systems since 1994.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Sajid's picture

PEAR::DB is too slow!!

On August 10th, 2008 Sajid (not verified) says:

http://www.onlamp.com/pub/a/php/2001/11/29/peardb.html
http://markmail.org/message/c2aik7tba25j4coz

If PEAR::DB is toooo slow, how do you want scale up (!!!) your application using it?!

I think, you are calling a good (maybe better) application design - scaling up the application!
BUT What about increasing users/hits like facebook guys are facing?

Sajid's picture

PEAR::DB is too slow!!

On August 10th, 2008 Sajid (not verified) says:

http://www.onlamp.com/pub/a/php/2001/11/29/peardb.html
http://markmail.org/message/c2aik7tba25j4coz

If PEAR::DB is toooo slow, how do you want scale up (!!!) your application using it?!

I think, you are calling a good (maybe better) application design - scaling up the application!
BUT What about increasing users/hits like facebook guys are facing?

Anonymous's picture

Keep Looking

On May 21st, 2004 Anonymous says:

The architecture in this article is neither scalable nor secure. Scalability usually implies the ability to build some sort of N-tier architecture so that processing can be distributed across multiple servers if necessary. As for security, I can imagine an application that contains code like the following (line 19 in user.php) could be too secure:

return $_GET['action']($index_content);

Just imagine the code injection a malicious person could do with that.

There seem to be two general type of frameworks in PHP:

- ones like this with a sloppy design glued together with global vars and assumptions,

- and others that copy pattern happy, first generation Java frameworks (which Java is starting to abandon) that are so absurdly complex that they do the worst things you can do in PHP: make it slow and a chore to program.

You are usually better off in PHP either programming to the metal or using an old school, PHPLIB, kitchen sink style libraries. And then there is PEAR (am I the worlds biggest, most incoherent framework or the worlds smallest, least coherent repository?)

Does anyone know if a PHP framework that:

- respects PHP's wonderfully simple request and output systems,

- has a lightweight front/application controller that provides basic dataflow/action chaining,

- isn't any more object oriented than PHP actually is,

- provides simple request filtering and validation (preg_replace anyone?),

- allows for some N-tier application separation,

- and doesn't impose a specific DB/DAO or Template/View,

- is customizable enough to go as simple or complex as needed,

- maybe even allows either procedural or OO programming.

I would love to hear if anyone knows of such a thing. Maybe it is time to write it.

Sajid's picture

:)

On August 10th, 2008 Sajid (not verified) says:

You probably need to write it by yourself and I think, it's even better...

I personally use my own framework to develop applications using PHP (just don't like other frameworks!) and I made it exactly what I want from a framework (and minimal/simple at the same time). Sweet!
:)

Sandeep's picture

Re: Keep looking

On February 4th, 2006 Sandeep (not verified) says:

I think http://www.jaws-project.com/index.php might interest you. It is a breeze to install it and also it makes MVC for procedural programmer like me easy to understand. I know MVC in theory and it shows a good example of how to implement in PHP.

Regards

Anonymous's picture

I am all for your wishlist

On December 9th, 2005 Anonymous (not verified) says:

I am all for your wishlist of the 'Keep Looking' poster. I hope Zend Framework does not fall into the trap of overengineering and too much of MVC crap from Java domain.

In the meantime I found http://phx.sourceforge.net/ that seems to have most of the attributes that you enumerated. It looks remarkably simple but I am hesistant to use it since it does not come with a user and security management

Anonymous's picture

Re: Keep Looking

On May 30th, 2004 Anonymous says:

Does anyone know if a PHP framework that:
- respects PHP's wonderfully simple request and output systems,
- has a lightweight front/application controller that provides basic dataflow/action chaining,
- isn't any more object oriented than PHP actually is,
- provides simple request filtering and validation (preg_replace anyone?),
- allows for some N-tier application separation,
- and doesn't impose a specific DB/DAO or Template/View,
- is customizable enough to go as simple or complex as needed,
- maybe even allows either procedural or OO programming.

I've authored MVCnPHP which is a minimal MVC framework that would let you do much of what you want here except allow for procedural programming. I think using MVC sort of implies OO is the way to go though I can see how allowing procedural commands, views, etc can be done but that reintroduces some of the things the MVC would be acheiving (more atomic code, more maintainable, etc.) You can learn more about MVCnPHP here .

You are right, though, frameworks don't ensure any sort of scaling. DB-based session handling via PHP sessions and allowing true mutiple web and db servers get you that.

Anonymous's picture

Re: Keep Looking

On May 30th, 2004 Anonymous says:

Also, quit dinging PEAR. PEAR has a number of useful classes and if you are hosted, you can still use PEAR despite restrictions on the host by modifying PHP's include_path through code using ini_get and ini_set. Also, people tend to compare PEAR to CPAN and similar repositiories and that isn't apples-to-apples.

Anonymous's picture

Re: Keep Looking

On May 31st, 2004 Anonymous says:

But PEAR deserves it. I agree it has a number of well coded and useful classes. But the point is: what is it? It's sure not CPAN which is a code repository with a great installer. PHP could use a great repository so you wouldn't have to search a dozen sites to find code. And the PEAR installer is definitely the best part of PEAR.

It's not a framework even though they claim to have some crazy "no conceptual duplication" rule. The code quality is uneven. It is not coherent. And much of the code is totally bloated. PEAR.php is unnecessary and should have just been some standards for method names (like error handling and reporting). Even they admit that the PEAR_Error is terrible.

They are the official code repository and are installed with PHP. They should be held to a higher standard.

I think they need to 1) open the repository to everyone with minimal requirements (like CPAN or SourceForge) and 2) come up with a core set of classes that are a coherent base on which to build a medium size site. They should, for practical reasons, leave enterprise scale stuff at the high end and small things like email forms at the low end for others in the repository to solve.

Anonymous's picture

Re: Keep Looking

On May 24th, 2004 Anonymous says:

Apparently, you have not read the code illustrated at all!

The line return $_GET['action']($index_content); is inside an IF statement. If I remember correctly, it's something like this:

if (in_array($_GET['action'], $allowed)) {
return $_GET['action']($index_content);
}

so your entire comment makes absolutely no sense since code injection is not possible.

Also, please don't confuse the article with an actual framework.
The code is provided as a draft to illustrate the points brought up in the article.

Thanks,

Xavier

Anonymous's picture

Re: Keep Looking

On May 25th, 2004 Anonymous says:

I read his article, looked at the code, and learned from it. I also read the comments and learned more. I even went and improved some of my own code after writing my post. It would be helpful if the writer actually joined the conversation about writing better PHP code rather than just becoming defensive.

"so your entire comment makes absolutely no sense since code injection is not possible"

Actually very little of the comment was about code injection. The point was not to find one bad line. I just think one goal of presenting a secure application framework is to promote safe access to the request. You mention magic quotes yourself. I think perhaps a better method is have all access to the request go through filter functions. That way you don't miss anything, which is easy to do when you directly access the PHP globals all over your code. Those functions can also centrally handle php.ini settings which you also mention.

I apologize if you took offense. My comments were to express my thoughts about PHP applications, security and scalability. I just don't think the code you presented addresses those issues very well.

Anonymous's picture

Re: Keep Looking

On May 25th, 2004 Anonymous says:

Reading my previous comment over again, I understand that I may have overreacted.

However, please understand that the article is in no way intended to present a *framework*. The source-code provided is a good illustration of the patterns described in the two articles, no more.

Also, I agree that requests should be filtered, which is actually illustrated in Figure #1. I do have some code that does just that if you are interested.

The purpose of this design is to provide every module with a predictable environment (initialized by index.php and config.inc.php) where every module has a database connection available, knows what to expect from request variables, knows what the user is trying to do at any point. Using this, you have a central facility to provide security and scalability to your applications.

The article was never intended to be read as "If you want to write scalable and secure apps, use the attached code" but simply "With a design like this, you can really focus on implementing security and modularity because your environment is predictable, centralized and efficient".

I did my best to provide a lot of comments in the code to point the developer in the right direction as to where they should spend some time implementing such things.

I will gladly continue this conversation on here, or by email.

Thanks,
Xavier

Anonymous's picture

Re: Keep Looking

On May 23rd, 2004 Anonymous says:

You should look at http://logicreate.com, the answer lies within.

Anonymous's picture

Re: Keep Looking

On May 22nd, 2004 Anonymous says:

I've not looked at the code but the example you gave is typical of somebody with zero coding experience. The biggest problem with PHP has nothing to do with the language itself, it's a human by-product of PHP's ease of use. That people are writing articles and distributing scripts containing such terrible code is giving PHP an undeserved bad name.

PEAR is possibly the most foul pile of OOP::POO I've ever seen, but it's targetted at people with a shared hosting account and not at anybody doing serious work. I suspect PHP5's strip comments and whitespace function will be used to speed up the PEAR libs in production enviroments, stripping comments alone should reduce them to 1/10th the size.

We're working on porting our framework to PHP5, the object model is greatly improved and it should finally let us clean up our code. As for scalability, it's usually the backend db that is the bottleneck, PHP has no inherent scalability because it doesn't need any!

Anonymous's picture

Re: Keep Looking

On May 22nd, 2004 Anonymous says:

Maybe it is time to write it
Do it!

isn't any more object oriented than PHP actually is,
Glad somebody said it.

Having said that experimenting and trying new things with php is important. I do hope the java phase passes soon though

Post new comment

Please note that comments may not appear immediately, so there is no need to repost your comment.
The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <pre> <ul> <ol> <li> <dl> <dt> <dd> <i> <b>
  • Lines and paragraphs break automatically.

More information about formatting options

Newsletter

Each week Linux Journal editors will tell you what's hot in the world of Linux. You will receive late breaking news, technical tips and tricks, and links to in-depth stories featured on www.linuxjournal.com.
Sign up for our Email Newsletter

Featured Videos

Setting up an https server in Apache is easy. This tutorial covers how to create and sign your ssl certificate as well as how to configure the web server.

From the Magazine

January 2009, #177

It's a battle as old as time: good vs. evil. Fortunately, Linux and FOSS are on our side as we wage the battle against those who try to steal our secrets and invade our systems.

Checking your system's security is best done sooner rather than later. Test the locks with our article on security verification; find out how to use PAM to help secure your systems; use MinorFS and AppArmor to implement discretionary access control; learn more about Samba security in part III of our series; use Darknet to help detect bots and secure your systems; use the Yubikey to increase your site's security; and don't forget to lock the doors, because a cold boot attack could render your security useless if somebody has physical access to your computer.

But, we're not just about sowing the seeds of fear. We also show you how to use memcached in Rails, how to manage multiple servers efficiently, how to deploy applications easily with Capistrano, how to manage your videos with MythVideo, how to mix it up a bit (your audio that is), and even play a few games.

Read this issue