8. PHP 函数

PHP 使用 function 关键字定义函数,此外还支持可变函数、引用函数和匿名函数等。

用户自定义函数

定义

一个函数可由以下的语法来定义:

<?php
function foo($arg1, ..., $argn)
{
    //do something
    return $retval;
}
命名规范

函数名和 PHP 中的其它标识符命名规则相同。有效的函数名以字母或下划线打头,后面跟字母,数字或下划线。

函数调用前必须先定义
<?php

function actionA()
{
    echo "A";
}

actionA();//可以调用
actionB();//无法调用

function actionB()
{
    echo "B";
}
函数中调用函数
<?php

function actionA()
{
  function actionB()
  {
      echo "B";
  }
}

actionB();//无法调用
actionA();//定义函数 actionB()
actionB();//可以调用

PHP 不支持函数重载,也不可能取消定义或者重定义已声明的函数。

<?php

function sayHi()
{
    echo 'Hi';
}
function sayHi()
{
    echo 'Hello';
}
sayHi();//报错,不能重定义函数 sayHi()

函数名是大小写无关的,不过在调用函数的时候,通常使用其在定义时相同的形式。

递归函数

递归函数的本质是函数调用函数本身,但是要避免递归函数/方法,调用超过 100-200 层,因为可能会使堆栈崩溃从而使当前脚本终止。 无限递归可视为编程错误。

函数的参数

通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表。
PHP 支持按值传递参数(默认),通过引用传递参数以及默认参数。也支持可变数量的参数;

通过引用传递参数

缺省情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。 如果想要函数的一个参数总是通过引用传递,可以在函数定义中该参数的前面预先加上符号 &

<?php
function actionB(&$string)
{
    $string .= 'and something extra.';
}
$str = 'This is a string, ';
actionB($str);
echo $str;    // outputs 'This is a string, and something extra.'
?>
默认参数的值

函数可以定义 C++ 风格的标量参数默认值,如下:

<?php
function makecoffee($type = "cappuccino")
{
    return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?> 

返回值

值通过使用可选的返回语句返回。可以返回包括数组和对象的任意类型。返回语句会立即中止函数的运行,并且将控制权交回调用该函数的代码行。

return
<?php
function square($num)
{
    return $num * $num;
}
echo square(4);   // outputs '16'.

函数不能返回多个值,但可以通过返回一个数组来得到类似的效果。

返回一个数组以得到多个返回值
<?php
function small_numbers()
{
    return array (0, 1, 2);
}
list ($zero, $one, $two) = small_numbers();

从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用操作符 &

从函数返回一个引用
<?php
function &returns_reference()
{
    return $someref;
}

$newref =& returns_reference();
?> 
返回值类型声明

PHP 7 增加了对返回类型声明的支持。 类似于参数类型声明,返回类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同。

<?php

function arraysSum(array $arrays): array
{
    return array_map(function(array $array): int {
        return array_sum($array);
    }, $arrays);
}

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));

以上例程会输出:

Array
(
    [0] => 6
    [1] => 15
    [2] => 24
)

可变函数

PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。

变量函数不能用于语言结构,例如 echo, print, unset(), isset(), empty(), include, require 以及类似的语句。需要使用自己的包装函数来将这些结构用作变量函数。

<?php

class Test
{
    public static $actionB = "property B";

    public function actionA()
    {
        echo "method A";
    }
    public static function actionB()
    {
        echo "method B";
    }
}

function sayHi() {
    echo "Hi".PHP_EOL;
}

function sayHello($word = '') {
    echo "Hello $word";
}


$func = 'sayHi';
$func();

$func = 'sayHello';
$func('World');

$func = 'actionA';
(new Test())->$func();

echo Test::$actionB;
$actionB = 'actionB';
Test::$actionB();

从结果可以看出

  • 可以用可变函数的语法来调用一个对象方法和静态方法。

内部函数

也称为内置函数,PHP 有很多标准的函数和结构。还有一些函数需要和特定地 PHP 扩展模块一起编译,否则在使用它们的时候就会得到一个致命的未定义函数错误。

例如,要使用 image 函数中的 imagecreatetruecolor(),需要在编译 PHP 的时候加上 GD 的支持。或者,要使用 mysql_connect() 函数,就需要在编译 PHP 的时候加上 MySQL 支持。

调用 phpinfo() 或者 get_loaded_extensions() 可以得知 PHP 加载了那些扩展库。同时还应该注意,很多扩展库默认就是有效的。PHP 手册按照不同的扩展库组织了它们的文档。

Note: 如果传递给函数的参数类型与实际的类型不一致,例如将一个 array 传递给一个 string 类型的变量,那么函数的返回值是不确定的。在这种情况下,通常函数会返回 NULL。但这仅仅是一个惯例,并不一定如此。

参见 function_exists(),函数参考,get_extension_funcs() 和 dl()。

匿名函数

匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。

匿名函数目前是通过 Closure 类来实现的。

<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
    return strtoupper($match[1]);
}, 'hello-world');
// 输出 helloWorld

闭包函数也可以作为变量的值来使用。PHP 会自动把此种表达式转换成内置类 Closure 的对象实例。把一个 closure 对象赋值给一个变量的方式与普通变量赋值的语法是一样的,最后也要加上分号:

匿名函数变量赋值
<?php
$greet = function($name)
{
    printf("Hello %s<br/>", $name);
};

$greet('World');
$greet('PHP');
从父作用域继承变量

闭包可以从父作用域中继承变量。 任何此类变量都应该用 use 语言结构传递进去。 PHP 7.1 起,不能传入此类变量: superglobals、 $this 或者和参数重名。

<?php
$msg = 'hello';

$a = function () {
    var_dump($msg);
};
$a();

$b = function () use ($msg) {
    var_dump($msg);
};
$b();

$msg = 'hi';
$b();

$c = function () use (&$msg) {
    var_dump($msg);
};
$c();

$d = function ($arg) use ($msg) {
    var_dump($arg . ' ' . $msg);
};
$d("hello");

从结果可以看出

  • 使用 use 可以从父作用域继承变量
  • 匿名函数是在定义的时候继承父作用域变量,而不是在调用的时候继承
  • 变量使用引用赋值,则原变量发生改变,则引用该变量的变量也会发生变化
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 1. 定义 函数是一个被命名的,独立的代码段,它执行特定的任务,并可能给调用它的程序一份返回值。 PHP的模块化程...
    楠哥哥_0b86阅读 619评论 1 2
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,114评论 0 13
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,727评论 0 38
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,364评论 0 5
  • 展信好, 郁可,山里落雪的时候,我就很少进山了,往常扰人的林鸟和山物都不见了踪影,大概和我一样寻着角落窝起来,...
    何宿阅读 186评论 0 0