|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
HTML中的任何元素都要亲自实践,只有明白了什么元素会起到什么效果之后,你才会记忆深刻,而一味的啃书,绝对是不行的,我想大部分新手之所以觉得概念难学,大部分是一个字“懒”,懒是阻止进步的最大敌人,所以克服掉懒的习惯,才能更快的学好一样东西。 <P> 本文举例申明了创立可设置装备摆设 PHP 使用法式的几种办法。文中也切磋了使用法式中幻想的设置装备摆设点,并在使用法式过度可设置装备摆设和过度关闭之间追求一个均衡点。
假如企图让其别人或公司可使用您的 PHP 使用法式,需求确保该法式是可设置装备摆设的。最少,要答应用户以一种平安的体例设置数据库登录及暗码,从而使个中的资料不会对外公然。
本文展现了几种用于存储设置装备摆设设置及编纂这些设置的手艺。别的,文中也为哪些元素需求设为可设置装备摆设和若何防止堕入设置装备摆设过度或设置装备摆设缺乏的窘境供应了指点。
利用 INI 文件停止设置装备摆设
PHP 内建了对设置装备摆设文件的撑持。这是经由过程 php.ini 文件如许的初始化文件(INI)机制完成的,在 php.ini 文件中界说了数据库毗连超时或会话若何存储等常量。假如情愿的话,可以在这个 php.ini 文件中为使用法式定制设置装备摆设。为了申明,我将以下代码行添加到 php.ini 文件中。
myapptempdir=foo
然后,我编写了一个小 PHP 剧本来读取这个设置装备摆设项,如清单 1 所示。
清单 1. ini1.php
<?php
function get_template_directory()
{
$v = get_cfg_var( "myapptempdir" );
return ( $v == null ) ? "tempdir" : $v;
}
echo( get_template_directory()."\n" );
?>
当在号令行中运转这段代码时,失掉以下了局:
% 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
<?php
echo( ini_get("include_path")."\n" );
ini_set("include_path",
ini_get("include_path").":./mylib" );
echo( ini_get("include_path")."\n" );
?>
在本例中,我将我的当地 mylib 目次添加到了 include 途径中,所以可以从该目次中 require PHP 文件,而不需求将该途径添加到 require 语句中。
PHP 中的设置装备摆设
凡是关于在 INI 文件中存储设置装备摆设条目标一个替换举措是利用一个复杂的 PHP 剧本来坚持数据。以下是一个样例。
清单 4. config.php
<?php
# Specify the location of the temporary directory
#
$TEMPLATE_DIRECTORY = "tempdir";
?>
利用该常量的代码以下所示。
清单 5. php.php
<?php
require_once 'config.php';
function get_template_directory()
{
global $TEMPLATE_DIRECTORY;
return $TEMPLATE_DIRECTORY;
}
echo( get_template_directory()."\n" );
?>
该代码起首包括设置装备摆设文件(config.php),接着就能够直接利用这些常量了。
利用这项手艺有良多优势。起首,假如某些人仅仅阅读 config.php 文件,该页面是空白的。所以可以将 config.php 放到不异的文件中,并作为 Web 使用法式的根。第二,在任何编纂器中都可编纂,而且在一些编纂器中乃至具有语法着色及语法反省功效。
这项手艺的弱点是,这是一个像 INI 文件一样的只读手艺。将数据从此文件中提掏出来是垂手可得的,但在该 PHP 文件中调剂数据却很坚苦,在一些情形下乃至是不成能的。
上面的替换办法显示了若何编写在实质上既可读又可写的设置装备摆设体系。
<P> 文本文件
后面的两个例子关于只读设置装备摆设条目都是适合的,但关于既读又写的设置装备摆设参数来讲又若何呢?起首,看看清单 6 中的文本设置装备摆设文件。
清单 6. config.txt
# My application's configuration file
Title=My App
TemplateDirectory=tempdir
这是同 INI 文件不异的文件格局,但我本人编写了帮助东西。为此,我创立了本人的 Configuration 类,以下所示。
清单 7. text1.php
<?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."\n" );
?>
该代码起首创立了一个 Configuration 对象。该机关函数接上去读取 config.txt 并用解析过的文件内容来设置部分变量 $items。
该剧本随后寻觅 TemplateDirectory,这并没有在对象中直接界说。因而,利用设置成 'TemplateDirectory' 的 $id 来挪用奇异的 __get 办法,__get 办法针对该键前往 $items 数组中的值。
这个 __get 办法特定于 PHP V5 情况,所以此剧本必需在 PHP V5 下运转。实践上,本文中一切的剧本都需求在 PHP V5 下运转。
当在号令交运行此剧本时,能看到以下了局:
% php text1.php
tempdir
%
一切都在意料当中,该对象读取 config.txt 文件,然后为 TemplateDirectory 设置装备摆设项取得准确的值。
但关于设置一个设置装备摆设值,应当怎样做呢?在此类中创立一个新办法及一些新的测试代码,就可以够失掉这个功效,以下所示。
清单 8. text2.php
<?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."\n" );
$c->TemplateDirectory = 'foobar';
echo( $c->TemplateDirectory."\n" );
?>
如今,有了一个 __set 函数,它是 __get 函数的 “从兄弟”。该函数其实不为一个成员变量获得值,当要设置一个成员变量时,才挪用这个函数。底部的测试代码设置值并打印出新值。
上面是在号令行中运转此代码时呈现的了局:
% php text2.php
tempdir
foobar
%
太好了!但若何能将它存储到文件中,从而将使这个修改固定上去呢?为此,需求写文件并读取它。用于写文件的新函数,以下所示。
清单 9. text3.php
<?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]]."\n";
}
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."\n" );
$c->TemplateDirectory = 'foobar';
echo( $c->TemplateDirectory."\n" );
$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 文件如今被新值更新了。
<P> XML 设置装备摆设文件
虽然文本文件易于浏览及编纂,但却不如 XML 文件盛行。别的,XML 有浩瀚合用的编纂器,这些编纂器可以了解标志、特别符号本义等等。所以设置装备摆设文件的 XML 版本会是甚么样的呢?清单 11 显示了 XML 格局的设置装备摆设文件。
清单 11. config.xml
<?xml version="1.0"?>
<config>
<Title>My App</Title>
<TemplateDirectory>tempdir</TemplateDirectory>
</config>
清单 12 显示了利用 XML 来装载设置装备摆设设置的 Configuration 类的更新版。
清单 12. xml1.php
<?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."\n" );
?>
看起来 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 保留为一个文件。
<P> 利用数据库
最初的替换体例是利用一个数据库保留设置装备摆设元素的值。那起首要用一个复杂的形式来存储设置装备摆设数据。上面是一个复杂的形式。
清单 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
<?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."\n" );
$c->TemplateDirectory = 'new foo';
echo( $c->TemplateDirectory."\n" );
?>
这实践上是一个夹杂的文本/数据库处理计划。请细心察看 parse 办法。该类起首读取文本文件来获得初始值,然后读取数据库,进而将键更新为最新的值。在设置一个值后,键就从数据库中移除失落,并添加一条具有更新过的值的新纪录。
察看 Configuration 类若何经由过程本文的多个版原本发扬感化是一件风趣的事,该类能从文本文件、XML 及数据库中读取数据,并一向坚持不异的接口。我勉励您在开辟中也利用具有不异不乱性的接口。关于对象的客户机来讲,这项任务详细是若何运转的是不明白的。关头的是对象与客户机之间的契约。
甚么是设置装备摆设及如何设置装备摆设
在设置装备摆设过量的设置装备摆设选项与设置装备摆设缺乏间找一个恰当的两头点是一件坚苦的事。可以一定的是,任何数据库设置装备摆设(例如,数据库称号、数据库用户用及暗码)都应当是可设置装备摆设的。除此以外,我还有一些根基的保举设置装备摆设项。
在初级设置中,每个特征都应当有一个自力的启用/禁用选项。依据其对使用法式的主要性来答应或禁用这些选项。例如,在一个 Web 服装论坛使用法式中,延时特征在缺省形态下是启用的。但电子邮件告诉在缺省形态下倒是禁用的,由于这仿佛需求定制。
用户界面(UI)选项全应当设置到一个地位上。界面的布局(例如,菜单元置、额定的菜单项、链接到界面特定元素的 URL、利用的 logo,诸如斯类)全应当设置到一个单一名置上。我激烈地建议不要将字体、色彩或款式条目指定为设置装备摆设项。这些都应当经由过程层叠款式表(Cascading Style Sheets,CSS)来设置,且设置装备摆设体系应当指定利用哪一个 CSS 文件。CSS 是设置字体、款式、色彩等等的一种无效且天真的体例。有很多精彩的 CSS 东西,您的使用法式应当很好天时用 CSS,而不是试图自行设置尺度。
在每个特征中,我保举设置 3 到 10 个设置装备摆设选项。这些设置装备摆设选项应当以一种意义分明的体例定名。假如设置装备摆设选项可以经由过程 UI 设置,在文本文件、XML 文件及数据库中的选项称号应当直接同界面元素的题目相干。别的,这些选项全应当有明白的缺省值。
总的来讲,上面这些选项应当是可设置装备摆设的:电子邮件地址、CSS 所利用的器材、从文件中援用的体系资本的地位和图形元素的文件名。
关于图形元素,您或许想要创立一个名为皮肤 的自力的设置装备摆设文件类型,该类型中包括了对设置装备摆设文件的设置,包含 CSS 文件的地位、图形的地位及这些类型的器材。然后,让用户在多种皮肤文件中停止遴选。这使得对使用法式外不雅和感到的大范围更改动得复杂。这也一样为用户供应了一个时机,使使用法式可以在分歧的产物装置间改换皮肤。本文其实不涵盖这些皮肤文件,但您在这里学到的基本常识将会使对皮肤文件的撑持变得加倍复杂。
停止语
可设置装备摆设性关于任何 PHP 使用法式来讲都是相当主要的一个局部,一入手下手就应当成为设计的中间局部。我但愿本文可以对您完成设置装备摆设架构供应一些匡助,并对应当答应甚么样的设置装备摆设选项有所指点。怎样学习,大家都知道编程是1门很枯燥的事业,所以大家一定要有兴趣,可能刚开始打算学的时候是因为别人说php有多好,php多么流行,但是后来伴随着学习的深入,你的这些 |
|