ch05 代码重用与函数编写

代码重用与函数编写

代码重用的好处

目的:降低成本、增加可靠性并提高一致性

成本

使用已有软件的成本通常小于开发一个等价产品的成本;

购买软件产品的成本小于使用开源项目的成本(修改已有代码比编写新代码更困难)。

可靠性

重写代码时容易忽略的两种情况:一是原作者加入的某些功能代码,二是测试发现缺陷后对源代码添加的新代码。

=> 使用已有成熟的代码通常要比新的“绿色”代码更可靠

遗留代码(代码模块太陈旧):开发替代函数库以供组织结构使用

一致性

系统提供的外部接口应该是一致的:编写一段能和系统功能的其他部分保持一致的新代码。

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

1.作用:在PHP脚本载入文件。通常,这个文件可以包含任何希望在一个脚本中引入的内容,包括PHP语句、文本、HTML标记、PHP函数或PHP类。

二者几乎是相同的,唯一的区别在于语句执行失败后,require()将给出一个致命的错误,而include()只给出一个警告。

2.对应的变体函数分别是require_once()和include_once()。用于确保一个被引入的文件只能被引入一次,防止错误地引入同样的函数库两次,出现重复定义函数的错误。而且变体函数的运行速度比原函数更快。

require()函数–引入代码

#reusable.php
<?php
    echo "Here is a very simple PHP statement.<br />";
?>

在这里插入图片描述

#main.php
<?php
    echo "This is the main file.<br />";
    require('reusable.php'); #将被被请求的文件内容代替并执行
    echo "The script will end now.<br />";
?>

在这里插入图片描述

require()函数要点:注意处理文件扩展名和PHP标记的不同方式
- PHP并不会检查所需文件的扩展名。这就意味着,只要不想直接调用这个文件,就可以按任意方式命名该文件。例如,以.html命名reusable.php文件时,其中的PHP标记将会被视为为文本或HTML,不会被执行。
- 当使用require()语句载入该文件时,他会作为PHP文件的一部分被执行。
- 如果扩展名为.inc或其他非标准扩展名的文件保存在Web文档树中,并且用户直接在浏览器中载入他们,用户将可以以纯文本的形式查看源代码,包括任何密码。因此,将文件保存在Web文档树之外,或使用标准的文件扩展名非常重要。

require()函数–制作web站点模板

<!-- home.html -->
<!DOCTYPE html>
<html>
<head>
  <title>TLA Consulting Pty Ltd</title>
  <link href="styles.css" type="text/css" rel="stylesheet">
</head>
<body>

  <!-- page header -->
  <header>    
    <img src="logo.gif" alt="TLA logo" height="70" width="70" /> 
    <h1>TLA Consulting</h1>
  </header>

  <!-- menu -->
  <nav>
    <div class="menuitem">
      <a href="home.html">
      <img src="s-logo.gif" alt="" height="20" width="20" /> 
      <span class="menutext">Home</span>
      </a>
    </div>

    <div class="menuitem">
      <a href="contact.html">
      <img src="s-logo.gif" alt="" height="20" width="20" />  
      <span class="menutext">Contact</span>
      </a>
    </div>

    <div class="menuitem">
      <a href="services.html">
      <img src="s-logo.gif" alt="" height="20" width="20" /> 
      <span class="menutext">Services</span>
      </a>
    </div>

    <div class="menuitem">
      <a href="about.html">
      <img src="s-logo.gif" alt="" height="20" width="20" /> 
      <span class="menutext">About</span>
      </a>
    </div>
  </nav>

  <!-- page content -->
  <section>
     <h2>Welcome to the home of TLA Consulting.</h2>
     <p>Please take some time to get to know us.</p>
     <p>We specialize in serving your business needs
     and hope to hear from you soon.</p>
  </section>

  <!-- page footer -->
  <footer>
      <p>&copy; TLA Consulting Pty Ltd.<br />
      Please see our 
      <a href="legal.php">legal information page</a>.</p>
  </footer>

</body>
</html>

在这里插入图片描述

通常可以将这个文件分割,然后将这些部分分别命名为header.php、home.php和footer.php。header.php和footer.php都包含有在其他页面中可以重用的代码。

<!-- home.php -->
<?php
    require('header.php');
?><?php
    require('header.php');
?>
<!-- page content -->
<section>
    <h2>Welcome to the home of TLA Consulting.</h2>
    <p>Please take some time to get to know us.</p>
    <p>We specialize in serving your bussiness needs and hope to hear from your soon.</p>
</section>
<?php
    require('footer.php');
?>

注意!再通过require()调用文件的时候,文件名称并不会影响如何处理他们。

推荐策略:将.inc文件保存在一个目录中欧冠,而这个目录可以被脚本访问,但是被引入的文件不会被web服务器载入,也就是,保存在web文档树之外。

文件header.php包含了页面使用的CSS定义以及显示公司名称和导航菜单的表格。

<!-- header,php -->
<!DOCTYPE html>
<html>
<head>
  <title>TLA Consulting Pty Ltd</title>
  <link href="styles.css" type="text/css" rel="stylesheet">
</head>
<body>

  <!-- page header -->
  <header>    
    <img src="logo.gif" alt="TLA logo" height="70" width="70" /> 
    <h1>TLA Consulting</h1>
  </header>

  <!-- menu -->
  <nav>
    <div class="menuitem">
      <a href="home.html">
      <img src="s-logo.gif" alt="" height="20" width="20" /> 
      <span class="menutext">Home</span>
      </a>
    </div>

    <div class="menuitem">
      <a href="contact.html">
      <img src="s-logo.gif" alt="" height="20" width="20" />  
      <span class="menutext">Contact</span>
      </a>
    </div>

    <div class="menuitem">
      <a href="services.html">
      <img src="s-logo.gif" alt="" height="20" width="20" /> 
      <span class="menutext">Services</span>
      </a>
    </div>

    <div class="menuitem">
      <a href="about.html">
      <img src="s-logo.gif" alt="" height="20" width="20" /> 
      <span class="menutext">About</span>
      </a>
    </div>
  </nav>

文件footer.php包含了再每个页面底部显示脚注的表格。

<!-- footer.php -->
<!-- page footer -->
 <footer>
      <p>&copy; TLA Consulting Pty Ltd.<br />
      Please see our 
      <a href="legal.php">legal information page</a>.</p>
  </footer>

</body>
</html>

在这里插入图片描述

如果希望保证一个文件将被当作普通文本或HTML,而且不会执行任何PHP脚本,可以使用readfile()作为替代方法。这个函数将回显文件内容,不会对其进行解析。

使用auto_prepend_file和auto_append_file

php.ini配置文件提供了两个配置项:auto_prepend_file和auto_append_file。通过将这两个选项指向页眉和脚注文件,你可以保证他们在每个页面载入之前或者之后载入。如果文件不存在,将产生一个警告。

#windows平台:
auto_prepend_file = 'c:/path/to/header.php'
auto_append_file = 'c:/path/to/footer.php'

#UNIX平台
auto_prepend_file = '/path/to/header.php'
auto_append_file = '/path/to/footer.php'

如果使用了这些指令,就不需要在输入include()语句,但页眉和脚注在页面中不再是页面的可选内容。

如果使用的是Apache Web服务器,可以对单个目录进行不同配置选项的设置和改变。要完成设置变更,必须将服务器设置为允许覆盖其主配置文件。要给目录设定自动预加入和自动追加,需要在该目录中创建一个名为.htaccess的文件。
.htaccess文件代码:
php_value auto_prepend_file "/path/to/header.php"
php_value auto_append_file "/path/to/footer.php"

- 没有等号
- 极大的灵活性,可以在一台只影响你的目录的共享机器上运行
- 缺点:目录中每个被读取和被解析的文件每次都要进行处理,而不是只在启动时处理一次,所以性能会有所降低

使用PHP函数

函数:包含了能够执行单个设计好的任务的代码,并且可以重复使用。

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

调用函数

phpinfo()函数:显示了已安装的PHP版本、PHP信息、Web服务器设置和大量不同的PHP和服务器变量值。

通过函数原型来了解函数所需的参数个数,每一个参数所表示的对象以及每一个参数的数据类型。

函数参数包括在括号里,可以给可选参数赋值也可以忽略他们,如果忽略他们,函数会使用默认值。一个具有多个可选参数的函数,必须按照从右到左的顺序使用默认值。

调用未定义函数

调用一个未定义的函数时显示以下错误:
在这里插入图片描述

PHP函数的错误信息:可以告诉我们错误出现在那个文件中,在文件的哪一行,以及试图调用的函数名称。
- 函数名称拼写是否正确?
- 这个函数是否存在于所用的PHP版本中?
- 函数是否属于没有安装或启用的扩展库?
- 函数所在文件是否被引入?
- 函数作用域是否正确?

PHP的一个缺点是函数命名规则没有统一。不统一的原因是PHP函数是基于C函数库实现的。

理解大小写和函数名称

函数调用不区分大小写!!!但应尽量保持一致并使用相同的大小写策略。

函数名称和变量名称不同,变量名称区分大小写。

自定义函数

声明一个函数可以让我们像内置函数那样使用自己的代码。

内置函数允许和文件进行交互、使用数据库、创建图形,还可以链接其他的服务器。

函数基本结构

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

自定义函数只能在声明他们的脚本中使用。将经常用到的函数包含在一个文件中,然后再所有脚本中调用require()语句,就可以在其他脚本中使用了。

在一个函数中,花括号包括了完成所要求任务的代码。在花括号中,可以包含任何在PHP脚本的其他地方都合法的代码,其中包括函数调用、新变量或函数声明、require()或include()语句、类声明以及HTML脚本。

函数命名

函数名必须精炼又有描述性。

函数命名的限制:
- 函数名称不能和已有的函数重名;
- 函数名称只能包含字母、数字和下划线;
- 函数名称不能以数字开始。

自定义函数不能和内置函数或是用户已定义的函数重名。虽然可以在不同的文件中重复使用一个函数名称,但这会议i年起混乱,应该避免。

参数使用

<!-- create_table.php -->
  <?php
#创建函数
  function create_table($data) {
     echo '<table>';
     reset($data);
     $value = current($data);
     while ($value) {
        echo "<tr><td>$value</td></tr>\n";
        $value = next($data);
     }
     echo '</table>';
   }
  #调用函数
   $my_data = ['First piece of data','Second piece of data','And the third'];
   create_table($my_data);
   ?>

在这里插入图片描述

传递参数允许我们获得在函数外部生成的数据。

<!-- create_table_2.php -->
 <?php
#创建函数2
  function create_table($data, $header=NULL, $caption=NULL) {
     echo '<table>';
     if ($caption) {
       echo "<caption>$caption</caption>"; 
     }
     if ($header) {
       echo "<tr><th>$header</th></tr>"; 
     }     
     reset($data);
     $value = current($data);
     while ($value) {
        echo "<tr><td>$value</td></tr>\n";
        $value = next($data);
     }
     echo '</table>';
   }
  #调用函数
   $my_data = ['First piece of data','Second piece of data','And the third'];
   $my_header = 'Data';
   $my_caption = 'Data about something';
   create_table($my_data, $my_header, $my_caption);
   ?>

在这里插入图片描述

参数为什么是可选的??因为已经在函数中为他们定义了默认值。

可选参数值不用全部给出;可以给出一部分而忽略一部分。参数将会按照从左到右的顺序进行赋值。

注意!!!可选参数值在调用时不能以间隔方式给出。

了解传递的参数个数以及参数值
- func_num_args() 返回传入参数的个数
- func_get_args()  返回参数数组
- func_get_arg()  逐个访问参数

理解作用域

变量作用域可以控制变量在代码中可见并可用的位置。
- 在函数内部声明的变量作用域是从声明它们的那条语句开始到函数末尾。这叫做函数作用域。这些变量成为局部变量。
- 在函数外部声明的变量作用域是从声明它们的那条语句开始到文件末尾,而不是函数内部。这叫做全局作用域。这些变量称为全局变量。
- 超级全局变量,它在函数内部和外部都是可见的。
- 使用require()和include()并不影响作用域。如果这两个语句用于函数内部,函数作用域适用,如果它不在函数内部,全局作用域适用。
- 关键字global可以用来指定一个在函数中定义或使用的变量具有全局作用域。
- 通过调用unset($variable_name)可以手动删除变量。如果变量被删除,它就不在函数所指定的作用域中了。
function fn(){
    $var = "contents";  # 变量$var是局部变量,具有函数作用域
}
fn();
echo $var; #变量$var是全局变量,具有全局作用域 
<?php
    function fn(){
        echo 'inside the function, at first $var = '.$var.'<br />';
        $var = 2;
        echo 'then, inside the function,$var = '.$var.'<br />';
    }
    $var = 1;
    fn(); #函数在调用之前是不会被执行的
    echo 'outside the function,$var = '.$var.'<br />';
?>

在这里插入图片描述

在函数内部创建的变量有全局作用域(函数调用结束之后,变量在函数外部也存在) <= 关键字global

<?php
    function fn(){
        global $var;
        $var = "contents";
        echo 'then, inside the function,$var = '.$var.'<br />';
    }

    fn();
    echo 'outside the function,$var = '.$var.'<br />';
?>

在这里插入图片描述

引用传递和值传递

<?php
    function incremnet($value, $amount = 1){
       $value = $value + $amount;
    }

    $value = 10;
    incremnet($value);
    echo $value;
?>

在这里插入图片描述

$value是一个不同的变量,内部的为函数作用域内,值为11.外部的为全局作用域,值为10.

函数参数调用的常规方式是值传递。当传递一个参数的时候,一个包含传入值的新变量将被创建。它是原来那个变量的拷贝。可以使用任意方式修改它,但函数外部原来变量值是不会被改变的。

如果需要修改传入变量的值,要使用按引用传递。此时,在参数被传递给函数的时候。函数不会再创建一个新变量,而是获得原变量的引用。这个引用有一个变量名称,它以$开始,可以像其他变量一样使用。其区别在于不是获得变量原本值,而是指向原值。任何对该引用的修改都会影响到原变量值。
- 通过再函数定义的参数名前加一个&来指定参数的按引用传递。
<?php
    function incremnet(&$value, $amount = 1){
       $value = $value + $amount;
    }

    $a = 10;
    echo $a.'<br />';
    incremnet($a);
    echo $a.'<br />';
?>

在这里插入图片描述

关键字return

关键字return将终止函数的执行。

<?php
    function test_return(){
       echo "This statement will be executed.";
       return;
       echo "This statement will never be executed.";
    }

   test_return();
?>

在这里插入图片描述

错误条件是使用return语句终止函数执行至结束处的常见原因。

<?php
    function larger($x, $y){
        if ((!isset($x)) || (!isset($y))){  #isset()内置函数确认变量是否已经被创建并赋值
            echo "This function requires two numbers.";
            return;
        }
        if ($x >= $y){
            echo $x.'<br />';
        }else{
            echo $y.'<br />';
        }
    }

    $a = 1;
    $b = 2.5;
    $c = 1.9;
    larger($a, $b);
    larger($c, $a);
    larger($d, $a);
?>

在这里插入图片描述

从函数返回值。通常执行特定任务但又不返回具体值的函数将返回true或false来表示函数执行是否成功。

<?php
    function larger($x, $y){
        if ((!isset($x)) || (!isset($y))){  #isset()内置函数确认变量是否已经被创建并赋值
            return false;
        }
        if ($x >= $y){
            return $x;
        }else{
            return $y;
        }
    }

    $a = 1;
    $b = 2.5;
    $c = 1.9;
    $d = NULL;
    echo larger($a, $b).'<br />';
    echo larger($c, $a).'<br />';
    echo larger($d, $a).'<br />';
?>

在这里插入图片描述

递归实现

递归函数就是函数调用函数本身。这些函数特别适用于浏览动态数据结构。递归函数将在内存中创建几个自身的拷贝,而且将产生多次函数调用的开销。

在很多情况下,递归可以用来取代循环。但是递归比循环慢而且要占用更多的内存。

# recursion.php
<?php
    # 以相反的顺序打印字符串的内容
    function reverse_r($str){  #递归
        if(strlen($str) > 0){
            reverse_r(substr($str, 1));
        }
        echo substr($str, 0, 1);
        return;
    }

    function reverse_i($str){   #循环
        for($i = 1; $i <= strlen($str); $i ++){
            echo substr($str, -$i, 1);
        }
        return;
    }

    reverse_r('Hello');
    echo '<br />';
    reverse_i('Hello');
?>

在这里插入图片描述

匿名(闭包)函数

匿名(闭包)函数:通常是没有名称的函数。。他们通常用在回调函数场景。也就是,传递给其他函数的函数。

可以用内联方式将函数声明为匿名函数,也可以使用变量来保存闭包函数。

闭包函数具有对全局作用域变量的访问,但必须在闭包函数定义中使用use关键字显示定义这些变量。

#closures.php
<?php

    $printer = function($value){echo "$value <br />";};  #使用变量保存闭包函数

    $products = [
        'Tires' => 100,
        'Oil' => 10,
        'Spark Plugs' => 4
    ];

    $markup = 0.20;

    $apply = function(&$val) use ($markup){  #指定具有全局作用域的$markup变量应该在匿名函数中可用
        $val = $val * (1 + $markup);
    };

    array_walk($products, $apply);

    array_walk($products, $printer);
?>

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值