首頁 php教程 php手册 PHP最佳实践

PHP最佳实践

Jun 06, 2016 pm 07:50 PM
php 下面 實踐 文章 最佳

今天下午,我在读下面这篇文章。 虽然名字叫《PHP最佳实践》,但是它主要谈的不是编程规则,而是PHP应用程序的合理架构。 它提供了一种逻辑和数据分离的架构模式,属于MVC模式的一种实践。我觉得,这是很有参考价值的学习资料,类似的文章网上并不多,所以一

PHP最佳实践

  今天下午,我在读下面这篇文章。

  虽然名字叫《PHP最佳实践》,但是它主要谈的不是编程规则,而是PHP应用程序的合理架构。

  它提供了一种逻辑和数据分离的架构模式,属于MVC模式的一种实践。我觉得,这是很有参考价值的学习资料,类似的文章网上并不多,所以一边学习,一边就把它翻译了出来。

  根据自己的理解,我总结了它的MVC模式的实现方式(详细解释见译文):

* 视图层(View):前端网页;

* 逻辑层(Controller):先是页逻辑(Page Controller),负责处理页面请求;然后,调用业务逻辑(Business Controller),实现具体功能;

* 数据层(Model):数据保存在数据库之中,上面有一个数据库抽象层,再上面则是一个"数据访问对象"(DAO),它生成"值对象"(Value Object)。业务逻辑通过DAO,操作值对象。

  =======================================

  PHP最佳实践

  原载:http://www.odi.ch/prog/design/php/guide.php

  译者:阮一峰

  本文给出了PHP程序设计常见问题的解决方法,同时简单描述了PHP应用程序的架构。

  1. php.ini设置

  php.ini控制了解释器的行为,下面的一些设置保证了你的程序有最大的可移植性。

  i. short_open_tag

  ii. asp_tags

  iii. magic_quotes_gpc

  建议在脚本中包含一个全局文件,负责在读取$_GET、$_POST、$_COOKIE变量之前,首先检查这个设置是否打开,如果打开了,这对这些变量应用stripslashes函数。(注:该设置已经在PHP 5.3中被废除。)

  iv. register_globals

  不要依赖这个设置,永远通过全局变量$_GET、$_POST、$_COOKIE去读取GET、POST和COOKIE的值。为了方便起见,建议声明$PHP_SELF = $_SERVER['PHP_SELF']。

  v. file_uploads

  上传文件的最大大小,由下面的设置决定:

* file_uploads必须设为1(默认值),表示允许上传。

* memory_limit必须略大于post_max_size和upload_max_filesize。

* post_max_size和upload_max_filesize要足够大,能满足上传的需要。

  2. 配置文件(configuration file)

  你应该把与应用程序相关的所有配置,写在一个文件里。这样你就能很方便地适应开发环境的变化。配置文件通常包含以下信息:数据库参数、email地址、各类选项、debug和logging输出开关、应用程序常数。

  3. 名称空间(namespace)

  选择类和函数名的时候,必须很小心,避免出现重名。尽可能不要在类以外,放置全局性函数,类对内部的属性和方法,相当于有一层名称空间保护。如果你确实有必要声明全局性函数,那么使用一个前缀,比如dao_factory()、 db_getConnection()、text_parseDate()等等。

  4. 数据库抽象层

  PHP不提供数据库操作的通用函数,每种数据库都有一套自己的函数。你不应该直接使用这些函数,否则一旦改用其他数据库(比如从MySQL 转为Oracle),你就有大麻烦了。而且,数据库抽象层通常比系统本身的数据库函数,更易用一些。

  5. "值对象"(Value Object, VO)

  值对象(VO)在形式上,就像C语言的struct结构。它是一个只包含属性、不包含任何方法(或只包含很少方法)的类。一个值对象,就对应一个实体。它的属性,通常应该与数据库的字段名保持相同。此外,还应该有一个ID属性。

class Person {

var $id, $first_name, $last_name, $email;

}

  6. 数据访问对象(Data Access Object, DAO)

  数据访问对象(DAO)的作用,主要是将数据库访问与其他代码相隔离。DAO应该是可以叠加(stacked)的,这样就有利于将来你再添加数据库缓存。每一个值对象的类,都应该有自己的DAO。

class PersonDAO {
    var $conn;

function PersonDAO(&$conn) {
      $this->conn =& $conn;
    }

function save(&$vo) {
      if ($v->id == 0) {
        $this->insert($vo);
      } else {
        $this->update($vo);
      }
    }

function get($id) {
      #execute select statement
      #create new vo and call getFromResult
      #return vo
    }

function delete(&$vo) {
      #execute delete statement
      #set id on vo to 0
    }

#-- private functions

function getFromResult(&vo, $result) {
      #fill vo from the database result set
    }

function update(&$vo) {
      #execute update statement here
    }

function insert(&$vo) {
      #generate id (from Oracle sequence or automatically)
      #insert record into db
      #set id on vo
    }
  }

  DAO通常应该部署以下方法:

* save:插入或更新一条记录
  * get:取出一条记录
  * delete:删除一条记录

  你可以根据自己的需要,添加其他DAO方法,常见的例子有isUsed()、getTop($n)、find($criteria)。

  但是,所有的DAO方法都应该与数据库操作有关,不应该执行其他操作。DAO只应该对一张表进行基本的select / insert / update,不应该包含业务逻辑。举例来说,PersonDAO就不应该包含向某人发送Email的代码。

  你可以写一个工厂函数,根据不同的类名,返回相应的DAO。

function dao_getDAO($vo_class) {

$conn = db_conn('default'); #get a connection from the pool

switch ($vo_class) {

case "person": return new PersonDAO($conn);

case "newsletter": return new NewsletterDAO($conn);

...

}

}

  7. 自动生成代码

  99%的值对象和DAO代码,可以根据数据库模式(schema)自动生成,前提是你的表和列使用约定的方式进行命名。如果你修改数据库模式,一个自动生成代码的脚本将大大节省你的时间。

  8. 业务逻辑

  业务逻辑直接反映使用者的需要。它们处理值对象,根据业务需要修改值对象的属性,使用DAO与数据库层交互。

class NewsletterLogic {
    function NewsletterLogic() {
      ...
    }

function subscribePerson(&$person) {
      ...
    }

function unsubscribePerson(&$person) {
      ...
    }

function sendNewsletter(&$newsletter) {
      ...
    }
  }

  9. 页逻辑(控制器)

  当一个网页被请求时,页控制器(page controller)就会运行,然后产生输出。控制器的任务,就是将HTTP请求转化成业务对象(business object),然后调用相应的业务逻辑,生成展示输出的对象。

  页逻辑依次执行以下步骤(请参照后面的PageController类的代码):

i. 假定页面请求之中,包含一个cmd参数。

ii. 根据cmd参数的值,执行相应的动作。

iii. 验证页面返回的值,生成一个值对象。

iv. 针对值对象,执行业务逻辑。

v. 如果有必要,可以导向另一个页面。

vi. 收集必要的数据,输出结果。

  注意:可以编写一个工具函数(utility function),处理GET或POST值,当有的变量没有赋值时,提供一个默认值。页逻辑不包含HTML代码。

class PageController {
    var $person; #$person is used by the HTML page
    var $errs;

function PageController() {
      $action = Form::getParameter('cmd');
      $this->person = new Person();
      $this->errs = array();

if ($action == 'save') {
        $this->parseForm();
        if (!this->validate()) return;

NewsletterLogic::subscribe($this->person);

header('Location: confirmation.php');
        exit;
      }
    }

function parseForm() {
      $this->person->name = Form::getParameter('name');
      $this->person->birthdate = Util::parseDate(Form::getParameter('birthdate');
      ...
    }

function validate() {
      if ($this->person->name == '') $this->errs['name'] = FORM_MISSING;
      #FORM_MISSING is a constant
      ...
      return (sizeof($this->errs) == 0);
    }
  }

  10. 表现层(Presentation Layer)

  最顶层的页面包含实际的HTML代码。这个页面需要的所有业务对象(business object),由页逻辑提供。

  这个页面先读取业务对象的属性,然后将它们转换成HTML格式。

    require_once('control/ctl_person.inc.php'); #the page controller
    $c =& new PageController();
  ?>


  


  

    
     value="person->name); ?>">
    
  

  
  

  11. 本地化(Localization)

  本地化意味着要支持多种语言,这个比较麻烦,你无非有两种方法可以选择:

A) 准备多重页面。

B) HTML页面中去除特定语言相关的内容。

  一般来说,A方法用得比较多,因为B方法会使得HTML页面的可读性很差。

  所以,你可以先写完一种语言的页面,然后把它们进行拷贝,用某种命名法区别不同语言的版本,比如index_fr.php表示index.php的法语版。

  为了保存用户的语言选择,你有几种方法:

A) 将语言设定保存在一个session变量或cookie之中;

B) 从HTTP头中读取locale值;

C) 把语言设定作为一个参数,追加在每个URL后面。

  看上去A方法比C方法容易得多(虽然session和cookie都有过期的问题),而B方法只能作为A或C的补充。

  最后不要忘了,数据库中的字段也必须进行本地化。

  12. 安装位置

  有时候你需要知道程序的根目录在哪里,但是$_SERVER['DOCUMENT_ROOT']只是web服务器的根目录,如果你的程序安装在它的某个子目录之中,PHP没法自动知道。

  你可以定义一个全局变量$ROOT,它的值就是程序的根目录,然后把它包含在每一个脚本文件中。那么,你要包含某个文件,就这样写require_once("$ROOT/lib/base.inc.php");。

  13. 目录结构

  首先,每个类都应该有自己的独立文件,还必须有一套文件名的命名规则(naming convention)。

  软件的目录结构可以采用如下形式:

/ 根目录。浏览器从这个页面开始访问。

/lib/ 包含全局变量(base.inc.php)和配置文件(config.inc.php)。

/lib/common/ 包含其他项目也可以共用的库,比如数据库抽象层。

/lib/model/ 包含值对象类。

/lib/dao/ 包含数据访问对象(DAO)类,以及DAO工厂函数。

/lib/logic/ 包含业务逻辑类。

/parts/ 包含HTML模板文件。

/control/ 包含页逻辑。对于大型程序来说,这个目录下面可能还有子目录(比如admin/, /pub/)。

  base.inc.php文件中,应该按照以下顺序添加包含文件:

* /lib/common之中经常使用的类(比如数据库层)。

* 配置文件;

* /lib/model之中所有类;

* /lib/dao的之中所有类。

  至于那些存放图片、上传文件的目录,这里就省略了。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1317
25
PHP教程
1268
29
C# 教程
1246
24
在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

See all articles