Writing good, clean PHP code isn’t hard. One just needs a few simple guidelines.
Start every project by building a “Model”.
Before you even consider what it will look like, or even think of one snippet of HTML, think of what your program will actually do. Then, begin to write small snippets of code that do those things. If you have to write the same control structure (the same if statement, for example) more than once, it should probably be in a function of its own.
Don’t use global variables. Ever. If you need a piece of data, provide a way to set it in the class, or pass it to the function as a parameter. Don’t even be tempted to use PHP’s built-in globals ($_GET and friends). They have a purpose, but they don’t belong here.
As you write the various functions, consider whether or not they would work in a different environment. What if they were being called from another instance of PHP running on someone else’s server? What if you decided you wanted to output everything in Flash, or in a PDF file? What if they were going to be used completely outside of a web browser?
Give these little snippets of code useful names. If it gets the time, call it getTime(). If it gets weblog entries, call it getEntries(). If it adds a user to the database, call it addUser(). I think you get the idea.
After you build all of these little functions, store them away in a file all by themselves and include it at the top of the other scripts in the application.
That step alone will make your code much more usable. You can now build many little PHP scripts that access this “Model” to get and store the data that is needed to make the application work. If you find yourself storing any data or getting any data and not using the “Model” you built, chances are it should be in there. Don’t be afraid to build more than one “Model”. For instance, if you are building a weblogging application, you might have one “Model” handle the weblog data, and another “Model” handle the user data (authentication and such).
However, if you’re doing things right, why stop there? The next step is to build “Controllers”.
Begin writing individual PHP scripts that call the functions in your “Model” and prepare the data to be used. They might handle checking to see if a user is logged in and starting a session. Some of these scripts might even access more than one “Model” — a weblog “Model” and a user management “Model” for example.
Some scripts will get data from the “Model”. Others will put data submitted via the web into the “Model”. You should not write any script that does both.
When writing a script that puts data into the “Model”, when the script is complete, it should issue a header('Location: http://something.com/some/path') command to forward the action on to a page that will get data from the “Model”. It should not output anything to the browser. In the case of an error, forward the user to a page (using the header() function) that will display that error message and allow the user to try again.
When getting data from the “Model” simply build up the data that you are getting and it in arrays. When the scripts nears completion it should have done nothing but build arrays of data.
At the end of the scripts you should either call a templating engine (like Smarty), or use include to include a PHP file that contains the actual HTML you wish to display.
Now that wasn’t too hard. You’ve only got one step left: building the “Views”.
If you are using a templating engine that allows logic (if structures, and variable formatters), then you merely need to build an HTML template that displays your data as you desire (Smarty works in this fashion). Since the “Controllers” call your templating engine, the templating engine and the associated templates serve as your view.
If your templating engine doesn’t allow logic (like FastTemplate, for example), then instead of calling the templating engine at the end of your “Controllers”, include another PHP script that will perform layout logic using the constructs for your templating engine. These small PHP scripts should do nothing but use the variables you built in the “Controllers” and call the various functions provided by your templating engine. They should never call the “Model”.
If you choose not to use a templating engine, then your “Controllers” should merely include another PHP script. This script will have HTML in it and should access only the variables built in the “Controllers”. Feel free to use PHP control structures (like if, while, foreach and family), and PHP functions that format data (like htmlentities() and date()). However, do not call the “Model”, or use any PHP functions that store or retrieve data (like mysql_query() and fopen()).
That’s it. You’re done.
What you have now is the same application, but much more usable. If I want to make your application fit the theme of my webpage, I merely change the “Views”. If I want to change the way the URLs look, I change the “Controllers”. If I want to display additional information from a completely unrelated application on the same page, I just alter the “Controllers”. If I want to change the real meat of the application, then I can get dirty and muck around in the “Model”. This allows the code to be separated into its components. The “Model” holds the part that actually does something. The “View” displays the data to the web browser. The “Controller” ties the two together while handling the incoming data that might have been submitted via form or via a QUERY_STRING.
There are other ways to produce clean code. Some of them involve incorporating the “Controllers” and the “Views” into the same step. Others introduce even more levels of separation. In some cases, it’s even okay to not separate code at all. Regardless of what method you use, unless your script is less than 50 lines of code, you should always have a “Model”.
These ideas aren’t difficult. The code works the same, and does the exact same things. It just allows each piece to be isolated so that they can be easily altered, debugged, or included in some other application.