目錄
不同文件构建PHP程序的方式
首頁 php教程 php手册 不同文件构建PHP程序的方式

不同文件构建PHP程序的方式

Jun 13, 2016 am 09:16 AM
php 不同 內容 文件 方式 建構 用的 程式 計劃

不同文件构建PHP程序的方式

       以下为引用的内容:

  如果计划让其他人或公司可以使用您的 php 应用程序,需要确保该程序是可配置的。至少,要允许用户以一种安全的方式设置数据库登录及密码,从而使其中的材料不会对外公开。

  本文展示了几种用于存储配置设置及编辑这些设置的技术。另外,文中也为哪些元素需要设为可配置以及如何避免陷入配置过度或者配置不足的困境提供了指导。

  使用 INI 文件进行配置

  PHP 内建了对配置文件的支持。这是通过 php.ini 文件这样的初始化文件(INI)机制实现的,在 php.ini 文件中定义了数据库连接超时或会话如何存储等常量。如果愿意的话,可以在这个 php.ini 文件中为应用程序定制配置。为了说明,我将下列代码行添加到 php.ini 文件中。

  myapptempdir=foo

  然后,我编写了一个小 PHP 脚本来读取这个配置项,如清单 1 所示。

  清单 1. ini1.php

  

  function get_template_directory()

  {

  $v = get_cfg_var( “myapptempdir” );

  return ( $v == null ) ? “tempdir” : $v;

  }

  echo( get_template_directory().” ” );

  ?>

  当在命令行中运行这段代码时,得到如下结果:

  % php ini1.php

  foo

  %

  太棒了。但为什么不能用标准的 INI 函数来获取 myapptempdir 配置项的值呢?我研究了一下,发现在大多数情况下,定制配置项不能使用这些方法来获取。然而,使用 get_cfg_var 函数却是可以访问的。

  为使这个方法更加简单,将对变量的访问封装在第二个函数中,该函数使用配置键名及一个缺省值作为参数,如下所示。

  清单 2. ini2.php

  function get_ini_value( $n, $dv )

  {

  $c = get_cfg_var( $n );

  return ( $c == null ) ? $dv : $c;

  }

  function get_template_directory()

  {

  return get_ini_value( “myapptempdir”, “tempdir” );

  }

  这是对如何访问 INI 文件的一个很好的概括,所以,如果要使用一个不同的机制或将这个 INI 文件存储到其他位置,就不需要为更改大量的函数而大费周折。

  我不推荐使用 INI 文件作为应用程序的配置,这有两个理由。首先,虽然这样做较容易读取 INI 文件,但却几乎不可能安全地写 INI 文件。所以这样做只适合于只读配置项。第二,php.ini 文件在服务器的所有应用程序上共享,所以我认为特定于应用程序的配置项不应该写在该文件中。

  需要对 INI 文件了解什么呢?最重要的是如何重置 include 路径来添加配置项,如下所示。

  清单 3. ini3.php

  

  echo( ini_get(”include_path”).” ” );

  ini_set(”include_path”,

  ini_get(”include_path”).”:./mylib” );

  echo( ini_get(”include_path”).” ” );

  ?>

  在本例中,我将我的本地 mylib 目录添加到了 include 路径中,所以能够从该目录中 require PHP 文件,而不需要将该路径添加到 require 语句中。

  PHP 中的配置

  通常对于在 INI 文件中存储配置条目的一个替代办法是使用一个简单的 PHP 脚本来保持数据。如下是一个样例。

  清单 4. config.php

  

  # Specify the location of the temporary directory

  #

  $TEMPLATE_DIRECTORY = “tempdir”;

  ?>

  使用该常量的代码如下所示。

  清单 5. php.php

  

  require_once ‘config.php’;

  function get_template_directory()

  {

  global $TEMPLATE_DIRECTORY;

  return $TEMPLATE_DIRECTORY;

  }

  echo( get_template_directory().” ” );

  ?>

  该代码首先包含配置文件(config.php),接着就可以直接使用这些常量了。

  使用这项技术有很多优势。首先,如果某些人仅仅浏览 config.php 文件,该页面是空白的。所以可以将 config.php 放到相同的文件中,并作为 Web 应用程序的根。第二,在任何编辑器中都可编辑,并且在一些编辑器中甚至具备语法着色及语法检查功能。

  这项技术的缺点是,这是一个像 INI 文件一样的只读技术。将数据从此文件中提取出来是轻而易举的,但在该 PHP 文件中调整数据却很困难,在一些情况下甚至是不可能的。

  下面的替代方法显示了如何编写在本质上既可读又可写的配置系统。

  文本文件

  前面的两个例子对于只读配置条目都是合适的,但对于既读又写的配置参数来说又如何呢?首先,看看清单 6 中的文本配置文件。

  清单 6. config.txt

  # My application’s configuration file

  Title=My App

  TemplateDirectory=tempdir

  这是同 INI 文件相同的文件格式,但我自己编写了辅助工具。为此,我创建了自己的 Configuration 类,如下所示。

  清单 7. text1.php

  

  class Configuration

  {

  PRivate $configFile = ‘config.txt’;

  private $items = array();

  function __construct() { $this->parse(); }

  function __get($id) { return $this->items[ $id ]; }

  function parse()

  {

  $fh = fopen( $this->configFile, ‘r’ );

  while( $l = fgets( $fh ) )

  {

  if ( preg_match( ‘/^#/’, $l ) == false )

  {

  preg_match( ‘/^(.*?)=(.*?)$/’, $l, $found );

  $this->items[ $found[1] ] = $found[2];

  }

  }

  fclose( $fh );

  }

  }

  $c = new Configuration();

  echo( $c->TemplateDirectory.” ” );

  ?>

  该代码首先创建了一个 Configuration 对象。该构造函数接下来读取 config.txt 并用解析过的文件内容来设置局部变量 $items。

  该脚本随后寻找 TemplateDirectory,这并没有在对象中直接定义。因此,使用设置成 ‘TemplateDirectory’ 的 $id 来调用神奇的 __get 方法,__get 方法针对该键返回 $items 数组中的值。

  这个 __get 方法特定于 PHP V5 环境,所以此脚本必须在 PHP V5 下运行。实际上,本文中所有的脚本都需要在 PHP V5 下运行。

  当在命令行运行此脚本时,能看到下列结果:

  http://www.knowsky.com/php.asp

  % php text1.php

  tempdir

  %

  一切都在预料之中,该对象读取 config.txt 文件,然后为 TemplateDirectory 配置项获得正确的值。

  但对于设置一个配置值,应该怎么做呢?在此类中建立一个新方法及一些新的测试代码,就能够得到这个功能,如下所示。

  清单 8. text2.php

  

  class Configuration

  {

  …

  function __get($id) { return $this->items[ $id ]; }

  function __set($id,$v) { $this->items[ $id ] = $v; }

  function parse() { … }

  }

  $c = new Configuration();

  echo( $c->TemplateDirectory.” ” );

  $c->TemplateDirectory = ‘foobar’;

  echo( $c->TemplateDirectory.” ” );

  ?>

  现在,有了一个 __set 函数,它是 __get 函数的 “堂兄弟”。该函数并不为一个成员变量获取值,当要设置一个成员变量时,才调用这个函数。底部的测试代码设置值并打印出新值。

  下面是在命令行中运行此代码时出现的结果:

  % php text2.php

  tempdir

  foobar

  %

  太好了!但如何能将它存储到文件中,从而将使这个改动固定下来呢?为此,需要写文件并读取它。用于写文件的新函数,如下所示。

  清单 9. text3.php

  

  class Configuration

  {

  …

  function save()

  {

  $nf = ”;

  $fh = fopen( $this->configFile, ‘r’ );

  while( $l = fgets( $fh ) )

  {

  if ( preg_match( ‘/^#/’, $l ) == false )

  {

  preg_match( ‘/^(.*?)=(.*?)$/’, $l, $found );

  $nf .= $found[1].”=”.$this->items[$found[1]].” ”;

  }

  else

  {

  $nf .= $l;

  }

  }

  fclose( $fh );

  copy( $this->configFile, $this->configFile.’.bak’ );

  $fh = fopen( $this->configFile, ‘w’ );

  fwrite( $fh, $nf );

  fclose( $fh );

  }

  }

  $c = new Configuration();

  echo( $c->TemplateDirectory.” ” );

  $c->TemplateDirectory = ‘foobar’;

  echo( $c->TemplateDirectory.” ” );

  $c->save();

  ?>

  新的 save 函数巧妙地操作 config.txt。我并没有仅用更新过的配置项重写文件(这样会移除掉注释),而是读取了这个文件并灵活地重写了 $items 数组中的内容。这样的话,就保留了文件中的注释。

  在命令行运行该脚本并输出文本配置文件中的内容,能够看到下列输出。

  清单 10. 保存函数输出

  % php text3.php

  tempdir

  foobar

  % cat config.txt

  # My application’s configuration file

  Title=My App

  TemplateDirectory=foobar

  %

  原始的 config.txt 文件现在被新值更新了。

  xml 配置文件

  尽管文本文件易于阅读及编辑,但却不如 XML 文件流行。另外,XML 有众多适用的编辑器,这些编辑器能够理解标记、特殊符号转义等等。所以配置文件的 XML 版本会是什么样的呢?清单 11 显示了 XML 格式的配置文件。

  清单 11. config.xml

  

  

  

  tempdir

  

  清单 12 显示了使用 XML 来装载配置设置的 Configuration 类的更新版。

  清单 12. xml1.php

  

  class Configuration

  {

  private $configFile = ‘config.xml’;

  private $items = array();

  function __construct() { $this->parse(); }

  function __get($id) { return $this->items[ $id ]; }

  function parse()

  {

  $doc = new DOMDocument();

  $doc->load( $this->configFile );

  $cn = $doc->getElementsByTagName( “config” );

  $nodes = $cn->item(0)->getElementsByTagName( “*” );

  foreach( $nodes as $node )

  $this->items[ $node->nodeName ] = $node->nodeValue;

  }

  }

  $c = new Configuration();

  echo( $c->TemplateDirectory.” ” );

  ?>

  看起来 XML 还有另一个好处:代码比文本版的代码更为简洁、容易。为保存这个 XML,需要另一个版本的 save 函数,将结果保存为 XML 格式,而不是文本格式。

  清单 13. xml2.php

  …

  function save()

  {

  $doc = new DOMDocument();

  $doc->formatOutput = true;

  $r = $doc->createElement( “config” );

  $doc->appendChild( $r );

  foreach( $this->items as $k => $v )

  {

  $kn = $doc->createElement( $k );

  $kn->appendChild( $doc->createTextNode( $v ) );

  $r->appendChild( $kn );

  }

  copy( $this->configFile, $this->configFile.’.bak’ );

  $doc->save( $this->configFile );

  }

  …

  这段代码创建了一个新的 XML 文档对象模型(Document Object Model ,DOM),然后将 $items 数组中的所有数据都保存到这个模型中。完成这些以后,使用 save 方法将 XML 保存为一个文件。

  使用数据库

  最后的替代方式是使用一个数据库保存配置元素的值。那首先要用一个简单的模式来存储配置数据。下面是一个简单的模式。

  清单 14. schema.sql

  DROP TABLE IF EXISTS settings;

  CREATE TABLE settings (

  id MEDIUMINT NOT NULL AUTO_INCREMENT,

  name TEXT,

  value TEXT,

  PRIMARY KEY ( id )

  );

  这要求进行一些基于应用程序需求的调整。例如,如果想让配置元素按照每个用户进行存储,就需要添加用户 ID 作为额外的一列。

  为了读取及写入数据,我编写了如图 15 所示的更新过的 Configuration 类。

  清单 15. db1.php

  

  require_once( ‘DB.php’ );

  $dsn = ‘MySQL://root:passWord@localhost/config’;

  $db =& DB::Connect( $dsn, array() );

  if (PEAR::isError($db)) { die($db->getMessage()); }

  class Configuration

  {

  private $configFile = ‘config.xml’;

  private $items = array();

  function __construct() { $this->parse(); }

  function __get($id) { return $this->items[ $id ]; }

  function __set($id,$v)

  {

  global $db;

  $this->items[ $id ] = $v;

  $sth1 = $db->prepare( ‘DELETE FROM settings WHERE name=?’ );

  $db->execute( $sth1, $id );

  if (PEAR::isError($db)) { die($db->getMessage()); }

  $sth2 = $db->prepare(

  ‘INSERT INTO settings ( id, name, value ) VALUES ( 0, ?, ? )’ );

  $db->execute( $sth2, array( $id, $v ) );

  if (PEAR::isError($db)) { die($db->getMessage()); }

  }

  function parse()

  {

  global $db;

  $doc = new DOMDocument();

  $doc->load( $this->configFile );

  $cn = $doc->getElementsByTagName( “config” );

  $nodes = $cn->item(0)->getElementsByTagName( “*” );

  foreach( $nodes as $node )

  $this->items[ $node->nodeName ] = $node->nodeValue;

  $res = $db->query( ‘SELECT name,value FROM settings’ );

  if (PEAR::isError($db)) { die($db->getMessage()); }

  while( $res->fetchInto( $row ) ) {

  $this->items[ $row[0] ] = $row[1];

  }

  }

  }

  $c = new Configuration();

  echo( $c->TemplateDirectory.” ” );

  $c->TemplateDirectory = ‘new foo’;

  echo( $c->TemplateDirectory.” ” );

  ?>

  这实际上是一个混合的文本/数据库解决方案。请仔细观察 parse 方法。该类首先读取文本文件来获取初始值,然后读取数据库,进而将键更新为最新的值。在设置一个值后,键就从数据库中移除掉,并添加一条具有更新过的值的新记录。

  观察 Configuration 类如何通过本文的多个版本来发挥作用是一件有趣的事,该类能从文本文件、XML 及数据库中读取数据,并一直保持相同的接口。我鼓励您在开发中也使用具有相同稳定性的接口。对于对象的客户机来说,这项工作具体是如何运行的是不明确的。关键的是对象与客户机之间的契约。

  什么是配置及怎样配置

  在配置过多的配置选项与配置不足间找一个适当的中间点是一件困难的事。可以肯定的是,任何数据库配置(例如,数据库名称、数据库用户用及密码)都应该是可配置的。除此之外,我还有一些基本的推荐配置项。

  在高级设置中,每一个特性都应该有一个独立的启用/禁用选项。根据其对应用程序的重要性来允许或禁用这些选项。例如,在一个 Web 论坛应用程序中,延时特性在缺省状态下是启用的。但电子邮件通知在缺省状态下却是禁用的,因为这似乎需要定制。

  用户界面(UI)选项全应该设置到一个位置上。界面的结构(例如,菜单位置、额外的菜单项、链接到界面特定元素的 URL、使用的 logo,诸如此类)全应该设置到一个单一位置上。我强烈地建议不要将字体、颜色或样式条目指定为配置项。这些都应该通过层叠样式表(Cascading Style Sheets,CSS)来设置,且配置系统应该指定使用哪个 CSS 文件。CSS 是设置字体、样式、颜色等等的一种有效且灵活的方式。有许多出色的 CSS 工具,您的应用程序应该很好地利用 CSS,而不是试图自行设置标准。

  在每一个特性中,我推荐设置 3 到 10 个配置选项。这些配置选项应该以一种意义明显的方式命名。如果配置选项能够通过 UI 设置,在文本文件、XML 文件及数据库中的选项名称应该直接同界面元素的标题相关。另外,这些选项全应该有明确的缺省值。

  总的来说,下面这些选项应该是可配置的:电子邮件地址、CSS 所使用的东西、从文件中引用的系统资源的位置以及图形元素的文件名。

  对于图形元素,您也许想要创建一个名为皮肤 的独立的配置文件类型,该类型中包含了对配置文件的设置,包括 CSS 文件的位置、图形的位置及这些类型的东西。然后,让用户在多种皮肤文件中进行挑选。这使得对应用程序外观和感觉的大规模更改变得简单。这也同样为用户提供了一个机会,使应用程序能够在不同的产品安装间更换皮肤。本文并不涵盖这些皮肤文件,但您在这里学到的基础知识将会使对皮肤文件的支持变得更加简单。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡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)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

在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中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

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

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

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魔術方法(__ -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 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

See all articles