function 函数名([参数1,参数2...])
{
函数体;
return 返回值;
}
2、使用双层for循环输出表格
function table(){
echo "<table align='center' border='1px' width='600px'>";
echo "<caption><h1>通过函数输出表格</h1></caption>";
for($out=0;$out<10;$out++){
$bgcolor = $out%2 == 0 ? "#FFFFFF" : "#DDDDDD";
echo "<tr bgcolor=".$bgcolor.">";
for($in=0;$in<10;$in++){
echo "<td>".$out*10+$in."</td>";
}
echo "</tr>";
}
echo "</table>";
}
\
3、函数tabel()改写
function table($tableName,$rows,$cols){
echo "<table align='center' border='1px' width='600px'>";
echo "<caption><h1>$tableName</h1></caption>";
for($out=0;$out<$rows;$out++){
$bgcolor = $out%2 == 0 ? "#FFFFFF" : "#DDDDDD";
echo "<tr bgcolor=".$bgcolor.">";
for($in=0;$in<$cols;$in++){
echo "<td>".($out*$cols+$in)."</td>";
}
echo "</tr>";
}
echo "</table>";
}
table("此时你是我的唯一",5,3);
4、PHP变量的范围 (分为局部变量和全局变量)
局部变量也称为内部变量,是在函数内部声明的变量,其作用域仅限于函数内部。
局部变量从存储方式上可分为动态存储类型和静态存储类型。函数中的局部变量,如果专门声明为static存储类别,默认都是动态地分配存储空间的。
其中的内部动态变量在函数调用结束后自动释放。如果希望在函数执行后,其内部变量依然保存在内存中,应使用静态变量。在函数执行完毕后,静态变量
并不会消失,而是在所有对该函数的调用之间共享,即在函数再次执行时,静态变量将接续前次的结果继续运算,并且仅在脚本的执行期间函数第一次被调用时
被初始化。要声明函数变量为静态的,需要关键字static。自行理解!
function demo($one){
$two = $one;
echo "在函数内部执行:$two+$one=".($two+$one)."<br/>";
}
demo(200);
echo "在函数外部执行:$two+$one=".($two+$one); //非法访问
全局变量也称外部变量,是在函数的外部定义的,他的作用域变量定义处开始,
到本程序文的结尾。
在函数中若要使用全局变量,必须要利用global关键字定义目标变量,以告诉函数主体此变量为
全局变量。
$one = 200;
$two = 100;
function demo(){
//在函数内部使用global关键字加载全局变量$one和$two
global $one,$two;
echo "运算结果:$two+$one=".($two+$one)."<br/>"; //300
echo "运算结果:".($GLOBAL['two']+$GLOBAL['one'])."<br/>";
}
5、PHP函数参数的种类
常规参数的函数
string example(string name,int age,double height)
伪类型参数的函数:
PHP的伪类型:mixed number callback 三种
mixed funName(mixed $args)
number funName(number $args)
引用参数的函数:
如果函数中的形参中有使用"&"修饰的参数,则在调用该函数时就必须传入一个变量给这个参数,而不能传递一个值。
void funName(array $&arg)
默认参数的函数:
默认值必须是常量表达式,不能是变量、类成员或者函数调用。PHP允许使用数组和特殊类型NULL作为默认参数。
mixed funName(string name[,string value[,int age]]) // 在参数列表中出现使用[]描述的参数
function person($name="张三",$age=20,$sex="男"){
echo "我的名字是:{$name},我的年龄是{$age},我的性别是{$sex}<br/>";
}
可变个数参数的函数:
func_get_args();//将所有传递给脚本的函数的参数当作一个数组返回
func_num_args();//返回参数的总数
mixed func_get_arg(int $arg_num);//返回参数列表的某一项(0.....)
mixed funName(string arg[,string ...])
回调函数:函数参数为一个函数
mixed funName(callback arg) //在参数列表中使用伪类型callback描述
了解变量函数、使用变量函数声明和应用回调函数,借助call_user_func_array()函数自定义回调函数,类静态函数和对象的方法回调;
//变量函数不能用于语言结构,例如echo()
//print()、unset()、isset()、empty()
//include()、require()及类似的语句
function one($a,$b){
return $a+$b;
}
function two($a,$b){
return $a+$b+$b*$b;
}
function three($a,$b){
rerurn $a*$a*$a+$b*$b*$b;
}
$result = "one";
//$result = "two";
//$result = "three";
echo $result(1,2);
function filter($fun){
$fun();
}
function test(){
echo "haha!";
}
function test2(){
echo "houhou!";
}
filter("test");
filter("test2");//haha!houhou!
function fun($msg1,$msg2){
echo '$msg1='.$msg1;
echo '<br/>';
echo '$msg2='.$msg2;
}
call_user_func_array('fun',array('Lamp','兄弟连'));
//类静态调用和对象的方法调用
class Demo{
static function fun($msg1,$msg2){
echo '$msg1='.$msg1;
echo '<br/>';
echo '$msg2='.$msg2;
}
}
class Test{
function fun($msg1,$msg2){
echo '$msg1='.$msg1;
echo '<br/>';
echo '$msg2='.$msg2;
}
}
//类静态调用
call_user_func_array(array('Demo','fun'),array('Lamp','兄弟连'));
//对象的方法调用
call_user_func_array(array(new Test(),'fun'),array('Lamp','兄弟连'));
callback("函数名称字符串"); //回调全局函数
callback(array("类名称字符串","类中静态方法名称字符串"));//回调类中的静态成员方法
callback(array(对象引用,"对象中方法名称字符串");//回调对象中的静态成员方法
递归函数:函数调用自身
6、使用自定义函数库
函数库并不是定义函数的PHP语法,而是编程时的一种设计模式。函数是结构化程序设计的模块,是实现代码重用的最重要的核心。为了更好的组织代码,使自定义的函数可以在同一个项目的多个文件中使用,通常将多个自定义的函数组织到同一个文件或多个文件中。这些收集函数定义的文件就是创建的PHP函数库。如果在PHP的脚本中想使用这些文件中定义的函数,就需要使用include、require、include_once、require_once中的一个函数,将函数库文件载入到脚本程序中。
include和require语句,都是包括并运行指定文件。不同之处在于,对include语句来说,在执行文件时每次都要进行读取和评估;而对require来说,文件只处理一次
(实际上,文件内容替换了require语句),这就意味着如果可能执行多次的代码,则使用require效率比较高。另外,如果每次执行代码时,读取不同的文件,或者有通过一组
文件迭代的循环,就是用include语句。
require 的使用方法如 require("MyRequireFile.php");
。这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require 所指定引入的文件,使它变成 PHP 程序网页的一部份。常用的函数,亦可以这个方法将它引入网页中。
include 使用方法如 include("MyIncludeFile.php");
。这个函数一般是放在流程控制的处理部分中。PHP 程序网页在读到 include 的文件时,才将它读进来。这种方式,可以把程序执行时的流程简单化。
他们两个的用途是完全一样的,不一定非得哪个放在最前面哪个放在中间。他们最根本的区别在于错误处理的方式不一样。
require一个文件存在错误的话,那么程序就会中断执行了,并显示致命错误
include一个文件存在错误的话,那么程序不会中端,而是继续执行,并显示一个警告错误。
以下为补充:
1. include有返回值,而require没有。
2. include()包括并运行指定文件 在处理失败时include() 产生一个警告,被导入的程序代码都会被执行,而且这些程序在执行的时候会拥有和源文件中呼叫到include()语句的位置相同的变量范围。你可以导入同一个服务器中的静态页面。
3. include_once()的作用和include()是几乎相同的
唯一的差别在于include_once()会先检查要导入的档案是不是已经在该程序中的其它地方被导入过了,如果有的话就不会再次重复导入(这项功能有时候是很重要的,比方说要导入的里面宣告了一些你自行定义好的函数,那么如果在同一个程序重复导入这个文件,在第二次导入的时候便会发生错误讯息,因为PHP不允许相同名称的函数被重复宣告第二次)。
4. require()会将目标文件的内容读入,并且把自己本身代换成这些读入的内容 在处理失败时require() 则导致一个致命错。
这个读入并且代换的动作是在PHP引擎编译你的程序代码的时候发生的,而不是发生在PHP引擎开始执行编译好的程序代码的时候(PHP 3.0引擎的工作方式是编译一行执行一行,但是到了PHP 4.0以后就有所改变了,PHP 4.0是先把整个程序代码全部编译完成后,再将这些编译好的程序代码一次执行完毕,在编译的过程中不会执行任何程序代码)。require()通常来导入静态的内容,而include()则适合用导入动态的程序代码。
5. 如同include_once(),require_once()会先检查目标文件的内容是不是在之前就已经导入过了,如果是的话,便不会再次重复导入同样的内容。
5. require是无条件包含也就是如果一个流程里加入require,无论条件成立与否都会先执行require。
7. require通常放在PHP程序的最前面,PHP程序在执行前,就会先读入require所指定引入的文件,使它变成PHP程序网页的一部份。常用的函数,亦可以这个方法将它引入网页中。
8. include一般是放在流程控制的处理部分中PHP程序网页在读到include的文件时,才将它读进来。这种方式可以把程序执行时的流程简单化。
7、PHP匿名函数和闭包
匿名函数:一个没有名称的函数。
php的闭包(Closure)也就是匿名函数,是PHP5.3引入的。
闭包的语法很简单,需要注意的关键字就只有use,use是连接闭包和外界变量。
function callback($fun) {
$fun();
}
$msg = "Hello, everyone";
$fun = function () use($msg) {
print "This is a closure use string value, msg is: $msg. <br />/n";
};
$msg = "Hello, everybody";
callback($fun);
闭包的一个重要概念就是在内部函数中可以使用外部变量,需要通过关键字use来连接闭包函数和外界变量,这些变量都必须在函数或类的头部声明。闭包函数是从父作用域中继承变量,与使用全局变量是不同的,全局变量存在于一个全局的范围,无论当前正在执行的是哪个函数。而闭包的父作用域是定义该笔包的函数,不一定是调用他的函数。
闭包的作用
1. 减少foreach的循环的代码
比如手册http://php.net/manual/en/functions.anonymous.php 中的例子Cart
<?php
// 一个基本的购物车,包括一些已经添加的商品和每种商品的数量。
// 其中有一个方法用来计算购物车中所有商品的总价格。该方法使用了一个closure作为回调函数。
class Cart
{
const PRICE_BUTTER = 1.00;
const PRICE_MILK = 3.00;
const PRICE_EGGS = 6.95;
protected $products = array();
public function add($product, $quantity)
{
$this->products[$product] = $quantity;
}
public function getQuantity($product)
{
return isset($this->products[$product]) ? $this->products[$product] :
FALSE;
}
public function getTotal($tax)
{
$total = 0.00;
$callback =
function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
//使用用户自定义函数对数组中的每个元素做回调处理
array_walk($this->products, $callback);
return round($total, 2);;
}
}
$my_cart = new Cart;
// 往购物车里添加条目
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
// 打出出总价格,其中有 5% 的销售税.
print $my_cart->getTotal(0.05) . "\n";
// The result is 54.29
?>
这里如果我们改造getTotal函数必然要使用到foreach。
2. 减少函数的参数
function html($code , $id="", $class=""){
if ($id !== "") $id = " id = \"$id\"" ;
$class = ($class !== "")? " class =\"$class\">":">";
$open = "<$code$id$class";
$close = "</$code>";
return function ($inner = "") use ($open, $close){
return "$open$inner$close";
};
}
如果是使用平时的方法,我们会把inner放到html函数参数中,这样不管是代码阅读还是使用都不如使用闭包。
3. 解除递归函数
<?php
$fib = function($n) use(&$fib) {
if($n == 0 || $n == 1) return 1;
return $fib($n - 1) + $fib($n - 2);
};
echo $fib(2) . "\n"; // 2
$lie = $fib;
$fib = function(){die('error');};//rewrite $fib variable
echo $lie(5); // error because $fib is referenced by closure
注意上题中的use使用了&,这里不使用&会出现错误fib(n-1)是找不到function的(前面没有定义fib的类型)
所以想使用闭包解除循环函数的时候就需要使用
<?php
$recursive = function () use (&$recursive){
// The function is now available as $recursive
}
这样的形式。
4. 延迟绑定
如果你需要延迟绑定use里面的变量,你就需要使用引用,否则在定义的时候就会做一份拷贝放到use中
<?php
$result = 0;
$one = function()
{
var_dump($result);
};
$two = function() use ($result)
{
var_dump($result);
};
$three = function() use (&$result)
{
var_dump($result);
};
$result++;
$one(); // outputs NULL: $result is not in scope
$two(); // outputs int(0): $result was copied
$three(); // outputs int(1)
使用引用和不使用引用就代表了是调用时赋值,还是申明时候赋值