PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,
并且受到越来越多的使用 ColdFusion 和 PHP
的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。
MVC如何工作
MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
视图
视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中
扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web
services.
如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
模型
模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components
这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次
就可以被多个视图重用,所以减少了代码的重复性。
控制器
控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后用确定用哪个视图来显示模型处理返回的数据。
现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。
为什么要使用 MVC
大部分Web应用程序都是用像ASP,PHP,或者CFML这样的过程化语言来创建的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表
示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC从根本上强制性的将
它们分开。尽管构造MVC应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。
首先,最重要的一点是多个视图能共享一个模型,正如我所提及的,现在需要用越来越多的方式来访问你的应用程序。对此,其中一个解决之道是使用MVC,
无论你的用户想要Flash界面或是 WAP
界面;用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。
由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用HTML来表示,但是它们也有可能要用
Macromedia
Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序
所重用。
因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从MySQL移植到
Oracle,或者改变你的基于RDBMS数据源到LDAP,只需改变你的模型即可。一旦你正确的实现了模型,不管你的数据来自数据库或是LDAP服务
器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互对立,改变其中一个不会影响其它两个,所以依据这种设计思想你能构造良好的松偶合
的构件。
对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。
MVC的缺点
MVC的缺点是由于它没有明确的定义,所以完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。
你将不得不花费相当可观的时间去考虑如何将MVC运用到你的应用程序,同时由于模型和视图要严格的分离,这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经过了测试,你就可以毫无顾忌的重用它们了。
根据我个人经验,由于我们将一个应用程序分成了三个部件,所以使用MVC同时也意味着你将要管理比以前更多的文件,这一点是显而易见的。这样好像我们的工作量增加了,但是请记住这比起它所能带给我们的好处是不值一提。
MVC并不适合小型甚至中等规模的应用程序,花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。
MVC是一条创建软件的好途径
MVC设计模式是一个很好创建软件的途径,它所提倡的一些原则,像内容和显示互相分离可能比较好理解。但是如果你要隔离模型、视图和控制器的构件,你
可能需要重新思考你的应用程序,尤其是应用程序的构架方面。如果你肯接受MVC,并且有能力应付它所带来的额外的工作和复杂性,MVC将会使你的软件在健
壮性,代码重用和结构方面上一个新的台阶。
有一些基础的东西还是要懂的。
而且手册有的方面也不是说的很详细,否则我想php的书可以会很惨
WHILE
WHILE循环是PHP3中循环的一个简单例子。它和在C中的表现完全一样,WHILE语句基本的结构如下所示:
WHILE(expr) statement
WHILE语句的的含义是十分简单的。它告诉PHP在WHILE表达式为真的情况下反复的执行嵌套的语句。表达式的值在每一次循环开始的时候被检查,所以
即使这个值在执行嵌套的语句时被更改了,执行过程将不会被终止,直到结束该次循环为止。有些情况下,WHILE表达式的值在开始就是假,那么这些嵌套的语
句将一次也不会被执行。
和使用IF语句类似,您可以在同一个WHILE循环中使用多个语句作为一个组,使用{ }或类似于下文的语法:
WHILE(expr): statement ... ENDWHILE;
在下面的两个例子实现的功能是相同的,即打印了从1到10的所有数字:
/* example 1 */
$i = 1;while ($i <= 10) {
print $i++; /* the printed value would be
$i before the increment
(post-increment) */
}
/*example 2 */
$i = 1;
while ($i <= 10):
print $i;
$i++;
endwhile;
DO..WHILE
DO..WHILE循环和WHILE循环是十分类似的,除了真值检查是在每个循环过程最后进行的外。这里最主要的不同就是对于DO..WHILE
循环,它和标准的WHILE循环不一样,它的第一个循环过程总是会被执行的(由于真值检查是在最后被执行的)。标准的WHILE循环中的第一个语句不一定
被执行(由于真值检查是在循环开始时进行的)。
这儿是使用DO..WHILE循环语句的一个例子:
$i = 0;
do {
print $i;
} while ($i>0);
上文的循环仅仅会被执行一次,在第一次循环执行完毕之后,检查表达式为假($I并不比0大)此时循环就会被终止。
高级的C语言使用者对使用DO..WHILE循环的不同之处会有很深的理解,为了允许在代码段的执行过程中终止执行,可以使用将他们加入DO..WHILE(0)语句中,再使用BREAK语句的方法。下面代码段说明了这一点:
do {
if ($i < 5) {
print "i is not big enough";
break;
}
$i *= $factor;
if ($i < $minimum_limit) {
break;
}
print "i is ok";
...process i...
} while(0);
如果您对这些都不是很明白的话,也不必担心。您可以在不使用这些特性的情况下编写出很强有力的代码。
FOR
在PHP中FOR循环是最复杂的循环。它的特性和它在C语言中的表现类似。FOR循环的语法如下:
FOR (expr1; expr2; expr3) statement
第一个表达式expr1将在循环开始时无条件的被求解执行;
在每一个循环开始的时候,第二个表达式将被执行。如果它的值为真,则该循环将继续下面嵌套语句的执行。如果它的值为假,则循环结束;
在每个循环的最后第三个表达式将被执行。
任何一个表达式都可以是空的,当表达式二(expr2)是空的时候,意味这这个循环运行的次数将是不确定的(PHP和C一样默认该表达式为真)。这种做法
并不象您想象的那样没有用,因为在有些情况下您可能希望使用带条件的BREAK语句来取代FOR的真值判断来作为终止循环的方法。
注意下面的几个例子,所有的这些语句显示了从1到10的数字:
/* example 1 */
for ($i = 1; $i <= 10; $i++) {
print $i;
}
/* example 2 */
for ($i = 1;;$i++) {
if ($i > 10) {
break;
}
print $i;
}
/* example 3 */
$i = 1;for (;;) {
if ($i > 10)
{ break;
}
print $i;
$i++;
}
/* example 4 */
for ($i = 1; $i <= 10; print $i, $i++) ;
当然,看上去第一个例子最好(或者是第四个例子),但是您将发现在许多场合使用空表达式的FOR循环是十分方便的。
在FOR循环中PHP也支持交互的“冒号语法”。例如:
FOR (expr1; expr2; expr3): statement; ...; endfor;
其他有FOR语句的语言往往使用该语句来处理数组。在PHP中使用WHILE语句和list()和each()函数来做这件事情。请参考这些函数相关的例子。
BREAK
BREAD 跳出当前的循环体,提前结束循环.
$i = 0;
while ($i < 10) {
if ($arr[$i] == "stop") {
break;
}
$i++;
}
CONTINUE
CONTINUE结束本次循环,跳到循环体的开始处,接着进行下一次循环的判定.
while (list($key,$value) = each($arr)) {
if ($key % 2) { // skip even members
continue;
}
do_something_odd ($value);
}
SWITCH
在实际问题中常常需要用到多分支的选择.你可以使用多重嵌套的IF语句来处理,但如果分支较多,则嵌套的IF语句层数多,程序冗长而且可读性降低.PHP中提供SWITCH语句来直接处理多分支选择.
下面的两个例子使通过两种不同的方式来实现同一件事,一个使用了一系列的IF语句,另外一个使用了SWITCH语句:
/* example 1 */
if ($i == 0) {
print "i equals 0";
}
if ($i == 1) {
print "i equals 1";
}
if ($i == 2) {
print "i equals 2";
}
/* example 2 */
switch ($i) {
case 0:
print "i equals 0";
break;
case 1:
print "i equals 1";
break;
case 2:
print "i equals 2";
break;
}
为了理解SWITCH语句为了躲避语句冗长,知道它如何被执行的是非常重要的.SWITCH语句石一行一行
执行的(事实上,是一条语句一条语句).在开始时,没有代码被执行.仅仅当一个值于SWITCH表达式的语句的值相同的CASE语句被发现后,PHP继续
执行语句直到
SWITCH体的结束,或者出现了BREAK语句.如果你在一个分支语句的后面没有写BREAK语句,PHP将继续执行下面分支的语句.例如:
/* example 3 */
switch ($i) {
case 0:
print "i equals 0";
case 1:
print "i equals 1";
case 2:
print "i equals 2";
}
这里,如果$i等于0,PHP将会执行所有打印语句.如果$i等于1,PHP将会执行剩下的两个打印语句,并且仅仅当$i等于2的时候,你才能得到你期望
的执行结果,只有’I equals 2’被显示.因此不要在每一个分支语句的后面忘记BREAK语句(即使你在一定的环境下有可能想避免提供他们).
一个特殊的分支是默认的分支.这个分支可以匹配任何其它分支没有匹配的事情.例如:
/* example 4 */
switch ($i) {
case 0:
print "i equals 0";
break;
case 1:
print "i equals 1";
break;
case 2:
print "i equals 2";
break;
default:
print "i is not equal to 0, 1 or 2";
}
另外一个值得一提的事实是CASE表达式可以是任何计算标量类型的表达式,也就是说,整型或实型和字符型.数组和对象将不会导致PHP崩溃,但是他们没有没有任何意义.
REQUIRE
REQUIRE语句使用指定的文件来代替它自己,与C语言中的#include语句非常相似。这意味着你不能把一个require()语句放在一个循环体中,并且期望它在每一次反复中都包含不同文件的内容.为了达到这个目的,可以使用INCLUDE语句。
require (''header.inc'');
INCLUDE
INCLUDE语句包括和计算指定文件.
在每次遭遇INCLUDE语句的时候都会进行一次.因此你可以在一个循环体中使用INCLUDE语句.以用来包含一些不同的文件.
$files = array (''first.inc'', ''second.inc'', ''third.inc'');
for ($i = 0; $i < count($files); $i++) {
include($files[$i]);
}
INCLUDE()与REQUIRE()语句是不同的,include语句是每一次都重新计算(并且仅仅当它被执行的时候),而require
()语句当他第一次被碰到的时候,用指定的文件来代替它本身,无论这个文件的内容是否被计算(例如,如果它出现在一个条件为FALSE的if语句中).
因为include()是一个特殊的语言结构,你必须在一个语法块中封闭它,如果它在一个条件块中.
/*错误,不会同设想一样工作. */
if ($condition)
include($file);
else
include($other);
/*下面是正确的. */
if ($condition)
{
include($file);
}
else {
include($other);
}
当一个文件被计算的时候,语法分析将处在”HTML-模式”中,这个模式将输出这个文件的内容直到第一个PHP开始标签(
参考 readfile(),virtual().
函数
一个function(函数)可以使用如下语法来定义
function foo ($arg_1, $arg_2, ..., $arg_n) {
echo "Example function.\n";
return $retval;
}
任何有效的PHP代码可以出现在function(函数)中,即使是其它的函数或类定义.
Function必须在他们被引用之前定义.
返回值
使用一些可选的返回语句,任何类型的数值都能被返回,包括对象和广义表.
function my_sqrt ($num)
{
return $num * $num;
}
echo my_sqrt (4); // 输出 ''16''.
可以返回多值,但是同时的影响使通过一个广义表来实现:
function foo()
{
return array (0, 1, 2);
}
list ($zero, $one, $two) = foo();
参数
通过参数表可以传递信息到函数,这个表可以是变量或常量以逗号(,)分隔构成的。
PHP3支持使用值来传递变量(默认),通过调用传递,和默认的参数值.可变长度的参数列表目前不被支持,但是可以通过传递数组来实现.
function takes_array($input) {
echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}
通过调用传递(Passing by reference)
默认的,函数参数通过值来传递.如果你希望允许一个函数可以修改它的参数的值,你可以通过调用来传递他们.
如果你希望一个函数参数意志通过引用被传递,你可以预先函数定义中在参数名前加符号(&):
function foo( &$bar ) {
$bar .= '' and something extra.'';
}
$str = ''This is a string, '';
foo ($str);
echo $str; // 输出 ''This is a string, and something extra.''
如果你希望向一个不是用这种方式定义的函数用调用的方式传递参数,你可以在函数调用中的参数名称前加符号(&).
function foo ($bar) {
$bar .= '' and something extra.'';
}
$str = ''This is a string, '';
foo ($str);
echo $str; //输出 ''This is a string, ''
foo (&$str);
echo $str; //输出 ''This is a string, and something extra.''
默认值
一个函数对于标量参数可以定义C++-风格的默认值.
function makecoffee ($type = "cappucino") {
echo "Making a cup of $type.\n";
}
echo makecoffee ();
echo makecoffee ("espresso");
上面的程序段的输出如下:
Making a cup of cappucino.
Making a cup of espresso.
默认值必须是一个常量表达式,不是一个变量或类成员.
注意当时用默认参数时,任何默认都应该在任何非默认参数右边;否则,事情将不会想你所想的那样.考虑下面的程序段:
function makeyogurt ($type = "acidophilus", $flavour) {
return "Making a bowl of $type $flavour.\n";
}
echo makeyogurt ("raspberry"); // 将不会按照预想工作
上面例子的输出是:
Warning: Missing argument 2 in call to makeyogurt() in
/usr/local/etc/httpd/htdocs/php3test/functest.html on line 41
Making a bowl of raspberry .
现在,用下面的对比上面的:
function makeyogurt ($flavour, $type = "acidophilus"){
return "Making a bowl of $type $flavour.\n";
}
echo makeyogurt (“raspberry”);//正常工作
这个例子的输出是:
Making a bowl of acidophilus raspberry.
OLD_FUNCTION
OLD_FUNCTION语句允许你声明一个使用PHP/FI2 的语法的函数(你需要做的就是把’function’替换成’old_function’.
这是一个不被赞成的特征,并且应该仅仅被PHP/FI2到PHP3的转换这使用.
定义成为OLD_FUNCTION模式的函数不能被PHP的内部代码调用。其中之一的情况是,意味着您不能在象as
usort()、array_walk()和register_shutdown_function().这样的函数中使用使用他们。您可以使用编写交换
函数的方法来调用OLD_FUNCTION模式的函数(在普通的PHP3表单中)。
CLASS
一个class是一个变量和使用这些变量的函数的组合。定义class使用如下的语法:
// Add $num articles of $artnr to the cart
function add_item ($artnr, $num) { $this->items[$artnr] += $num; }
// Take $num articles of $artnr out of the cart
function remove_item ($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} else {
return false;
}
}
}
?>
如上所示,定义了一个名字为Cart的class。这个class由多个描写物品的数组和添加项目、删除项目的函数组成。
Class是一种类型,这就是说,它是实际变量的设计蓝图。您可以根据设计建立一个变量组和针对它们的一些新的操作。示例如下:
$cart = new Cart;
$cart->add_item("10", 1);
如上所示,建立了一个类型为class Cart的对象$cart。这个对象中的函数add_item()被调用来添加一个物品号为10的项目。
Class可以使用其他的Class来扩展。这个扩展的或者继承的class(类)拥有基本class所有的变量和函数同时您还可以在其中加如您自己做的扩展定义。要这样定义需要使用扩展定义的关键词。
class Named_Cart extends Cart {
var $owner;
function set_owner ($name) {
$this->owner = $name;
}
}
以上定义了一个名字为Named_Cart的class(类),这个类拥有所有包含于类Cart中的变量和函数,同时还添加了一个变量$
owner和函数set_owner()。您可以建立一个有名字的cart,同时获得cart的拥有者名字。您还可以在类Named_Cart中,使用普
通的属于类cart的函数。
$ncart = new Named_Cart; // Create a named cart
$ncart->set_owner ("kris"); // Name that cart
print $ncart->owner; // print the cart owners name
$ncart->add_item ("10", 1); // (inherited functionality from cart)
在这个类的函数中变量$this表示这个对象。在当前的对象中,您可以使用$this->something来访问任何变量和函数。
当您建立一个新的类时,有一个构造器函数将被自动的调用。如果某个函数的名字和类的名字一样,那么它就成为构造器:
class Auto_Cart extends Cart {
function Auto_Cart () {
$this->add_item ("10", 1);
}
}
在上面的例子中,定义了一个名字为Auto_Cart的类,它是在原来的类Cart中加上了一个构造器函数,这个构造器函数初始化了类Cart使用的方法
是:在每次建立一个类的时候添加一个物品号为10的一个项目。构造器还可以显示一些信息,这些信息可以被随意的挑选,这使他们可以变的十分的有用,
class Constructor_Cart {
function Constructor_Cart ($item = "10", $num = 1) {
$this->add_item ($item, $num);
}
}
// Shop the same old boring stuff
$default_cart = new Constructor_Cart;
// Shop for real...
$different_cart = new Constructor_Cart ("20", 17);
算术操作符
这些工作和基本的学校里教的内容相似。
Table 7-1. Arithmetic Operators(表7-1算术操作符)
example name result
$a + $b Addition Sum of $a and $b.?/FONT>
$a - $b Subtraction Remainder of $b subtracted from $a.?/FONT>
$a * $b Multiplication Product of $a and $b.?/FONT>
$a / $b Division Dividend of $a and $b.?/FONT>
$a % $b Modulus Remainder of $a divided by $b.
其中,除法操作符“/”返回一个整数值(整数除法的结果)如果两个操作数是整数(或者是被转化成整数的字符串)的话。如果任意一个操作数是浮点数,那么将进行浮点运算。
字符串操作符
这个地方仅仅有一个真正的字符串操作符:串联符号“.”。
$a = "Hello ";$b = $a . "World!";
// now $b = "Hello World!"
赋值操作符
基本的赋值操作符就是“=”。您往往会倾向于认为它的含义就是“等于”。不要这样想,它真正的含义就是左侧的操作数获得右侧表达式的值。
一个赋值表达式的意义在于值的指派。也就是说,“$a=3”的值是3。这就允许您做这样的事情:
$a = ($b = 4) + 5;
// $a is equal to 9 now, and $b has been set to 4.
作为赋值操作符的一个补充,还有一个针对二进制数和字符传进行操作的组合操作符,该操作符允许您在赋值方采用被赋值表达式的值。例如:
$a = 3;
$a += 5; // sets $a to 8, as if we had said: $a = $a + 5;
$b = "Hello ";
$b .= "There!"; // sets $b to "Hello There!", just like $b = $b . "There!";
位操作符
位操作符允许您精细的操作数据的每一个位。
Table 7-2. Bitwise Operators(表7-2位操作符)
example name result
$a & $b And Bits that are set in both $a and $b are set.?/FONT>
$a | $b Or Bits that are set in either $a or $b are set.?/FONT>
~ $a?/FONT> Not Bits that are set in $a are not set, and vice versa.
逻辑操作符
Table 7-3. Logical Operators(表7-3 逻辑操作符)
example name result?/FONT>
$a and $b And True of both $a and $b are true.?/FONT>
$a or $b Or?/FONT> True if either $a or $b is true.?/FONT>
$a xor $b Or?/FONT> True if either $a or $b is true, but not both.?/FONT>
! $a Not?/FONT> True if $a is not true.?/FONT>
$a && $b And?/FONT> True of both $a and $b are true.?/FONT>
$a || $b Or?/FONT> True if either $a or $b is true.
比较操作符
比较操作符,正如它的名字所示,允许您比较两个值。
Table 7-4. Comparson Operators(表7-4 比较操作符)
example name result?/FONT>
$a == $b Equal?/FONT> True if $a is equal to $b.?/FONT>
$a != $b Not equal True if $a is not equal to $b.?/FONT>
$a < $b Less than?/FONT> True if $a is strictly less than $b.?/FONT>
$a > $b Greater than?/FONT> True if $a is strictly greater than $b.?/FONT>
$a <= $b Less than or equal to?/FONT> True if $a is less than or equal to $b.?/FONT>
$a >= $b Greater than or equal to?/FONT> True if $a is greater than or equal to $b.
字符串操作函数
PHP3.0中的字符串操作功能是比较多的,重要的有以下这些:
(1)echo,print,printf,sprintf
用于输出字符串.字符串中如果有变量名则被替换成其值. 后两个函数类似于C的同名函数.
(2)strchr, strlen, strtok, strrchr, strrev, strstr, strtolower, strtoupper, substr, ucfirst
用的字符串操作函数,有些和C中的同名函数意义完全一致. strrev是把一个字符串翻转.
strtolower和strtoupper是将字符串转换为小写和大写.ucfirst是把字符串的第一个字符变成大写.
substr是返回字符串的一个子串,用法是:substr(字符串,头,长度).头位置是 从0算起的.如果是负数,则是从尾部向前数的意思.
(3)Chr,Ord
同名函数.
(4)explode,implode,join
与数组有关的函数. explode(字符串,分割符)返回一个将字符串在分割符处分开所产生的数组. implode(数组,分割符)返回一个将数组各元素之间插上分割符而成的字符串. join与implode意义相同.
(5)Chop
处理串尾部的空白.
(6)htmlspecialchars
将HTML特殊字符换成它们的名字,例如"<"变成"<".
(7)nl2br
在HTML中的每一个回车前面加上"
".
(8)AddSlashes,StripSlashes
给字符串中按照需要加上"\"和去掉"\",对于某些数据库,必须在要查询的字符加上和去掉"\"之后才能够查询.
(9)parse_str
将"name1=value1&name2=value2&..."类型的字符串分析成一些变量.
例如: parse_str("a=1&b=2"); 生成$a与$b两个变量,值分别为1,2.
如果有两对名字/值的名字部分相同,则后一个的值覆盖前一个的.
如果这两对的名字尾部都有"[]",例如"a[]=1&a[]=2",则生成数组$a,两个元素分别为1,2.
正规表达式函数
PHP与其它跨平台语言(也许Java不在其列. )类似,也有正规表达式功能. PHP3.0的正规表达式功能当然远远比不上Perl,但还是足够用的,主要函数有这么些:
(1)ereg,eregi
这是正规表达式匹配函数,前者是大小写有关匹配,后者则是无关的.
用法: ereg(正规表达式,字符串,[匹配部分数组名]);
PHP3.0中的正规表达式大体类似于grep中用的.
(2)ereg_replace,eregi_replace
这些是替换函数.
用法:
ereg_replace(正规表达式,替换串,原字符串);
字符串处理函数中有一个strtr,是"翻译"函数,类似于Perl中的tr/.../.../,
用法: strtr(字符串,"从","到");
例如:strtr("aaabb","ab","cd")返回"cccdd".
(3)split
与explode函数有些类似,但这次可以在匹配某正规表达式的地方分割字符串.
用法:
split(正规表达式,字符串,[取出前多少项]);
文件操作函数
PHP3.0中的文件操作函数大体和C的类似,但有一些扩充,特别是除了支持
对本机文件的访问外,也支持对HTTP和FTP的URL进行访问,只要把这些URL作为文件名传递给文件操作函数就可以了.
主要的文件操作函数有:
(1)fclose, feof, fgetc, fgets, fopen, fputs, fseek, ftell, mkdir, readlink, rename, rewind, rmdir, stat, unlink
这些函数的功能和C语言中的同名函数类似.
(2)chgrp, chmod, chown, copy
这些函数的含义也都很容易理解:
chgrp(文件名,组);
chmod(文件名,模式);
chown(文件名,用户);
copy(源文件名,目标文件名);
需要注意的是:这些函数用的是文件名而不是fopen返回的文件号.
(3)file_exists, fileatime, filectime, filegroup, fileinode,
filemtime, fileowner, filesize, filetype, fileperms, fileumask, is_dir,
is_executable, is_file, is_link, is_readable, is_writeable
这些是文件信息函数,大多接受一个文件名作为参数.
(4)fgetss
用法:
fgetss(文件号,最大长度);
读取文件的一行或直到最大长度(类似于fgets),但去掉所有的 HTML和PHP标记.
(5)file
用法:
file(文件名);
返回一个数组,每一个元素是文件中的一行.
(6)tempnam
用法:
tempnam(目录名,前缀);
返回一个临时文件名.
(7)basename, dirname
取得文件路径中的文件名部分和目录名部分. 在Windows系统下,"/"和"\"都可以作为目录分割符,其他系统下只有"/"可以.
目录遍历函数
PHP中的目录遍历功能本来也很普通,但它却具有一种"面向对象"的形式, 所以也提一下:
(1)dir, opendir
用法:
$d = dir("目录名");
$handle = opendir("目录名");
前者返回一个目录对象,后者返回一个目录句柄. 前者返回的对象有handle和path两个属性,第一个就相当于opendir 返回的句柄,第二个就是目录名本身.访问时用$d->handle和$d->path.
(2)read, readdir, rewind, rewinddir, close, closedir
三组中每组的前一个是目录对象的方法,用"对象->方法()"调用, 后一个是函数,用"函数名(目录句柄)"调用. read是返回目录中的下一个文件名. rewind是回到目录的第一个文件名. close是关闭目录,不再遍历.
(3)chdir
转换PHP的工作目录.
时间函数
PHP中的时间函数有这么些:
(1)date
用法:
date(格式,[时间]);
如果没有时间参数,则使用当前时间. 格式是一个字符串,其中以下字符有特殊意义:
U 替换成从一个起始时间(好象是1970年1月1日)以来的秒数Y 替换成4位的年号.
y 替换成2位的年号.
F 替换成月份的英文全称.
M 替换成月份的英文简称.
m 替换成月份数.
z 替换成从当年1月1日以来的天数.
d 替换成日数.
l 替换成星期几的英文全称.
D 替换成星期几的英文简称.
w 替换成星期几(数字).
H 替换成小时数(24小时制).
h 替换成小时数(12小时制).
i 替换成分钟数.
s 替换成秒数.
A 替换成"AM"或"PM".
a 替换成"am"或"pm".
S 替换成序数字后缀,例如:"st","nd","rd","th".
函数返回作过了替换的格式串.
(2)getdate(时间)
返回一个哈希表,各下标是:
"seconds" -- 秒数
"minutes" -- 分数
"hours" -- 小时数
"mday" -- 日数
"mon" -- 月份数
"year" -- 年号
"yday" -- 1月1日以来的天数
"weekday" -- 星期几,英文全称
"month" -- 月份,英文全名
(3)gmdate
与date类似,但先将时间转换成格林威治标准时.
(4)mktime
用法:
mktime(小时数,分数,秒数,月,日,年); 返回一个时间值,可用于其他函数.
(5)time
用法:
time(); 返回1970年1月1日零点以来的秒数.
(6)microtime
用法:
microtime(); 返回一个字符串,用空格分成两部分,后一部分相当于time()
的返回值,前一部分是微秒数.
(7)checkdate
用法:
checkdate(月,日,年); 返回逻辑真或逻辑假. 如果:
年在1900和32767之间(包括1900与32767);
月在1到12之间;
日在该月的允许日数范围内(考虑了闰年);
则返回逻辑真.
(8)set_time_limit
用法:
set_time_limit(秒数);
规定从该句运行时起程序必须在指定秒数内运行结束, 超时则程序出错退出.
图象函数
PHP中有一组图像函数,可以动态生成gif格式的图像数据流并输出到 服务器.
为了这组函数能够工作,系统中必须有gd库的支持.如果是在Unix下,
应该在编译PHP之前先取得gd的源码并编译之,生成libgd.a和一些.h文件,分别拷到系统的库目录和头文件目录中(例如/usr/lib和
/usr/include);如果是在Windows下,PHP3.0的安装程序会安装一个gd.dll文件,在程序中加一句''dl
("gd.dll");''即可使用图像函数.
主要的图像函数有:
(1)ImageCreate(宽度,高度)
返回一个图像描述符.
(2)ImageCreateFromGif(文件名);
返回一个图像描述符.
(3)ImageColorAllocate(图像描述符,红,绿,蓝);
返回一个颜色描述符.由于Gif图像只能有256色,必须先对它分配调色板, 这个语句就是分配一个调色板项.
(4)ImageColorTransparent(图像描述符,颜色描述符);
指定某颜色为透明色.
(5)ImageArc(图像描述符,圆心横坐标,圆心纵坐标,椭圆宽,椭圆高,起始角,终止角,颜色描述符);
ImageChar(图像描述符,字体,x,y,字符,颜色描述符);
ImageCharUp(图像描述符,字体,x,y,字符,颜色描述符);
ImageCopyResized(目标图像描述符,源图像描述符,目标x,目标y,源x,源y,目标宽,目标高,源宽,源高);
ImageDashedLine(图像描述符,x1,y1,x2,y2,颜色描述符);
ImageFill(图像描述符,起始点x,起始点y,颜色描述符);
ImageFilledPolygon(图像描述符,各顶点数组,顶点数,颜色描述符);
ImageFilledRectangle(图像描述符,x1,y1,x2,y2,颜色描述符);
ImageFillToBorder(图像描述符,起始点x,起始点y,边界色,填充色);
ImageLine(图像描述符,x1,y1,x2,y2,颜色描述符);
ImagePolygon(图像描述符,各顶点数组,顶点数,颜色描述符);
ImageRectangle(图像描述符,x1,y1,x2,y2,颜色描述符);
ImageSetPixel(图像描述符,x,y,颜色描述符);
ImageString(图像描述符,字体,x,y,字符串,颜色描述符);
ImageStringUp(图像描述符,字体,x,y,字符串,颜色描述符);
这些都是画图函数,需要略做解释的就是多边形的顶点数组内依次存放着 第一点x,第一点y,第二点x,第二点y,...
(6)ImageLoadFont(文件名);
文件应该是一个位图字体文件,返回一个字体号.系统缺省带有1-5字体号, 可以直接使用.
(7)ImageSX,ImageSY
分别得到一个图像的宽度和高度,接收一个图像描述符参数.
(8)ImageColorAt(图像描述符,x,y);
ImageColorClosest(图像描述符,红,绿,蓝);
ImageColorExact(图像描述符,红,绿,蓝);
ImageColorSet(图像描述符,颜色描述符,红,绿,蓝);
ImageColorsForIndex(图像描述符,颜色描述符);
ImageColorsTotal(图像描述符);
前三个返回一个颜色描述符.ImageColorExact如果找不到匹配则返回-1.
ImageColorsForIndex返回一个三项的数组,元素分别是红,绿,蓝值.
ImageColorsTotal返回总颜色数.
(9)ImageFontHeight,ImageFontWidth
接收一个字体号作为参数.
(10)ImageGif(图像描述符,[文件名]);
如无文件名,则将gif数据流送往浏览器.这时程序一开始应该有一句: Header("Content-type: image/gif")
(11)ImageDestroy(图像描述符);
图像函数中有一个小Bug(至少在PHP3.0RC和PHP3.0RC3 For
Unix的源码中已经发现,现在www.php.net上的下载文件应该已经更改),就是ImageSetPixel总是在(y,y)处画点,不管x的值
是什么,不过这个问题不是很大.
数据库函数(部分)
PHP的数据库功能应该说是它最有用的功能之一.它的特点就是内置了对很多数据库的支持,而不再需要重新扩充.
Perl和Tcl也都是常用的跨平台语言,都有很强的字符能力,前者字符能力更强一些,性能更高一些;而后者有GUI能力.它们都可以扩充以支持数据库,
但这时如果仍旧希望应用程序有跨平台能力,则需要在各种平台上各自扩充,比如在 Unix平台上对Perl扩充DBI包,在Windows
95/NT下对Perl扩充Win32::ODBC包,有时候这是很麻烦的.而PHP由于内置了数据库支持,就为编程人员省去了这些麻烦.
对各种数据库,访问函数并不完全相同,例如那些基于SQL的数据库显然不能用和dBase或dbm相同的方式访问.以下比较详细地介绍以下MiniSql和MySql数据库的访问函数:
mSQL(mini SQL)是一种小型的关系数据库,性能不是太好,对SQL语言的支持也不够完全,但在一些网络数据库应用中是足够了.
MySQL是mSQL的一个变种,性能有所提高,增加了用户访问控制.
这两种数据库都是通过SQL语言访问的,但MySQL基本支持全部SQL92规范, 只是"select ... where select
.."不支持,另外还扩充了一些数据类型,而mSQL 则基本上不支持任何嵌套SQL语句,也不支持"update set
column1=column1-1"这样的语句.
mSQL由于较简单,在运行简单的SQL语句时速度比MySQL略快,而MySQL在线程和索引上下了功夫,运行复杂的SQL语句时比mSQL,
PostgreSQL,Oracle等都要快一些.
安全性方面,mSQL通过ACL文件设定各主机上各用户的访问权限,缺省是全部可读/写,而MySQL通过一个授权库设定用户名,口令和访问权限,较可靠
一些mSQL的存储能力不是很清楚,MySQL的存储能力受文件系统限制,例如在Linux下不能超过2G(3G?记不清楚了).
mSQL与MySQL既然本来就是差不多的两个东西,PHP中对它们的访问语句也都差不多,例如msql_close与mysql_close就分别完成
同样的关闭动作.所以以下介绍时只对mysql介绍,msql的访问语句只需换个前缀即可(特殊情况另行说明).
注意:mSQL与MySQL访问函数都需要有相应的权限才能运行.
(1)mysql_connect(主机,用户名,口令);
返回一个连接号.
注意:mysql各用户的口令可以随该用户所在机器IP地址不同而改变.另外,mSQL没有用户名机制,所以msql_connect只需要一个主机参数. 主机可以是IP地址或域名.
(2)mysql_create_db(数据库名);
(3)mysql_select_db(数据库名,连接号);
连接一个数据库.
(4)mysql_query(SQL语句,连接号);
如果SQL语句是select,则返回一个结果号.否则返回的值可以不理会.
如果失败,返回false.
(5)mysql_fetch_array(结果号);
取出下一行,返回一个数组.可以用数字下标访问(第一个字段是下标 0),也可以用字符串下标访问(即使用各字段名). 如已取了最后一行,返回 false.
(6)mysql_fetch_field(结果号,[字段序号]);
如无字段序号,取下一个字段. 返回一个哈希表,下标有: name, table, max_length, not_null,
primary_key, unique_key, multiple_key, numeric, blob, type, unsigned,
zerofill 各下标的意思应该比较明白了.
(7)mysql_num_rows(结果号);mysql_num_fields(结果号);
(8)mysql_free_result(结果号);
(9)mysql_list_dbs();mysql_list_tables(数据库名);
(10)mysql_close(连接号);
(11)mysql_pconnect(主机,用户名,口令);
与mysql_connect完全相似,但建立一个"永久连接",该连接一经建立永不关闭,即使使用mysql_close函数或程序执行完毕也不关闭.下一次试图建立永久连接时,系统如发现已存在一个永久连接,则直接返回该连接号而不重新创建.
<?来源:中国防黑网
作者:三尺寒冰
简述:
/*************************
说明:
判断传递的变量中是否含有非法字符
如$_POST、$_GET
功能:
防注入
**************************/
//要过滤的非法字符
$ArrFiltrate=array("'",";","union");
//出错后要跳转的url,不填则默认前一页
$StrGoUrl="";
//是否存在数组中的值
function FunStringExist($StrFiltrate,$ArrFiltrate){
foreach ($ArrFiltrate as $key=>$value){
if (eregi($value,$StrFiltrate)){
return true;
}
}
return false;
}
//合并$_POST 和 $_GET
if(function_exists(array_merge)){
$ArrPostAndGet=array_merge($HTTP_POST_VARS,$HTTP_GET_VARS);
}else{
foreach($HTTP_POST_VARS as $key=>$value){
$ArrPostAndGet[]=$value;
}
foreach($HTTP_GET_VARS as $key=>$value){
$ArrPostAndGet[]=$value;
}
}
//验证开始
foreach($ArrPostAndGet as $key=>$value){
if (FunStringExist($value,$ArrFiltrate)){
echo "";
if (empty($StrGoUrl)){
echo "";
}else{
echo "";
}
exit;
}
}
?>
保存为checkpostandget.php
然后在每个php文件前加include(“checkpostandget.php“);即可
今晚青协就要选新咖会长同部长。
已经过佐成年了。
我向青协呢度已经过佐两年了。
真系想唔到时间会咁快~~~
今届的会长同副会长都是我地部,呢个已经系我地四个呢一年咖成绩
但是我依家更担心咖系剩返咖个两个可唔可以撑得住社交部~~~
不过时间总会变好咖~~~
{
/**
* subStrWithSuffix
* 中文字符截取 (Mon Aug 01 11:13:34 CST 2005)
* @version 1.0.0
* @author
* @deprecated 解决中文截取出现乱码
* @return string
*/
function subStrWithChr ($string, $length, $start = 0)
{
if ($start < 0 || ($stringLength = strlen($string)) < $start) return $string;
$length = (($length < 1 || $length > $stringLength)?$stringLength:$length);
for ($i = 1, $o = ($start % 2)?2:1; ($start > 0 && $i
< $o && ord(substr($string, $start , 1)) > 0xa0); $i ++)
$start --;
for ($i = 1, $o = ($length % 2)?2:1; ($stringLength > $length
&& $i < $o && ord(substr($string, $length - 1 ,
$length)) > 0xa0); $i ++) $length ++;
$string = substr($string, $start, $length);
return $string;
}
/**
* wordWrapWithChr
* 字符截行 (Mon Aug 01 14:15:37 CST 2005)
* @version 1.0.0
* @author
* @deprecated 解决中文截取出现乱码
* @return string
*/
function wordWrapWithChr ($string, $width, $break = null)
{
/**
* 中文标点符号怎么处理?暂时没有比较好的解决方案
* ,。?:;’‘“”、()*……—…%¥€$£·!
*/
for ($break = $break?$break:"\n", $line = 0, $text = array(),
$handle = 0, $length = strlen($string); $handle < $length; $handle
+= strlen($text[$line ++]))
$text[$line] = String::subStrWithChr($string, $width, $handle);
return implode($break, $text);/* */
}
}
function startTimer()
{
global $starttime;
$mtime = microtime ();
$mtime = explode (' ', $mtime);
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
}
function endTimer()
{
global $starttime;
$mtime = microtime ();
$mtime = explode (' ', $mtime);
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = round (($endtime - $starttime), 5);
return $totaltime;
}
?>