`
congfeng02
  • 浏览: 200063 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

PHP框架设计入门之一:布局篇

阅读更多

PHP框架设计入门之一:布局篇

(本文译自 Leon Bukhman 的 PHP Application Framework Design ,10/13/05)

引用:

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.

本文讲述了如何用PHP来做一个完整的应用框架设计。我们假定读者已有PHP的工作知识。系列的此部分讲述框架的应用和类的架构。接下来的部分将覆盖从会话处理到创造页面模板的内容。

引用:

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.

类的架构

在贯彻大项目时,我喜欢先画出类图,并看看怎样把各部分组件拼合在一起。幸亏,PHP从版本4开始具备了相应的功能支持面向对象编程。尽管本文是用PHP4写的,但你同样能用PHP5来实现所有的功能(在本文写作时PHP5还正待发布)。面向对象编程和设计的内容超出了本文的范围,希望读者至少在一定程度上熟识其相关内容。因为OOP是开发大型应用和web应用开发的关键,这点是毫无例外的。

引用:

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 application’s core features

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

现在确定一下基类要做什么。下面是准备讨论的一些基本特征:

建立数据库连接

确定页面布局和显示HTML

鉴证和用户会话信息管理

定义应用核心要素

下面是框架及其要素的实现:

复制内容到剪贴板

代码:

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 application’s configuration. We can go with XML or some other even more intricate technology that will inevitably make the framework less efficient but let’s 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.

为简单解释起见,先建立一个包含应用配置的文件。我们可以用XML或其他一些复杂的技术来做,不过这样框架的效率就会降低了,所以我们从最基本的技术开始。我们现在需要的只是一些常数用来定义像数据库连接或安装路径之类的字符串。我们不想在每次改数据库密码或者改变应用路径时都要在每页里翻来倒去的寻找修改的地方。只要把 constants.php 这个文件找出来就行了。通常我认为最有用的设定是URL和应用的系统路径。

引用:

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).

同样的,有一些我们随时需要用到的函数,我把它们放在functions.php文件里。我们没有把这些函数作为基类的方法,是因为应用里所有的类都可能用到它们 (包括那些没有扩展基类的)。在需要用到时,我再讲这个函数。现在作为一个简单的例子,先包括一个me()函数,它将返回现在PHP文件的文件名。

复制内容到剪贴板

代码:

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.

现在我们一行一行地来讨论system.php这个类。第一行调用了session_start() ,如果会话(session)不存在,它就打开一个新的会话(第二部分有更多内容)。然后把所有需要的库文件包括进来。这里要注意两件事情:第一,使用 require_once 只在第一次把文件包括进来,如果没有此文件,就抛出个异常 (而用include则之显示一个警告信息)。第二,把同一个文件夹里的所有文件都包括进来的绝对路径。这样做是因为我们不想为了应用而再配置服务器 (作PHP里改变包括的路径)。用相对路径行不通,因为基类会在各种不同的页面里用到,要为用到基类的每一页设定相对路径是很困难的。

复制内容到剪贴板

代码:

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

(译注:在PHP5我们可以用 __autoload()的方法。)

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’s 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 anew 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. Thisis 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 anunderscore ( _ ) 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 anexception.

复制内容到剪贴板

代码:

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 SQLserver 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 don’t 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.

无论使用什么类型的SQL数据库,应用框架都应该对数据提供一个清晰的接口。在应用和数据库后台之间,最好能保持松散的偶合。比如说,如果用户打算要改变数据库的地理位置,或甚至于要改变SQL数据库的类型,你也用不着去改写代码。幸好,已经有人为我们处理好了这些问题了,我们要做的就是使用PEAR::DB模块,它对一些通用的数据库服务器都提供了统一的接口。你可以在”PHP扩展和应用分类“ 里阅读这部分,我建议大家也阅读下面的PEAR::DB辅导部分。

引用:

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 System Base 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.

假如PEAR::DB模块已经正确地安装和配置好了,在每一页里需要用到一个持续的数据库连接时,我们要做的就是引用PEAR::DB对象。我们将在系统基类里创建此对象作为一个成员变量,并在构造器里建立数据库的连接。我们已经有了建立DNS字串所需要的常量,并且在 functions.php 里也有一个函数可以返回一个指向新PEAR::DB 对象的指针。

复制内容到剪贴板

代码:

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 System Base constructor as follows: $this->db = db_connect(); and we are done.

此函数在没有引进PEAR:DB库时予以引进,创建一个DNS字串,并连接数据库。我们要做的就是在系统基类的构架器里像这样:$this->db = db_connect(); 来使用此函数,而我们已经这样做了。

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 let’s 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 toprint 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 thatneed 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 be haveand 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.

分享到:
评论

相关推荐

    PHP快速入门

    而ThinkPHP作为一个国内广泛使用的PHP框架,更是为PHP开发提供了高效、便捷的解决方案。本教程将通过实例介绍如何快速入门PHP,尤其是基于ThinkPHP框架进行数据库操作。 首先,了解PHP基础是入门的第一步。PHP是一...

    yii框架入门实例

    - **作者背景**:由美国华人xueqiang开发,其曾是Prado框架的核心开发成员之一,拥有丰富的框架开发经验。 - **发展历程**:自2008年1月至现在,Yii经历了多个版本的迭代,最新版本为1.1.13。 - **设计理念**:借鉴...

    yii快速入门教程--一个非常好的php框架

    ### Yii快速入门教程知识点 #### 一、基本概念 **1. 入口文件** - **功能**: 入口文件是整个Yii应用的第一个脚本,它负责加载Yii框架以及初始化应用。 - **内容**: 通常包含如下代码: ```php <?php $yii = ...

    PHP-Smarty框架入门视频

    Smarty是一个广泛使用的PHP模板引擎,它将业务逻辑与呈现逻辑分离,使得开发者可以更专注于页面设计和用户体验,而不用关心后端PHP代码的复杂性。本视频教程将引导初学者进入Smarty的世界,通过一个简单易懂的小demo...

    个人导航项目-php框架

    1. Laravel:Laravel是最流行的PHP框架之一,以其优雅的语法和强大的功能受到开发者的青睐。它提供了丰富的工具如Eloquent ORM(对象关系映射)、Artisan命令行工具以及一套完整的路由和中间件系统。 2. Symfony:...

    新手怎样学习PHP网站建设(入门篇).rar

    8. **PHP框架介绍**:随着经验的积累,你可能会接触到PHP的一些流行框架,如Laravel、CodeIgniter或Symfony,它们可以简化开发过程,提高代码质量。 9. **最佳实践和安全性**:了解如何编写安全的PHP代码,避免SQL...

    韩顺平PHP从入门到精通全套教程

    - **HTML介绍与运行原理**:HTML(HyperText Markup Language),即超文本标记语言,是构成网页的基础语言之一。学习HTML的基础知识,包括其运行原理、文档结构以及如何通过浏览器解析显示。 - **HTML文档结构**:...

    asp入门教程:一步一步学ASP

    本教程“asp入门教程:一步一步学ASP”旨在帮助初学者了解并掌握ASP的基本概念、语法和应用,通过使用Dreamweaver这一流行的网页设计工具,实践构建一个简单的ASP留言簿。 1. ASP基础: ASP的核心是脚本语言,通常...

    入门教程PHP (最基础的PHP

    标题“入门教程PHP (最基础的PHP)”与描述“入门教程PHP 最基础的PHP”强调了该教程面向的是PHP初学者,旨在提供最基础的PHP知识,帮助学习者快速入门并掌握PHP的基础概念和技能。 #### 第一章:PHP简介 **知识点...

    Dreamweaver8+PHP动态网站开发从入门到精通-MXP

    8. **PHP框架简介**:可能简述一些流行的PHP框架,如Laravel或CodeIgniter,以及它们如何简化开发过程。 通过这个教程,读者将能够结合Dreamweaver的可视化编辑工具和PHP的动态功能,创建出功能强大的动态网站。...

    基于GenesisSample230的Genesis框架的入门主题

    10. **插件兼容性**:Genesis框架设计时考虑到了与其他插件的配合,因此学习如何编写与各种插件兼容的主题代码非常重要。这包括正确地处理钩子和优先级,以及遵循插件开发的最佳实践。 通过深入研究Genesis Sample ...

    PHP初学入门必备(全套资料海量)

    此外,"CakePHP-1[1].3.chm"和"CakePHP1[1].2手册.CHM"是关于CakePHP框架的手册, CakePHP是一个基于MVC(模型-视图-控制器)架构的PHP框架,它的使用可以极大地提高开发效率,让初学者快速构建动态网站。...

    韩顺平PHP从入门到精通笔记

    - PHP框架:如Laravel、Symfony等框架的使用,提高开发效率。 - 安全实践:防止SQL注入、XSS攻击等,确保应用程序的安全性。 - PHP性能优化:缓存技术、代码优化策略,提升网站性能。 通过韩顺平的PHP从入门到精通...

    php框架 doitphp框架

    PHP框架是预编写的一系列代码库,它们提供了统一的开发模式,有助于提高开发效率,降低项目的维护成本,同时也强化了代码的可复用性和安全性。 **1. doitphp框架介绍** DoitPHP框架以其易学易用的特点,吸引了许多...

    PHP的Yii框架入门使用教程

    Yii框架是PHP开发中的一个高性能、基于组件的MVC(Model-View-Controller)框架,专为高效构建Web应用程序而设计。本教程将引导你入门Yii框架,从安装到建立第一个应用,逐步了解其基本结构和功能。 首先,让我们...

    PHP3.1快速入门系列教程

    - **定义与特点**:ThinkPHP3.1是一个轻量级的PHP开发框架,采用MVC(Model-View-Controller)架构模式,遵循Apache2开源协议发布。它以其简洁实用的设计理念而著称,既注重性能又重视用户体验。 - **适用场景**:...

    ThinkPHP3.1新手入门.zip

    《ThinkPHP3.1新手入门》是一份专为初学者设计的教程,旨在帮助开发者快速掌握ThinkPHP3.1框架的基础知识和应用技巧。ThinkPHP3.1是ThinkPHP框架的一个较早版本,但它的核心理念和基础结构对于理解整个ThinkPHP系列...

    PHP入门资料

    本资源包是为初学者设计的PHP入门资料,旨在帮助你快速掌握PHP基础知识,同时结合HTML和CSS,构建动态、交互式的网页。下面我们将深入探讨PHP、HTML和CSS这三种技术的基本概念及它们在Web开发中的应用。 1. PHP...

    thinkphp学习笔记入门到深入篇

    【ThinkPHP学习笔记入门到深入篇】 ThinkPHP是一款基于PHP的开源快速开发框架,它以其简洁的代码结构、高效的性能和强大的功能深受开发者喜爱。这篇笔记涵盖了从基础到深入的多个方面,旨在帮助初学者迅速掌握...

Global site tag (gtag.js) - Google Analytics