With the basic structure for our Framework in place, it is time to start adding functionality to it. In this tutorial we will create a template manager and database handler, bringing us a step closer to a powerful Framework fit for use for almost any project. If you haven't already, be sure to review Part 1 of this series first!

MVC: Tweak the structure

In the first part of this tutorial, we created a folder called controllers to store the business logic for our applications. As daok pointed out in a comment, this isn't the best place for all of the business logic, and that a model should be used to store this logic. Previously, I have always used the database itself as the model in the majority of my applications, however, seperating this out a little more will make our framework even more powerful, and easier to extend.

So, what is MVC? MVC is a design pattern (as was the Singleton and Registry patterns we looked at in part 1), and it stands for Model View Controller, and the aim of this pattern is to seperate the business logic, user interface actions and the user interface from one another. Although we are not going to do anything with our models and controllers just yet, let's update our frameworks folder structure to include the "models" folder. The model will contain the main business logic, and the controller will deal with user interaction (e.g. submitting data, such as a comment). NB: Our __autoload function does not need to be changed.

Database Handler

Most websites and web applications which make use of PHP also make use of a database engine, such as MySQL. If we keep all of our database related functions in the same place, then we can (in theory) easily change the database engine we use. We can also make certain operations easier, such as inserting records, updating records or deleting records from the database. It can also make it easier when dealing with multiple database connections.

So...what should our database handler do:

Manage connections to the database

Try to provide some level of abstraction from the database

Cache queries so we can use them later

Make common database operations easier

Let's look at the code for our database handler, then we will discuss it afterwards.

Before discussing this in more detail, I should point out that this database handler is very basic. We could provide complete abstraction by not executing queries directly, but instead constructing queries based on paramaters to a query function, and then executing it.

Our delete, insert and update record methods make it easier to perform some common tasks (as I mentioned above we could extend this to do much much more), by only providing information such as the table name, an array of fields and coresponding values, limit values and conditions. Queries can also be "cached" so that we can do things with them later. I find this feature (as well as the ability to "cache" arrays of data) is very handy when combined with a template manager, as we can easily iterate through rows of data and populate it into our templates with little fuss, as you will see when we look at the template manager.

We can also work with multiple database connections relatively easily, so long as we switch between the appropriate connections when we need to (although this won't work when caching queries and retrieving them via our template manager without further work), for example, the code snippet below would allow us to delete records from two databases.

How might we want to extend this class?

Full abstraction

Make use of inheritance, create an interface and have database classes inherit from it, each for different database engines

Store the connection ID's along with the query when caching queries

Improve data sanitizing, depending on the type of data we wish to sanitize

Template Manager

The template manager will handle all of the output, it needs to be able to work with various different template files, replace placeholders (I call them tags) with data and iterate through parts of the template with multiple rows of data from the database.

To make things easier, we will make use of a page class to contain the content related to the page, this also makes it easier for us to extend this and add features to it later. The template manager will manage this object.

So, what exactly does this class do?

Creates our page object, and bases it from template files, the page object contains the content and information which is needed to make-up the HTML of the page. We then buildFromTemplate('templatefile.tpl.php', 'templatefile2.tpl.php') to get the initial content for our page, this method takes any number of template files as its arguments, and stitches them together in order, useful for header, content and footer templates.

Manages the content associated with the page by helping the page object maintain a record of data to be replaced into the page, and also additional template bits which need to be incorporated into the page (addTemplateBit('userbar','usertoolsbar.tpl.php')).

Adds data and content to the page by performing various replace operations on the page content, including retrieving results from a cached query and adding them to the page.

The template file needs to mark within itself where a cached query needs to be retrieved and the data from the query replaced. When the template manager encounters a tag to replace which is a query, it gets the chunk of the page where it needs to iterate through by calling getBlock('block') on the page object. This chunk of content is then copied for each record in the query, and has tags within it replaced with the results from the query. We will take a look at how this looks in the template later in this tutorial.

Template Manager: Page

The page object is managed by the template manager, and it used to contain all of the details related to the page. This leaves the template manager free to manage, while making it easier for us to extend the functionality of this at a later date.

How can this class be extended and improved?

PostParseTags: You may wish to have tags replaced after most of the page has been parsed, maybe content in the database contains tags which need to be parsed.

Passworded pages: Assign a password to a page, check to see if the user has the password in a cookie or a session to allow them to see the page.

Restricted pages (although we need our authentication components first!)

Altering the

Dynamically adding references to javascript and css files based on the page or application.

Load core objects

Now that we have some objects which our registry is going to store for us, we need to tell the registry which objects these are. I've created a method in the PCARegistry object called loadCoreObjects which (as it says) loads the core objects. This means can can just call this from our index.php file to load the registry with these objects.

This method can be altered later to encorporate the other core objects the registry should load, of course there may be objects which we want our registry to manage, but only depending on the application the framework is used for. These objects would be loaded outside of this method.

Some Data

So that we can demonstrate the new features added to our framework, we need a database to make use of the database handler, and some of the template management functions (where we replace a block of content with the rows in the database).

The demonstration site we will make with our framework by the end of this series of tutorials is a website with a members directory, so let's make a very basic database table for members profiles, containing an ID, name, and email address.

Obviously, we need a few rows of data in this table!

A quick template

In order for anything to be displayed, we need a basic template, where we will list the data from our members table.

The START members and END members HTML comments denote the members block (which is obtained via the getBlock() method on the page), this is where the template manager will iterate through the records in the database and display them.

Framework in use

Now, we need to bring this all together, with our index.php file:

If we now view this page in our web browser, the results of the query are displayed on the page:

Coming in part 3...

In part three we will take a slight detour from the development side of our Framework, and look at how to design with our framework in mind, and how to slice up HTML templates so that they are suitable for our framework. When we start to build our first application with our framework, we will look in more detail at some of the workings of these classes. Finally, thank you for your comments last time!

Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.



