1.函数
函数是一个固定的代码块,或者称为一个子程序,一个函数可以多次调用。函数实现了计算机模块化编程。
a.函数的定义
function 函数名(参数,参数){
//执行代码
}
- 函数的命名规则:函数以字母、下划线开头,后面跟的是数字、字母、下划线
- 函数名不区分大小写
- 函数可以多次调用
b.可变函数
function fun($args){
echo $args;
}
$str = 'fun';
$str('呵呵');
c.匿名函数
PHP从5.3开始支持匿名函数,匿名函数就是没有名字的函数,匿名函数保存在变量中
$fun = function ($args){
echo $args;
};
var_dump($fun);
$fun('呵呵');
d.函数的预加载
代码的执行过程,词法分析——语法分析——编译——加载编译的代码——执行,在执行代码之前,函数已经加载到内存中了
e.与函数有关的魔术常量
__FUNCTION__用来获取当前的函数名。
function funname(){
echo __FUNCTION__; //获取当前函数名
}
2.create_function()
- create_function(参数字符串,函数体字符串)
- create_function()用来创建函数,通过此函数只需要定义需要的函数即可
$leng = 'eng';
if($leng == 'ch'){
$fn = create_function('$name','echo \'你好\'.$name;');
}elseif($leng == 'eng'){
$fn = create_function('$name','echo \'hello\'.$name;');
}
$fn('李白');
3.function_exists()
判断函数是否存在
function FunctionName(){
echo 'FunctionName';
}
if(function_exists('FunctionName')){
FunctionName(); // 如果存在函数就调用
}else{
echo 'FunctionName函数不存在';
}
4.函数参数
- 实参
- 形参
a.函数的传值与传址
默认情况下,函数的值都是值传递,在定义函数的时候前面的参数上加上取地址,表示传递的是变量的地址
function fun($args){
$args = 'this is a string';
}
$stu = array('tom','berry');
fun($stu);
var_dump($stu);
//array(2) { [0]=> string(3) "tom" [1]=> string(5) "berry" }
function fun(&$args){
$args = 'this is a string';
}
$stu = array('tom','berry');
fun($stu);
var_dump($stu);
//string(16) "this is a string"
++如果在传递地址,在调用函数的时候不能直接写值,只能写变量++
b.参数的默认值
形式参数在定义的时候可以给参数赋一个默认值。
function fun($name='哈哈'){
echo "你好!{$name}<br>";
}
fun();//你好!哈哈
fun('呵呵');//你好!呵呵
默认值必须是一个存在的值,不能通过变量来代替
function fun($name=$value){
echo "你好!{$name}<br>";
}
fun();'报错'
默认值可以是常量
define('VALUE','呵呵');
function fun($name=VALUE){
echo "你好!{$name}<br>";
}
fun();//你好!呵呵
函数有多个参数的时候,没有默认值的参数要放在前面,有默认值的参数放在后面
function fun($name,$sex='男',$age='未知',$add='地址不详') {
echo "你好:{$name}<br>";
echo "性别:{$sex}<br>";
echo "年龄:{$age}<br>";
echo "地址:{$add}<hr>";
}
fun('李白'); //你好:李白 性别:男 年龄:未知 地址:地址不详
fun('杜甫','女'); //你好:杜甫 性别:女 年龄:未知 地址:地址不详
fun('白居易','男',22); //你好:白居易 性别:男 年龄:22 地址:地址不详
fun('李清照','女',23,'北京'); //你好:李清照 性别:女 年龄:23 地址:北京
形参和实参个数不一样
function fun($name1,$name2) {
var_dump($name1,$name2);
echo '<hr>';
}
fun(10); // 实参少于形参,报一个错误,继续执行
fun(10,20,30); // 实参多于形参(正常执行,取前面对应的值)
传递不确定个数的参数
- func_num_args():获取参数的个数
- func_get_args():获取传递的所有参数并转成数组
function fun() {
$n = func_num_args();
$g = func_get_args();
echo $n,'<br>'; //3
var_dump($g); //array(3) { [0]=> int(10) [1]=> int(20) [2]=> int(30) }
}
fun(10,20,30);
5.函数的返回(return语句)
return的作用:
- 立即从函数中退出
- Return返回值
示例:求两个数的最大值
function myMax($num1,$num2) {
if($num1 > $num2)
return $num1;
return $num2;
}
echo myMax(10,20); //20
a.返回函数的引用
- 定义函数时,在函数名前面加上”&”表示返回函数的引用
- 调用函数时,在函数名前面加上“&”,如果没有“&”符,保存的是返回值的值
function &fun() {
$num = 10;
return $num;
}
$result = &fun();
echo $result; //10
6.变量的作用域
- 全局变量:在函数外部的变量
- 局部变量:在函数内部的变量
- 超全局变量:在函数的内部和外部使用
在javascript中,局部变量只能在函数内部使用,全局变量在函数内部和函数外部使用
默认情况下在PHP中全局变量只能在函数外部使用,局部变量在函数内部使用
通过超全局变量实现变量在函数内部和外部访问
$_GET['num'] = 10;
function fun(){
echo $_GET['num'];
}
fun(); //10
通过$GLOBALS[]来获取全局变量的值
$num = 10;
function fun(){
$num1 = 20;
echo $GLOBALS['num']+$num1; //$GLOBALS['num'] 获取全局变量num值
}
fun(); //30
global关键字用于创建一个对全局变量的引用
$num1 = 100;
function fun(){
$num2 = 200;
global $num1; //保存全局$num1地址,等价于$num1=&$GLOBALS['num1'];
echo $num1+$num2,'<br>'; //300
unset($num1); //销毁的是全局$num1的地址,不是具体的值
echo $num1,'<br>'; //报错
}
fun();
echo $num1; //100
在函数内部声明全局变量 方法1:
function fun(){
$_GET['num']=10;
}
fun();
echo $_GET['num']; //10
方法2:推荐使用
function fun(){
$GLOBALS['num']=10;
}
fun();
echo $num; //10
方法3:
function fun(){
global $num;
$num = 10;
}
fun();
echo $num; //10
变量有作用域的概念,常量没有作用域的概念
define('PI',3.14);
function fun(){
echo PI;
}
fun(); //3.14
function fun(){
define('PI',3.14);
}
fun();
echo PI;//3.14
7.变量的生命周期
- 全局变量:声明的时候产生,页面执行完毕后销毁
- 局部变量:函数执行的时候产生,函数执行完毕销毁。
可以通过unset()手动销毁变量。
8.静态变量 static
- 静态变量放在函数内部
- 作用域不变,还是在函数的内部访问,但是生命周期变了,页面执行完毕后才销毁。
- 静态变量只能被初始化一次。
function fun(){
$num = 10;
$num++;
echo $num,'<br>';
}
fun();//11
fun();//11
function fun(){
static $num = 10;
$num++;
echo $num,'<br>';
}
fun();//11
fun();//12
++静态变量作用域没有变,只是生命周期发生了变化++
function &fun(){
static $num = 10;
$num++;
echo $num,'<br>';
return $num;
}
$str = &fun(); //1
$str = 5;
fun(); //6
9.匿名函数的use()
匿名函数的作用域和普通函数是一样的,函数内部不能访问函数外部的变量, ++匿名函数中的use()可以将匿名函数外的变量引入到匿名函数内部++
$num = 10;
$fun = function() use ($num) { //use()可以将匿名函数外的变量引入到匿名函数内部
echo $num;
};
$fun(); //10
use()引入和匿名函数所在同一作用域的变量
$num=10;
function myfun() {
$num=20;
$fun=function() use($num){
echo $num;
};
$fun(); //20
}
myfun();
a.use()的传值和传址
默认情况下,use()是传值的
传值:
$num=20;
$fun = function() use ($num){
$num++;
echo $num,'<br>';//21
};
$fun();
echo $num;//20
传址:
$num=20;
$fun = function() use (&$num){
$num++;
echo $num,'<br>';//21
};
$fun();
echo $num;//21
b.匿名函数的作用
适合建立一个临时函数,用完以后可以销毁,如果一个函数只需要执行一次就可以声明成匿名函数
如何将函数内部的匿名函数在函数外部调用
function myfun() {
$num = 20;
$GLOBALS['fun']=function() use ($num) {
$num++;
echo $num,'<br>';
};
}
myfun();
$fun(); //21 将函数保存在全局变量中可以在外部直接调用
unset($fun);//销毁函数
10.递归
语法:函数的内部自己调用自己
要素:
1、递归点:递归调用的地方
2、递归出口:递归调用结束
递归:从1加到100
function fun($num) {
if($num==1)
return 1; //递归出口
return $num+fun($num-1); //递归点
}
echo fun(100);
//分析
//fun(100)=100+fun(99);
// =100+99+fun(98);
// =100+99+98+fun(97);
// =100+99+98+97++fun(1);
// =100+99+98+97+1
//结果 5050
递归:前10个斐波那契数列
//第n个斐波那契数
function cal($n) {
if($n==1 || $n==2)
return 1;
return cal($n-1)+cal($n-2);
}
// 分析:第5个斐波那契数
// cal(5) =cal(4)+cal(3)
// =2*cal(3)+cal(2)
// =2*[cal(2)+cal(1)]+1
// =2*(1+1)+1
// =5
在递归调用的时候,有时候可能PHP执行的时间不够用,可以通过php.ini配置文件更改php最大执行时间
max_execution_time = 30;
11. 函数的代理调用
不直接通过函数名去调用函数,而是通过PHP的内置函数call_user_func_array()来调用函数
<?php
function concat() {
$array=func_get_args();
if(empty($array)){
echo '您没有传递参数<br>';
return;
}
$str='';
for($i=0,$n=count($array); $i<$n; $i++) {
$str.=$array[$i];
}
echo $str;
}
//concat(1,2,3);
if(isset($_POST['button'])) {
$str=$_POST['str'];
$array=explode(',',$str);
call_user_func_array('concat',$array); //函数的代理调用
}
?>
<form method="post" action="">
请输入字符,用逗号分隔:<input type="text" name="str">
<input type="submit" name="button" value="连接字符串">
</form>
传入参数不确定时调用
11. 练习
a.打印颜色面板
<style type="text/css">
td{
border:#000 solid 1px;
width:20px;
height:20px;
}
table{
border-collapse:collapse;
float:left;
}
</style>
<div style="width:500px; margin:auto">
<?php
$arr=array('0','3','6','9','C','F'); //组成颜色的字符
$n=count($arr); //数组的个数钱
for($r=0;$r<$n;$r++){
echo '<table>';
for($b=0;$b<$n;$b++){
echo '<tr>';
for($g=0;$g<$n;$g++){
echo '<td style="background-color:#'.$arr[$r].$arr[$g].$arr[$b].'"></td>';
}
echo '</tr>';
}
echo '</table>';
}
?>
</div>
b.打印菱形
<style type="text/css">
span{
width:5px;
margin:0px 8px;
display:inline-block;
}
div{
text-align:center;
}
</style>
<div>
<?php
$total=9; //总行数
for($i=1;$i<=$total;$i++){
$row=$i; //$row表示变化后的行的编号
if($i>$total/2)
$row=$total-$i+1;
$n=2*$row-1; //星星的个数
for($j=1;$j<=$n;$j++){
echo '<span>*</span>';
}
echo '<br>';
}
?>
</div>
c.打印0
<div>
<?php
for($i=1;$i<=10;$i++){
if($i==1 || $i==2 || $i==9 || $i==10){
for($j=1;$j<=10;$j++){
echo '<span>*</span>';
}
}else{
for($j=1;$j<=10;$j++){
if($j==1 || $j==2 ||$j==9 ||$j==10)
echo '<span>*</span>';
else
echo '<span></span>';
}
}
echo '<br>';
}
?>
</div>
d.递归法:猴子吃桃子
一个猴子守着一堆桃子,第一天吃了一半又多吃了一个,第二天一样,到第十天就剩下一个桃子,请问原来有几个桃子。
//f(n)/2-1=f(n+1)
//f(n)=(f(n+1)+1)*2;
function f($n){
if($n == 10){
return 1;
}else{
return 2*(f($n+1)+1);
}
}
echo f(1);