PHP和Mysqlweb应用开发核心技术 第1部分 Php基础-3 代码组织和重用2

  从本章中,我们了解

  .创建可以调用的函数以便重用代码

  .把参数传递给函数并且从函数返回值和脚本的不同部分中的变量和数据进行交互

  .把代码和函数组存入到其他文件中,并且我们的脚本内包含这些文件.

  3.1基本代码重用:函数

  3.1.1 定义和调用函数

  关键字function通知php这是一个函数,后面跟着的是函数的名称,它可以是字母、数字、字符或下划线

  函数名称之后是参数列表,然后是函数体。在其它语言中名称相同、但是参数列表不同的函数,php不支持这一特性。

  

复制代码 代码如下:

  <?php

  function booo_spooky()

  {

  echo "I am booo_spooky. This name is okay!<br/>\n";

  }

  function ____333434343434334343()

  {

  echo <<<DONE

  I am ____333434343434334343. This is an awfully

  unreadable function name. But it is valid.

  DONE;

  }

  //

  // This next function name generates:

  //

  // Parse error: syntax error, unexpected T_LNUMBER,

  // expecting T_STRING in

  // /home/httpd/www/phpwebapps/src/chapter03/playing.php

  // on line 55

  //

  // Function names cannot start with numbers

  //

  function 234letters()

  {

  echo "I am not valid<br/>\n";

  }

  //

  // Extended characters are ok.

  //

  function grüß_dich()

  {

  echo "Extended Characters are ok, but be careful!<br/>\n";

  }

  //

  // REALLY extended characters are ok too!! Your file will

  // probably have to be saved in a Unicode format though,

  // such as UTF-8 (See Chapter 5).

  //

  function 日本語のファンクション()

  {

  echo <<<EOT

  Even Japanese characters are ok in function names, but be

  extra careful with these (see Chapter 5).

  EOT;

  }

  ?>

  3.1.2 把参数传递给函数

  基本语法:为了把参数传递给函数,在调用函数时需要把参数值 括在括号中,以逗号分隔。每个被传递的参数可

  以是任何合法表达式,可以是变量、常量值、运算符的结果,甚至可以是函数调用。

  

复制代码 代码如下:

  <?php

  function my_new_function($param1, $param2, $param3, $param4)

  {

  echo <<<DONE

  You passed in: <br/>

  \$param1: $param1 <br/>

  \$param2: $param2 <br/>

  \$param3: $param3 <br/>

  \$param4: $param4 <br/>

  DONE;

  }

  //

  // call my new function with some values.

  //

  $userName = "bobo";

  $a = 54;

  $b = TRUE;

  my_new_function($userName, 6.22e23, pi(), $a or $b);

  ?>

  按引用传递:默认情况下,只有变量的值被传递给函数。因此,对这个参数或者变量的任何改动都只是在函数局部有效的

  

复制代码 代码如下:

  $x = 10;

  echo "\$x is: $x<br/>\n";

  function change_parameter_value($param1)

  {

  $param1 = 20;

  }

  echo "\$x is: $x<br/>\n";

  ?>

  输出: $x is :10

  $x is :10

  如果你的目的是函数实际地修改传递给它的变量,而不仅仅处理其值的拷贝,那么可以用引用(reference)传递的功能。这是通过使用&字符完成的

  

复制代码 代码如下:

  <?php

  function increment_variable(&$increment_me)

  {

  if (is_int($increment_me) || is_float($increment_me))

  {

  $increment_me += 1;

  }

  }

  $x = 20.5;

  echo "\$x is: $x <br/>\n"; // prints 20.5

  increment_variable(&$x);

  echo "\$x is now: $x <br/>\n"; // prints 21.5

  ?>

  参数的默认值

  在你期望参数具有支配地位的特定值的情况下,称为默认参数值(default argumentvalue)

  

复制代码 代码如下:

  <?php

  function perform_sort($arrayData, $param2 = "qsort")

  {

  switch ($param)

  {

  case "qsort":

  qsort($arrayData);

  break;

  case "insertion":

  insertion_sort($arrayData);

  break;

  default:

  bubble_sort($arrayData);

  break;

  }

  }

  ?>

  可变数量的参数:

  php能够把任意数量的参数传递给函数,然后使用func_num_args、func_get_arg和func_get_args取得参数值

  

复制代码 代码如下:

  <?php

  function print_parameter_values()

  {

  $all_parameters = func_get_args();

  foreach ($all_parameters as $index => $value)

  {

  echo "Parameter $index has the value: $value<br/>\n";

  }

  echo "-----<br/>\n";

  }

  print_parameter_values(1, 2, 3, "fish");

  print_parameter_values();

  ?>

  3.1.3 从函数返回值

  一些其他语言把在退出之前只执行一些代码的子例程和执行一引起代码并且把值返回调用者的函数区分开来,php和它们不同,所有php函数在返回调用者时

  都有一个值和它相关联。对于没有明确的返回值的函数,返回值为null

  

复制代码 代码如下:

  <?php

  function does_nothing()

  {

  }

  $ret = does_nothing();

  echo '$ret: ' . (is_null($ret) ? '(null)' : $ret) . "<br/>";

  ?>

  如果希望返回非null时,利用return把它和一个表达式关联

  

复制代码 代码如下:

  <?php

  function is_even_number($number)

  {

  if (($number % 2) == 0)

  return TRUE;

  else

  return FALSE;

  }

  ?>

  当你希望从函数返回多个值 时,把结果作为数组传递回来是方便的方式

  

复制代码 代码如下:

  <?php

  function get_user_name($userid)

  {

  //

  // $all_user_data is a local variable (array) that temporarily

  // holds all the information about a user.

  //

  $all_user_data = get_user_data_from_db($userid);

  //

  // after this function returns, $all_user_data no

  // longer exists and has no value.

  //

  return $all_user_data["UserName"];

  }

  ?>

  3.1.4 函数内的变量范围

  函数级别变量:

  声明它们的函数内是合法,并且在函数的调用之间不记忆它们的值

  

复制代码 代码如下:

  <?php

  $name = "Fatima";

  echo "\$name: $name<br/>\n";

  function set_name($new_name)

  {

  echo "\$name: $name<br/>\n";

  $name = $new_name;

  }

  set_name("Giorgio");

  echo "\$name: $name<br/>\n";

  ?>

  静态变量:

  static作为前缀的变量在函数调用之间保持它们的值不变,如果声明变量时为其赋值了,在运行当前脚本时,php只在第一次遇到这个变量时执行赋值

  

复制代码 代码如下:

  <?php

  function increment_me()

  {

  // the value is set to 10 only once.

  static $incr=10;

  $incr++;

  echo"$incr<br/>\n";

  }

  increment_me();

  increment_me();

  increment_me();

  ?>

  脚本内声明的变量("全局变量")

  

复制代码 代码如下:

  <?php

  $name = "Fatima";

  echo "\$name: $name<br/>\n";

  function set_name($new_name)

  {

  echo "\$name: $name<br/>\n";

  $name = $new_name;

  }

  set_name("Giorgio");

  echo "\$name: $name<br/>\n";

  ?>

  l输出结果:

  $name: Fatima

  $name:

  $name: Fatima

  如果在 内部组函数加一个globa ,那么输出结果

  $name: Fatima

  $name: Fatima

  $name: Giorgio

  3.1.5 函数范围和可用性

  3.1.6 把函数作为变量使用

  

复制代码 代码如下:

  <?php

  function Log_to_File($message)

  {

  // open file and write message

  }

  function Log_to_Browser($message)

  {

  // output using echo or print functions

  }

  function Log_to_Network($message)

  {

  // connect to server and print message

  }

  //

  // we're debugging now, so we'll just write to the screen

  //

  $log_type = "Log_to_Browser";

  //

  // now, throughout the rest of our code, we can just call

  // $log_type(message) and change where it goes by simply

  // changing the above variable assignment!

  //

  $log_type("beginning debug output");

  ?>

  但是php包含很多不能用作变量函数的语言结构,这种结构的明显例子是echo、print、var_dump、print_r、isset、unset、is_null is_type

  3.2 中级代码重用:使用和包含文件

  3.2.1 把代码组织到文件中

  对通用功能进行分组: 如果希望把很多函数保存到单一位置上,典型情况是一个文件,即代码库(code library)

  生成一致的接口

  

复制代码 代码如下:

  <?php

  // circle is (x, y) + radius

  function compute_circle_area($x, $y, $radius)

  {

  return ($radius * pi() * pi());

  }

  function circle_move_location(&$y, &$x, $deltax, $deltay)

  {

  $x += $deltax;

  $y += $deltay;

  }

  function compute_circumference_of_circle($radius)

  {

  return array("Circumference" => 2 * $radius * pi());

  }

  ?>

  通过使用这此函数具有一致的名称、参数顺序以及返回值 ,可以显著地减少失败的可能性和代码中的缺陷。

  

复制代码 代码如下:

  <?php

  //

  // all routines in this file assume a circle is passed in as

  // an array with:

  // "X" => x coord "Y" => y coord "Radius" => circle radius

  //

  function circles_compute_area($circle)

  {

  return $circle["Radius"] * $circle["Radius"] * pi();

  }

  function circles_compute_circumference($circle)

  {

  return 2 * $circle["Radius"] * pi();

  }

  // $circle is passed in BY REFERENCE and modified!!!

  function circles_move_circle(&$circle, $deltax, $deltay)

  {

  $circle["X"] += $deltax;

  $circle["Y"] += $deltay;

  }

  ?>

  3.2.2 选择文件名和位置

  为了防止web用户打开.inc文件,我们使用两种机制防止这种情况发生,首先,在构成文档目录树中,我们确保web服务器不允许用户浏览或者加载

  不希望他们进行这些操作,在16章保护web应用程序中介绍,然后,然后将配置浏览器允许用户浏览.php和.html文件,但是不能浏览.inc文件

  防止这种问题的第二个途径不把代码入在文档树中,或存入其它目录,并且要么明确地在我们的代码中引用这个目录,通知php总是查看这个目录

  3.2.3 在脚本中包含库文件

  include 和require,这两个区别在于,当找不到文件时,require输出错误,而include输出警告。

  

复制代码 代码如下:

  <?php

  include('i_dont_exit.inc');

  require('i_dont_exit.inc');\

  ?>

  include和require在哪里查找文件

  你可以指定明确的路经:

  require("/home/httpd/lib/frontend/table_gen.inc');

  require('http://www.cnblogs.com/lib/datafuncs.inc');

  require(d:\webapps\libs\data\connetions.inc');

  如果没有指定明确路径,php就在当前目录中查找要包含的文件,然后查找php.ini文件中的include_path设置中列出的目录.

  在windows是include_path=".;c:\php\include;d:\webapps\libs“设置完成后,不要忘记重新启动web服务器。

  include和require做了什么

  包含在脚本标记中的任何内容都作为一般 php脚本处理。

  清单3-1和清单3-2显示php脚本和用于包含的简单文件

  清单3-1

  3.2.4 把包含用于页面模板化

  <p align='center'>

  <b>

  <?php echo $message; ?>

  </b>

  </p>

  清单3-2

  

复制代码 代码如下:

  <html>

  <head>

  <title>Sample</title>

  </head>

  <body>

  <?php

  $message = "Well, Howdy Pardner!";

  include('printmessage.inc');

  ?>

  </body>

  </html>

  文件包含和函数范围

  当把函数从脚本移动到包含文件时,会如何影响函数作用范围及调用它们的能力。

  如果一个函数在另一个文件中,并且这个文件没有通过include和require包含在当前脚本中,那么调用是非法的

  为了避免这个问题,在脚本开头包含其他文件是个好主意。

  当共享变成问题时

  为了避免重复加载共享文件,可以用require_once()和include_once()语言结构防止函数或者结构重复定义的问题