代码重用与函数编写

代码重用

一、代码重用的好处

软件工程师的一个目标是通过重复使用代码来避免编写新的代码。这样做可以使用已有的代码,降低成本、增加代码的可靠性并提高它们的一致性。在理想情况下,一个的新的项目是这样创建的:它将已有的可重新利用的组件进行组合,并将新的开发难度降到最小。

二、使用require()和include()函数

php提供了两个非常简单有用的语句,使用require()include()函数中的任意一条,可以将一个文件载入到php脚本中。通常,这个文件可以包含任何希望在一个脚本中输入的内容,其中包括php语句、文本、html标记、php函数或php类。

require()和include几乎是相同的,区别在于函数失败后:require()函数将给出一个致命的错误,include()函数只是给出一个警告。

require()和include()也有两个变体函数,分别是require_once()include_once()。这两个函数的作用是确保一个包含(included)的文件只能被引入一次。使用这两个函数可以防止错误的引入同样的函数库两次,从而出现重复定义的错误。如果考虑运行速度,那建议直接使用原函数,而不是变体函数。

1、文件扩展名和require()函数
当需要一个文件的时候,可以使用require()语句。比如:require('foo.php');将被请求的文件内容代替,然后再执行脚本。
2、使用require()制作web站点的模板
如果Web页面具有一致的外观,可以在php中使用require()语句将模板和标准元素加入到页面中。比如:现在有一个页面foo.html,它具有头部header、主体home、脚注footer几大部分组成。我们可以将几大部分分割,然后分别另存为header.php、home.php、footer.php。文件home.php可以替代foo.html,它包含页面内容和两个require()语句。如:

<?php
    require('header.php');
?>
<!--page content -->
<p>welcome</p>
.....
<p>blablabla</p>
<?php
    require('footer.php');
?>

home.php中的require()语句将载入header.php和footer.php。
文件header.php包含了页面使用的css样式以及公司名称、导航栏菜单等等。
文件footer包含了每个在页面底部出现的风格样式等内容。

这种方法使网站很容易具有统一的风格,而且还可以通过输入如下所示的代码创建一个新的统一风格的页面:

<?php require('header.php') ?>
here is the content for this page
<?php require('footer.php') ?>

只需另命名并保存,然后再通过require()语句即可调用这个新风格页面。
最重要的是:即使用这个页眉和脚注创建许多新页面后,也很容易修改页眉和脚注文件。无论是做一个无关紧要的修改,无论网页内容有几十、几百个,还是重新设计网站的外观,只需要进行一次修改。我们并不需要单独地队网站中的每个页面进行修改,因为它们都是载入页眉和脚注文件的。

如果希望保证一个文件将被当作纯文本或者纯html,而且不执行任何PHP,可以使用readfile()作为替代方法。

3、使用auto_prepend_file和auto_append_file
此为另一种加载页眉和页脚的方法,需要在配置文件php.ini中进行设置。这里不做详述。

在PHP中使用函数

函数存在于大多数的编程语言中。它们用于分隔那些能够完成独立而又明确的任务的代码。 这使得代码更易于阅读,并且允许在每次需要完成同样任务的时候意复使用代码。

函数是一个给出了调用接口的自包含模块,它可以执行一些任务,还可以返回结果(可选的)。

一、调用函数

如下所示代码是调用函数最简单的例子: function_name();

以上代码将调用一个名为.:function_name()且不需要任何输入参数的函数。这行代码还忽略了任何可能的函数返回值。

许多函数确实就是这样调用的。在测试时,你会发现函数phpinfo()是非常有用的,因为它显示了已安装的PHP的版本、关于PHP的信息、Web服务器的设置和众多的PHP和服务器变量的值。这个的数不需要任何参数,通常可以忽略它的返回值。所以,可以使用如下所示方式调用函数phpinfo():

phpinfo();

然而,大多数函数都需要一个或更多的参数,它们都是函数的输入参数。我们通过将数据或变量名放在函数名称后面的括号内,从而以参数形式传给函敬。为函数提供一个参数并对其进行调用如下所示:

function_name('parameter');

在这个例子中,所使用的参数是一个只包含parameter的字符串,但是,依据函数的不同,如下所示的调用也是可以的:

function_name(2);
function_name(7.99);
function_name($variable);

在最后一行中, $variable可以是任何一种PHP变量, 包括数组或对象。
参数可以是任何数据类型, 但特定的函数通常会要求特定的数据类型。

可以通过函数原型来了解函数所需的参数个数. 每一个参数所表示的对象以及每一个参数的数据类型。 通常, 在本书中, 当我们描述一个函数时, 会给出一个函数的原型。

fopen()的函数原型如下:

resource fopen ( string filename, string mode, [ bool use_include_path, [resource zcontext]] )

例子中, 函数名称前面的单词 “ resource ” 告诉我们这个函数会返回一个资源(即一个打开的文件句柄)。 而函数的参数在括号的里面。
在fopen()的例子中, 函数原型中给出了4个参数。 文件名称、 打开模式这两个参数都是字符串, 而 use_include_path是一个布尔值, 而参数context是一个资源。 use_include_path外面的方括号指明了这个参数是可选的。 可以给可选参数赋值也可以忽略它们, 如果忽略它们则会使用默认值。 但是 , 请注意, 一个具有多个可选值的函数, 必须按照从右到左的顺序使用默认值。 例如, 当使用fopen ()函敬, 可以不给出context参数 , 或者可以不提供use_include_path和 context参数; 但是, 不能不提供use_include_path参数, 而只提供context参数。

在了解这个函数的函数原型后, 可以知道下面的fopen()的调用是有效的:

$name = myfile.txt;
$openmode = 'r';
$fp = fopen($name,$openmode);

以上代码调用了open ()函数, 函数的返回值将保存在变量$fp中。 对于这个例子来说, 我们传递给函数一个名为$name的变量, 它包含了要打开文件的名称, 还有一个名为 $openmode的变量、 立包含了 一个表示要打开文件的字符串, 表示文件的打开模式。 我们并没有给出第三个和第四个可选参数。

二、调用未定义的函数

如果调用一个并不存在的函数, 会得到一个错误信息。
如果看到这个错误信息, 必须对两件事情进行检查:

1.函数名称的拼写是否正确。
2.这个函数是否存在于所用的PHP版本中。

请注意.函数调用将不区分大小写,所以调用function_name()Function Name()FUNCTION_NAME()都是有效的,而且都将返回相同的结果。可以按照便于自己阅读的方式任意使用大小写.但应该尽量保持一致。大多数PHP文档使用的命名惯例是:所有都用小写字母。

注意到函数名称和变量名称是不同的,这一点很重要。变量名是区分大小写的,所以$Name和$name是两个不同的变量.但Name()和name()则是同一个函数。

三、理解为什么要定义自己的函数

在前面,已经了解了使用PHP的某些内置函数的例子。但是,编程语言的真正功能是通过创建你自己的函数来实现的。

PHP内置函数允许和文件进行交互、使用数据库、创建图形,还可以连接其他服务器。
但是,在实际工作中,有许多时候所需要的东西是语言的创建者无法预见到的。所以我们可以编写自己的函数来完成任何所需的务。我们的代码可能是已有函数和自己逻辑的混合体,通过它来完成我们的任务。

如果正在为一个任务编写一段代码,而很可能这段代码将在一个脚本的多处或是多个脚本中都要使用,那么最明智的方法是将这段代码声明为函数。
声明一个函数可以让我们像内置函数那样使用自己的代码。只要简单地调用这个函数并提供给它必需的参数。这就意味着.在整个脚本中,都可以调用和多次重复使用相同的函数。

四、了解基本的函数结构

一个函数声明将创建或者声明一个新的函数。声明是以关键字function开始的,接下来,给出函数的名称和必要的参数,然后再给出每次调用这个函数时执行的代码。

在这里,给出一个常见的函数声明:

function my_function(){
echo 'my function was called';
}

这个函数声明是以function开始的, 这样读者和PHP解释器都将知道这是一个用户定义 的函数。 该函数名称是my_function 。可以使用如下所示的命令调用这个新函数:my_function();

内置函数在所有PHP脚本中都可以使用, 但是如果声明了自己的函数, 它们只是在声明它们的脚本中可以使用。 将经常用到的函数包含在一个文件中是一个很好的主意。 然后可以在所有脚本中调用require()语句, 这样这些函数就可以使用了。

在一个函数中, 花括号包括了完成所要求任务的代码。 在花括号中 ,可以包含任何在PHP脚本的其他地方都合法的代码, 其中包扩函数调用、 新的变量或函数声明、 require()或 include()语句类声明以及 HTML脚本。 如果希望在一个函数中退出PHP并输入HTML脚本, 可以像在脚本其他地方做的那样一一使用一个封闭的PHP标记, 然后再编写HTML。
下面代码是前面例子的一个合法的修改,其输出结果是一样的:

<?php
function my_function(){
?>
my function was called
<?php
}
?>

请注意, PHP代码被封闭在一对匹配的PHP开始和结束标记之间。 在本书的大多数小段代码示例中, 并没有使用这些标记。 它们被显示出来是因为在这些例子中有这样的要求。

函数的命名

在给函数命名的时候, 最重要的就是函数名称必须精炼但又要有描述性。 如果函数是用来创建页盾的, 那么pageheader()或page_header()是不错的名称。

函数命名具有如下几个限制:
函数名称不能和已有的函数重名。
2.函数名称只能包含字母、 数字和下画钱。
函数名称不能以数字开始。
许多语言允许重复使用函数名称。 这个特性叫做函数的重载。 但是PHP不支持函数重载.

所以自定义函数不能和内置函数或是用户已定义的函数重名。 请注意, 虽然每个PHP脚本知道所有内置函数, 但对于用户定义的函数, PHP只能识别那些存在于本脚本之中的。 这就意味着,虽然可以在不同的文件中重复使用一个函数名, 但这会引起也乱, 所以应该避免

请注意, 虽然$name并不是一个函数的合核名称, 但是一个类似于如下所示的函数调用:
$name() ;
也可以正确地执行, 这是根据$name的值来确定的。 其原因就是PHP可以取出保存在$name中的值, 寻找具有那个名称的函数, 并且调用该函数。 这种函数类型被称为可变函数, 而且有时候是有用的。

五、使用参数

要使函数正常工作, 它们中的大多数都需要一个或多个参数。 参数允许将数据传给函数。
传递参数允许我们获得在函数外面生成的数据。

也可以声明能够接收可变参数数量的函数。 通过3个帮助器函数: func_num_args()、func_get_arg ()以及func_get_args(), 可以确定已经传递了多少个参数以及这些参数的值。

func_num_args()函数将返回传入的参数数。func_get_args()函数将返回参数的数组。或者,可以使用func_get_ arg()函数一次获得一个参数,该函数需要以希望访问的参数个数作为参数(参数从0开始)。

六、理解作用域

当在包含文件中使用变量的时候,只需要在脚本中的require()include()语句前声明它们,但是在使用函数的时候,则要明确地将这些变量传递给函数。 一方面是因为没有将变量传给所需或包含文件的机制,另一方面是因为变量的作用域相对于函数是不同的。

变量的作用域可以控制变量在哪里是可见并且可用的。不同的编程语言有不同的变量作用域规则。PHP具有相当简单的规则:

1.在函数内部声明的变量作用域是从声明它们的那条语句开始到函数末尾。这叫做函数作用域。这些变量称为局部交量

2. 在函数外部声明的变量作用域是从声明它们的那条语句开始到文件末尾,而不是函数内部。这叫做全局作用域。这些变量称为全局变量。

3.特殊的超级全局变量在函数内部和外部都是可见的。

4.使用require()include()并不影响作用域。如果这两个语句用于函数内部,函数作用域适用。如果它不在函数内部,全局作用域适用。

5.关键字“global”可以用来手动指定一个在函数中定义或使用的变量具有全局作用域。

6.通过调用unset($variable_name)可以手动删除变量。如果变量被删除,它就不在参数所指定的作用域中了。

注意:函数在被调用之前是不会执行的!
如果希望一个在函数内部创建的变量具有全局域, 可以按如下方式使用关键字 “global”。
函数在哪里声明并不重要,重要的是在哪里调用并执行其中的代码。
当一个变量要在整个脚本都要用到时,也可以在脚本的开始处使用关键字“global”。

七、参数的引用传递和值传递

如果希望编写一个名为increment ()的函数来增加一个变量的值, 我们可能会按如下方式编写这个函数:

function increment($value, $amount = 1) { 
$value = $value +$amount; 
}

这段代码是设有用的。 下面测试代码的输出结果是 “ 10”.

$value = 10; 
increment ($value); 
echo $value; 

$value的内容没有被修改。 这要归因于作用域规则。 这段代码将创建一个名为$value的变量, 它的值是10。 然后调用函数increment ()。 当函数被调用肘, 它内部的变量$value被创建。 它的值加上 1,所以$value在函数内部的值为11,直到函数结束, 接下来我们返回到调用它的代码。 在这段代码中, 变量$value是一个不同的变量, 具有全局域, 所以它的值没有变。
解决这个问题的一个办法是将函数内的$value声明为全局变量, 但这意味着为了使用这个函数, 要进行变量运算的变量需要被命名为$value。

更好的办法是使用引用传递。 这里, 在参数被传递给函数的时候, 函数不会再创建一个新变量, 而是函数获得一个原来变量的引用。 这个引用有一个变量名称, 它以美元符号开始, 可以像另一个变量那样使用它。 其区别在于它不是获得变量本身的值, 而是指向原来的值。 任何对该引用的修改都会影响到原始变量值。
可以通过在函数定义的参数名前加一个地址符(&) 来指定参数的引用传递。 在函数调用处不用修改。

前面的increment()的例子就可以修改为引用传递参数, 这样它就可以正常工作了。

function increment(&$value, $amount = 1) { 
$value =$value +$amount; 
}
八、使用return关键字

关键字”return”将终止函数的执行。当一个函数的执行结束时要么是因为所有命令部执行完了,要么就是因为使用了关键字“return”。在函数结束后,程序返回到调用函数的下一条语句。
内置函数isset()将告诉我们一个变量是否已经被创建并被赋值了。
布尔值“true”和“false”可以分别用整数“1”和“0”来表示,虽然他们是不同的数据类型。

九、实现递归

PHP支持递归函数。递归函数就是函数调用自己本身。这些函数特别适用于浏览动态数据结构,例如连接列表和树。

但是,几乎没有基于Web的应用程序要求使用如此复杂的数据结构,所以我们很少使用递归函数。在很多情况下,递归可以用来取代循环,因为二者都是重复做一些事情。递归函数比循环慢而且要占用更多内存,所以应该尽可能多用些循环。

当递归方法的代码比循环方法的代码更简短、 更美观的时候, 我们可能会选择使用递归, 但是在应用领域通常不会这样。
虽然递归看上去更美观,但程序员常会忘记给出递归的终止条件。 这意味着函数会一直重复下去直到服务器内存耗尽 , 或者达到了最大调用次数。

十、命名空间

通常, 命名空闹是一个抽象的容器, 它可以包含一组标识符:在PHP中, 命名空间可以包含你所定义的函数 、常量以及类。 从结构的角度看, 为自定义函数和类定义命名空间的优点包 括如下:
1.一个命名空间中的所有函数、 类和常量都将自动冠以名称空间前缀。
2.非全路径的类 、 函数和常量名称将在运行时解析, 在查看全局空间之前, 将首先查看命名空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值