`
uag
  • 浏览: 19431 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

转载 PHP Application Framework Design: 1 – Getting Started

    博客分类:
  • php
阅读更多

转自   http://www.lbsharp.com/wordpress/index.php/2005/10/13/php-application-framework-design-1-getting-started/

 

This article describes the design of a complete application framework written in PHP. The reader is assumed to have a working knowledge of PHP. This part of the series describes the scope of the framework and goes over the initial class hierarchy. The following parts cover everything from session handling to creating page templates.

Introduction

I started web application development back in the days of ASP 3.0. Back then, ASP was so deficient that we had to write most of the code in DLLs and include them into the web projects. Sure, it was a bit cumbersome, but IIS was the best platform available for getting a team of VB developers productive. Then ASP.NET came around and fixed many of its predecessors deficiencies so the company where I worked at the time jumped on the bandwagon. Although I didn’t realize it at the time, .NET spoiled me with its ease of developing large applications (without much need for thorough design and planning).

Don’t get me wrong this is not an advertisement for Microsoft. While .NET was gaining ground over the Java platform (please don’t email me saying how Java is better thats not the point here), there were quite a few developments in the open source community as well. Apache has long established itself as the leading web server software and PHP became the open-source answer to ASP. By avoiding the overhead of CGI1, PHP combines speed and efficiency with the power and style of Perl. PHP also happens to be cross-platform and free (as in beer2) which makes it a no-brainer solution for many projects.

Unfortunately, PHP has its limitations. Although PHP does fix many features that make Perl unreadable, using it for large projects can be somewhat difficult (relative to Java or .NET that is). So what are the possible problems? For starters, large projects involve many developers with wide ranges of skill-sets. For web-projects, you may have people who don’t even know how to do anything save design page layouts and make pretty pictures (and yes we appreciate you guys as well). How do you get everyone to work together productively and be consistent? You may say that this is the Team Leaders job but managers can use help too sometimes. Developing in PHP can also be somewhat tedious when you find yourself copy-pasting the same blocks of code (e.g. to authenticate the user, insert the page template, connect to the database etc). This article will try to resolve these issues.

So whats missing from PHP? Well, nothing actually, if you spend some time to design what you want to accomplish. While platforms like .NET force you into doing things the Microsoft way, PHP gives you the flexibility to do things your way. Use this power wisely or else you will see the performance of your PHP application dwindle down to that of .NET or even Java (heaven forbid). And, while we are on the subject, why not just use .NET since it does so much work for you? That question is left up to the reader. Maybe the choice of using PHP was already made for you (by your management by magazine type boss). Maybe PHP is the only tool installed on your server. Or maybe you just like the syntax. I really don’t care and, if you are reading this (as opposed to having this read to you), the choice was probably already made. I also realize that there are some commercial products that provide a canned-framework for you to use that solve all the problems that I described above. I’m not trying to sell you anything just trying to show that you can easily come up with your own framework. Lets get cracking shall we.

Class Hierarchy

I like to start implementing large projects by drawing out the class diagrams and seeing how the components fit together. Luckily, as of version 4, PHP supports object oriented programming with all its bells and whistles. Although this article is written for PHP 4, you can accomplish all of the same results with PHP 5 (which is still somewhat bleeding edge at the time of writing this). Object oriented programming and design is beyond the scope of this article so I hope you are at least somewhat familiar with it. The point is that OOP is the key to developing large applications and web-development is no exception.

Update: PHP 5 is now fairly mainstream. Although the framework, as described, will still work, some of the hacks described in this article are no longer needed.

We will want to keep the framework minimal for performance reasons yet scalable and flexible enough to handle any kind of project that you may encounter. To start of, lets agree that the logic for each and every page of you application will be encapsulated in a class. This class will inherit from the system base class, which will handle everything that you may want your application to do. The benefits of this approach are fairly obvious. First, you are encapsulating all of the complex code away from the project developers. Thus, you can rest assured that your new intern will not mess with your system classes (unless you want her to for some reason). All the pages in the application will be more consistent and you will not be copy-pasting the same code into every page. More importantly, if you decide to change some underlying functions of your application, you will not have to edit each page as long as you keep the interface to your system base class consistent.

Now lets define what we want our system base class to do. Here is a basic list of features that I will go over in due time:

  • Establish the database connection
  • Define how the page will be laid out and print the HTML
  • Manage authentication and user session information
  • Define all your applications core features

Here is the framework and all of it’s glory:

class_system.php     - The base class which includes the following

|_constants.php      - Application constants

|_functions.php      - Generic functions

|_class_user.php     - Session handling

|_class_template.php - Template handling

|_class_form.php     - Form handling

Using this framework, all of your pages should have this structure:

include "include/class_system.php";

class Page extends SystemBase {

    //your code here

}

$p = new Page();

The idea here is that we want to minimize the time spent on the most common tasks such as creating new pages. In this case, all we have to do is include the base class (which will make sure that all the other necessary dependencies are also included), extend the base class, and simply make an instance of the class to get the ball rolling. This way you can start thinking about what the page will actually do rather than waste time with common tasks.

Configuration Files and Useful Functions

The simplest idea to explain is the need for a file that will contain the applications configuration. We can go with XML or some other even more intricate technology that will inevitably make the framework less efficient but lets start off with the basics. All we really need is a set of constants that define strings such as the database connection or installation paths. These are strings that we would not want to hunt down within each page of the application every time the database password is changed or the application is moved. The file constants.php is just that. The settings that I find most useful are the URL and system paths to the application.

On a similar note, there are some functions that we would like to always make available and I include them in the file functions.php. These functions are not made as methods of the base class because we would like to make them available to all the classes of our application (including those that do not extend the base class). I will go over the functions in this file when we need to use them. As a simple example, I include the me() function, which returns the file name of the current PHP file. (VB 6 programmers will remember that me is a reference to the current form).

function me() {

    return substr($_SERVER['PHP_SELF'], strrpos($_SERVER['PHP_SELF'],'/')+1,

                  strlen($_SERVER['PHP_SELF']));

}

The Base Class

Now lets dissect the class_system.php file line by line. The first thing that we do is call session_start() which starts a new user session if none exists or does nothing otherwise (more on sessions in part 2 of this series). Then we include all the need libraries. There are two things to note about the way this is done. First,require_once is used which will only include the file once and throw an exception if the file is not available (as opposed to include which would only make a warning and proceed with execution of the page). The second thing to note is that absolute paths are used to include the files which are all in the same folder. This is done because we don’t want to have to reconfigure the server to get the application working (by changing the include path used in PHP). Relative paths would not work because the base class will be included from various other pages and the relative path would have to work for each page that includes the base class.

session_start();

$path = dirname(__FILE__);

require_once "$path/constants.php";     //defines

require_once "$path/functions.php";     //generic functions

require_once "$path/class_user.php";    //session handling

require_once "$path/class_template.php";//template handling

require_once "$path/class_form.php";    //form handling

The implementation of the system base class is not at all surprising if you consider the way we intended to use it. Since the code is only executed when an instance of the class is created, we put everything that we want to happen into the class constructor. Also, since the base class will not be able to know exactly how to render each page, we make the methods abstract and let polymorphism take care of the rest (i.e. the derived classes will override the base classes methods.) Here is a list of the methods called from within the constructor:

init()              - initialize the page

authenticate()      - perform authentication

handleFormEvents()  - handle page submits

printPage()         - output the HTML

destroy()           - destroy page (close DB connection)

Unfortunately, PHP 4 does not enforce many OOP principles (note that PHP 5 has a new and much more robust object model). You can get everything to work, such as inheritance and polymorphism, but it takes some effort and some faith. For example, there is no concept of method protection so all methods (and attributes for that matter) are made public. This is a big no-no when it comes to OOP so a common convention is to prefix all methods that are intended to be private with an underscore ( _ ) and then take it on faith that the users of the class will not call these methods. Another problem is that we cannot declare the class to be abstract (i.e. we do not want people to declare instances of the base class but rather force them to inherit from it). We can get around this limitation by
including the following lines at the top of our constructor (you can read
 this article for an in-depth analysis of how this works). The code checks to see if the instance of the class is the base class and throws an exception.

if (!is_subclass_of($this,'SystemBase')) {

    trigger_error('Base instantiation from non subclass',E_USER_ERROR);

    return NULL;

}

Database Access

The application framework should provide a clean interface to your data regardless of the type of SQL server uses. It is also very desirable to have loose coupling between your application and your database backend. So, for example, if you ever decide to change the location of the database or even change the type of SQL server used, you dont want to have to rewrite all your code. Luckily, someone has already tackled this problem for us and all we have to do is use the PEAR::DB module, which provides a consistent interface to several popular database servers. You can read all about it at the PHP Extension and Application Repository and I recommend reading the following PEAR::DB tutorial as well.

Update: The new preferred database library is PEAR::MDB2 which is a merge of PEAR::DB and Metabase libraries. You will find migrating from DB to MDB2 fairly straight forward. There is even a migration guide.

Assuming that the PEAR::DB module is installed and configured correctly, all we need to have a persistent database connection available in every page is a reference to a PEAR::DB object. We will create this object as a member variable in the SystemBase class and create the database connection inside the constructor. We already have the necessary constants to build a DNS string and there is also a function in functions.php that returns a pointer to a new PEAR::DB object.

function &db_connect() {

    require_once 'DB.php';  //pear db class

    PEAR::setErrorHandling(PEAR_ERROR_DIE);

 

    $db_host = DB_HOST;

    $db_user = DB_USER;

    $db_pass = DB_PASS;

    $db_name = DB_NAME;

 

    $dsn = "mysql://$db_user:$db_pass@$db_host/$db_name";

    $db = DB::connect($dsn);

    $db->setFetchMode(DB_FETCHMODE_ASSOC);

    return $db;

}

The function imports the PEAR:DB library if it has not yet been imported, creates a DNS string, and connects to the database. All we have to do now is use this function in the SystemBase constructor as follows: $this->db = db_connect(); and we are done.

Optimization

You may think it is a bit too early to discuss code optimization at this point since we have yet to implement most of the necessary features. Code optimization is more of an art and I will not go into a line-by-line analyses of how we can achieve the same effect faster. The point here is that we already can tell what the major bottlenecks will be so lets nip the problem now before its gets out
of hand. The most obvious performance loss will be due to the persistent database connection that we establish for each page. In fact, if you make a few timing test to benchmark the performance of the framework you will see that establishing the connection alone take more time than everything else combined. Although it is a necessary evil and we will have to pay that price for it when using the database, not every page in our application will have to connect to the database. In fact, not every page will need to print out HTML content (i.e. it may just process the request and redirect). So before we go on lets define a few constants for the base class to indicate that we don’t need a database connection or to print the page. You will simply define these constants in pages that need them.

    define('NO_DB', 1)    if persistent DB connection is not needed

    define('NO_PRINT', 1) if page does not get rendered

Summary

So far, we have laid the foundation for how our application will behave and how the framework will be used. We established an OOP design for the application, defined some constants and function to expedite routine work, and added database support. Read the next part to see how to manage session data and users.

1.     CGI (Common Gateway Interface) was a popular method for using server side code to generate dynamic web pages. Any programming language can be used for CGI as long as it can read system environment variables that are set by the web server to provide information about the page request. Perl has been the language of choice for CGI programming because CGI programs involve a lot of text processing. Unfortunately, CGI does not scale well because each page request requires the server to fork a new process to run the CGI program. mod_perl is a way to reduce the overhead by including Perl as an internal Apache module; however, benchmarks show that PHP (which also runs as an Apache module) is still faster.

2.     The term “free as in beer” is used in the open-source community to distinguish things that cost nothing and peoples rights. The term was originally published in this paper.

 

分享到:
评论

相关推荐

    Getting Started with Twitter Flight

    Getting Started with Twitter Flight offers the reader insight into why Flight was created and how to use it to build performant, powerful web apps from a unique perspective – that of someone who has ...

    Applied.WPF.4.in.Context(第1版)

    Sample Application: Overview and Getting Started Microsoft Expression Blend Creating the Views Adding Controls to the Views The Entity Framework Data Binding Command Handling and Event Routing Testing...

    Getting Started with React Native 无水印pdf 0分

    Learn to design and build a fully-featured application using the newest cutting-edge framework from Facebook Leverage your JavaScript skills to become a native app developer Develop custom UI ...

    Practical.Web.Development.1782175911

    Chapter 1: The World Wide Web Chapter 2: HTML Chapter 3: CSS Chapter 4: JavaScript Chapter 5: PHP Chapter 6: PHP and MySQL Chapter 7: jQuery Chapter 8: Ajax Chapter 9: The History API – Not For...

    Professional Android 4 Application Development

    Professional Android 4 Application Development – Wrox Developers, build mobile Android apps using Android 4 The fast-growing popularity of Android smartphones and tablets creates a huge ...

    Professional Android 4 Application Development 源代码

    Chapter 1: Hello, Android A Little Background What Android Isn't Android: An Open Platform for Mobile Development Native Android Applications Android SDK Features Introducing the Open Handset Alliance...

    Pro Business Application Silverlight4

    You will learn how to take advantage of the power of Silverlight to develop rich and robust business applications, from getting started to deployment, and everything in between. In particular, this ...

    Database Processing Fundamentals, Design, and Implementation (12th Edition).rar

    PART 1 GETTING STARTED Chapter 1:Introduction Chapter Objectives The Characteristics of Databases A Note on Naming Conventions A Database Has Data and Relationships Databases Create Information ...

    Apress.Android.Apps.for.Absolute.Beginners.2nd.edition

    Recently updated to include Android Jelly Bean, Android Apps for Absolute Beginners, Second Edition takes you through the process of getting your first Android apps up and running using plain English...

    Netty in Action.2014(MEAP v08)

    PART 1: GETTING STARTED 1 Netty and Java NIO APIs - FREE 2 Your first Application with Netty - AVAILABLE PART 2: CORE FUNCTIONS / PARTS 3 General design ideas of Netty 4 Transports - AVAILABLE 5 ...

    Building Microservices with Spring.epub

    Getting Started with Spring Microservices begins with an overview of the Spring Framework 5.0, its design patterns, and its guidelines that enable you to implement responsive microservices at scale....

    Beginning iOS 7 Development: Exploring the iOS SDK

    Chapter 1: Welcome to the Jungle Chapter 2: Appeasing the Tiki Gods Chapter 3: Handling Basic Interaction Chapter 4: More User Interface Fun Chapter 5: Autorotation and Autosizing Chapter 6: Multiview...

    Bootstrap 4 responsive web design

    Chapter 1: Getting Started 3 Getting Bootstrap 4 Setting up the framework 5 Folder structure 6 Warming up the sample example 6 Bootstrap required tags 8 Building our first Bootstrap example 10 The ...

    Ember.js.Web.Development.with.Ember.

    Getting Started with Building Ambitious Ember.js Applications with Ember CLI Chapter 2. Understanding Ember.js Object-oriented Patterns Chapter 3. Rendering Using Templates Chapter 4. Managing ...

    CSharp 3.0 With the .NET Framework 3.5 Unleashed(english)

    2 Getting Started with C# and Visual Studio 2008 48 Writing a Simple C# Program 48 Creating a Visual Studio 2008 (VS2008) Project 52 Commenting Code 61 Identifiers and Keywords 64 ...

    Twisted Network Programming Essentials 2nd Edition

    Get started with Twisted, the event-driven networking framework written in Python. With this introductory guide, you’ll learn the key concepts and design patterns to build event-driven client and ...

    Selenium.Testing.Tools.Cookbook.2nd.Edition.178439251

    Chapter 1: Getting Started Chapter 2: Finding Elements Chapter 3: Working with Elements Chapter 4: Working with Selenium API Chapter 5: Synchronizing Tests Chapter 6: Working with Alerts, Frames, and ...

    Spring.Boot.Cookbook.1785284150

    Getting Started with Spring Boot Chapter 2. Configuring Web Applications Chapter 3. Web Framework Behavior Tuning Chapter 4. Writing Custom Spring Boot Starters Chapter 5. Application Testing Chapter...

    ASP.NET.MVC.5.with.Bootstrap.and.Knockout.js.1491914394

    Getting Started Chapter 1. Introduction to MVC Chapter 2. Introduction to Bootstrap Chapter 3. Introduction to Knockout.js Chapter 4. Working with a Database Part II. Working with Data Chapter 5. ...

Global site tag (gtag.js) - Google Analytics