【PHP入门】什么是PHP函数?

首先

这是PHP5高级考试/准高级考试总结的一部分,是关于PHP函数的逐步解释的文章。
考试对象是PHP5,但是内容是通用的,可以适用于PHP7左右。
虽然是初学者向的内容,但是如果对算术运算、echo和if语句等有一定理解,阅读起来会更容易。如果内容有错误,请指正。
此外,预计2021年秋季将开始进行PHP8技术认证高级考试,请通过官方网页获取最新信息。

函数的定义是

函数是一段处理逻辑的代码块,是一个完整的程序单元。
函数可以被重复利用,并且只需要给它起一个名字,下次使用时只需根据名字进行调用,因此可以用简短的描述来重复使用相同的逻辑。

如何撰写函数

在中文中,可以这样来表达:”按照 `function 名称() {}` 的格式编写,并在 `{}` 中放入处理内容。在PHP中,通常在行的结尾加上分号,但在函数的 `{}` 后面不需要分号。”

function functionName(){
    // 何らかの
    // 処理を
    // 書く
}
functionName();  // この1行だけで↑の関数(処理のまとまり)を実行できる

パラメータ(仮引数)と返り値

在函数中,接受输入的变量称为参数(形参),来自函数的输出称为返回值。
参数可以在圆括号中写入,以便在花括号中使用,如果在圆括号中不写参数并尝试使用其值,则会出现错误。
返回值通常称为返回值或返回等,可以通过指定 return $val 的方式进行,根据函数的设计可能也有没有返回值的情况。

function functionName($num){ // ←この丸カッコの中の部分がパラメータ、仮引数
    // 何らかの処理
    $val = $num + 1; // ←ここで使用している$numが、丸カッコで受けたパラメータ
    return $val; // ←この部分が返り値
}
function functionName(){ // ←丸カッコにパラメータ、仮引数が無い場合...
    // 何らかの処理
    $val = $num + 1; // ←ここの$numは「未定義の変数」を使おうとしていることになるため、
    return $val;
}
functionName(); // ←関数を呼び出した時点でエラーになる
// [エラー] Notice: Undefined variable: num in /sample/index.php on line 4

在函数内可以写多个return语句,但只有第一个到达的return语句的内容会被返回到函数的调用点。

function functionName($num){
    $val = $num + 1;
    $va2 = $num + 2;
    return $val1; // ←この時点で返り値が返されるので
    return $val2; // ←この部分の返り値は無効となる
}
function functionName($num){
    if($num === 0){
        return 0; // $numが0の時は、この時点で返り値が返される
    }
    if($num === 1){
        return 1; // $numが1の時は、この時点で返り値が返される
    }
}

如果你想在执行函数过程中停止并返回调用者的处理,你也可以使用不带返回值的return关键字。另外,可以省略函数最后的return。

function functionName($num){
    if($num === 0){
        return; // $numが0の場合、即座に関数の実行を終了する
    }
    if($num === 1){
        return 1; // $numが1の時は、この時点で返り値が返される
    }
    return; // 省略可能
}

返回值始终只能返回一个值。无法使用逗号返回多个值。

function functionName(){
    return 1, 2, 3;
}
functionName();
// [エラー] Parse error: syntax error, unexpected ',' in /sample/index.php on line 3

如果希望返回多个值,请使用数组。

function functionName(){
    return array(1, 2, 3);
}
var_dump(functionName());
// array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) }
returnについてもっと詳しく
return には、プログラムの制御を呼び出し元に戻す働きがあります。 呼び出し側のモジュールでは、呼び出しの次の式から続行します。
関数内にreturn文を書くと、即座にその関数の実行を停止し、引数を「関数の値」として返します。
ここで言う「引数」とは、return文の後ろに書く式や値のことです。return $val とした場合は $val が引数です。returnは関数ではなく「言語構造」というものに当たるので、 引数を丸カッコで囲う必要はありません。
> PHPマニュアル – return

用户定义函数和内置函数

大別すると関数には2種類あり、自分で好きなように作って利用する関数をユーザ定義関数、PHPに元々用意されている関数(自分でわざわざ作らなくても利用できる関数)を組み込み関数といいます。

调用函数

在调用函数时,需要写出函数的名称以及函数的参数的值(实际参数)。

$val = 1;
functionName($val); // 関数呼び出し時、丸カッコの中が値(実引数)となる
functionName(1); // 値は変数や、数値や文字列などでもよい

函数定义和函数调用的顺序。

另外,即使在函数定义之前进行函数调用也不会有问题。

$num1 = 5;
functionName($num1); // 10が返ってくる

function functionName($num1, $num2 = 2){
    $num = $num1 * $num2;
    return $num;
}

パラメータの数やデフォルト値の色々なパターン

関数の作りによっては、パラメータが不要な場合や、パラメータにデフォルト値が設定されていて省略可能なもの、逆にパラメータを複数指定することができるものもあります。

以下是一個沒有參數和返回值的函數的例子。輸出為100。
※請分開考慮輸出和返回值的存在與否。

function echoNum(){
    echo 100;
}

以下是一个只有一个参数且没有返回值的函数的示例。
如果变量 $count 被赋值为100,则输出为 100。

function echoNum($count){
    echo $count;
}

下面是一個有一個參數並且有返回值的函數示例。如果變量$count被賦值為100,那麼會輸出100並且回傳值1給調用該函數的地方。

function echoNum($count){
    echo $count;
    return 1;
}

↓パラメータがふたつあり、返り値がある関数の例。
変数$num1と$num2の足し算の計算結果が、関数の呼び出し元に返る。
$num1に10、$num2に20が代入されていた場合、30 の値が返ることになる。

function calcNum($num1, $num2){
    $num = $num1 + $num2;
    return $num;
}

↓パラメータがふたつあり、パラメータの2個目にだけデフォルト値が設定されていて、返り値がある関数の例。
変数$num1と$num2の掛け算の計算結果が、関数の呼び出し元に返る。
$num1に5、$num2に3が代入されていた場合、15 の値が返ることになるが、関数呼び出しの際に二つ目の引数を省略した場合は 5 * 2 で 10 の値が返る。

function calcNum($num1, $num2 = 2){
    $num = $num1 * $num2;
    return $num;
}
$num1 = 5;
$num2 = 3;
calcNum($num1, $num2); // 15が返ってくる
calcNum($num1); // 10が返ってくる

如果参数具有默认值,则可以省略实际参数的指定,但如果省略一个参数,则必须省略其后的参数。

function functionName($num1 = 1, $num2 = 2, $num3 = 3){
    return $num1 + $num2 + $num3;
}
echo functionName(2, , 10); // 途中の引数だけを省略することはできない
// [エラー] Parse error: syntax error, unexpected ',', expecting ')' in /sample/index.php on line 5
// 二つ目の引数を省略する場合 // 二つ目以降の引数をすべて省略しなければならない 
function functionName($num1 = 1, $num2 = 2, $num3 = 3){
    return $num1 + $num2 + $num3;
}
echo functionName(2);
// 一つ目の引数を省略する場合 // 一つ目以降すべてを省略しなければならない
function functionName($num1 = 1, $num2 = 2, $num3 = 3){
    return $num1 + $num2 + $num3;
}
echo functionName(); // 6

関数が求めるパラメータの数より多い実引数を与えても、多い分は無視されるだけで動作に影響ありませんが、関数が求めるパラメータより実引数が少ないとエラーになります。

function functionName($num1, $num2){
    return $num1 + $num2;
}
echo functionName(1, 3, 5); // 4 // 三つ目の引数が無視されて 1 + 3 = 4 の結果出力

実引数が少ない場合のエラーは、PHPのバージョンによって少し異なります。
PHP 5.4の場合だと、警告が出ますが処理は続行されます。

function functionName($num1, $num2){
    return $num1 + $num2;
}
echo functionName(1);
// 引数が足りないことを示す「警告」が発せられる
Warning: Missing argument 2 for functionName(), called in /sample/index.php on line 6 and defined in /sample/index.php on line 2
// この行のエラーは足りない引数である$num2を関数の中で使用しているために出ている
Notice: Undefined variable: num2 in /sample/index.php on line 3

1 // 引数を一つだけ使用して出力には成功

PHP 5.4だと警告は出ますが処理は続行されるため、引数が足りない分はその回数分エラーが発せられます。

function functionName($num1, $num2){
    return $num1 + $num2;
}
echo functionName();
Warning: Missing argument 1 for functionName(), called in /sample/index.php on line 7 and defined in /var/www/html/test/index.php on line 2

Warning: Missing argument 2 for functionName(), called in /sample/index.php on line 7 and defined in /var/www/html/test/index.php on line 2

Notice: Undefined variable: num2 in /sample/index.php on line 3

Notice: Undefined variable: num1 in /sample/index.php on line 3
0

当使用PHP 7.1或更高版本时,如果用户定义的函数传递的参数不足,将立即作为致命错误中断处理。

Fatal error: Uncaught ArgumentCountError: Too few arguments to function functionName(), 1 passed in /sample/index.php on line 6 and exactly 2 expected in /sample/index.php:2 Stack trace: #0 /sample/index.php(6): functionName(1) #1 {main} thrown in /sample/index.php on line 2

PHP手册:函数传递参数较少时的行为 – 不兼容的变更点

在之前的版本中,如果向用户定义的函数传递的参数不够,会发出警告。在PHP 7.1以上的版本中,将会抛出错误异常而不是警告。这个变更仅适用于用户定义的函数,不会对内部函数产生影响。

如果函数的参数数量未确定

当参数的数量不确定时,可以使用可变参数。
由于有处理可变参数的内置函数,所以可以同时使用它。

处理可变参数的内置函数

func_num_args() 返回给定参数的数量。
func_get_arg() 返回指定位置的参数。
func_get_args() 以数组形式返回所有给定的参数。

使用例如下所示。

function functionName(){
    $count = func_num_args();
    echo "引数の数: 全部で $count\n";
}
functionName(5, 3, 1); // 引数の数: 全部で 3 個
function functionName(){
    $arg0 = func_get_arg(0);
    echo "最初の引数:$arg0\n";
}
functionName(5, 3, 1); // 最初の引数:5
function functionName(){
    $args = func_get_args();
    $count = count($args);
    for ($i = 0; $i < $count; $i++) {
        $num = $i + 1;
        echo "{$num}個目の引数 → " . $args[$i] . "\n";
    }
}
functionName(5, 3, 1); // 1個目の引数 → 5 // 2個目の引数 → 3 // 3個目の引数 → 1

// 以下のようにしても同じ結果が得られます
function functionName2(){
    $args = func_get_args();
    foreach ($args as $key => $val) {
        $num = $key + 1;
        echo "{$num}個目の引数 → " . $val . "\n";
    }
}
functionName2(5, 3, 1); // 1個目の引数 → 5 // 2個目の引数 → 3 // 3個目の引数 → 1

函数的嵌套结构

在一个函数中可以写入更多的函数,这被称为嵌套或者嵌套调用。
为了调用内部的嵌套函数,需要通过调用包含它的外部(父级)函数,以便内部嵌套的函数被定义并调用。

function parent(){
    function child(){
        echo 'child';
    }
}

child(); // この時点では親が呼び出されていないので子も呼び出せない
parent(); // これ以降からchild()を呼び出せるようになる

函数的副作用

在函数中,如果除了计算返回值并将返回值返回给函数调用者之外还包含其他操作,那么这个函数就具有副作用。
例如,在返回返回值之前,在函数内部使用 echo 输出,或者删除文件等操作。

函数命名规则

以下是在PHP手册中所提到的内容。

有效的函数名格式首先以字符或下划线开始,然后可以跟随任意数量的字符、数字或下划线。用正则表达式表示为:^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$。

简而言之,函数的名称可以是半角字母数字、下划线,或者包括日语在内的其他字符。
第一个字符不能是数字,但是从第二个字符开始可以使用数字。
此外,由于正则表达式中有”\x7f-\xff”,所以如果字符编码是UTF-8,则可以使用平假名、片假名、汉字等字符。

然而,是否在函数名中使用日语的问题仍有争议,因此在实际开发中请遵循现场规定。例如,在系统中主要使用的代码,称为业务逻辑和产品代码的类别通常不使用日语,但有些现场在测试代码中采用日语函数名。

函数名称的大小写是不区分的。

// これらの関数は全て同じ関数名だと判断されるため、二つ目以降の関数はエラーとなる
function functionName(){
    // 何らかの処理
}
function Functionname(){
    // 何らかの処理
}
function FUNCTIONNAME(){
    // 何らかの処理
}
// [エラー] Fatal error: Cannot redeclare Functionname() (previously declared in /var/www/html/test/index.php:3) in /sample/index.php on line 7
function functionName(){
    // 何らかの処理
}

FunctionName(); // functionName() を呼び出せる
Functionname(); // functionName() を呼び出せる
FUNCTIONNAME(); // functionName() を呼び出せる

关于范围

話不是關於函數而是變數,我們稱之為作用域的範圍,該範圍指的是一個變數在代碼中的可用位置。變數的聲明位置將其分為全局作用域和函數級作用域兩種。

全球范围

グローバルスコープは、関数の外で宣言された変数のスコープです。
変数の有効範囲はスクリプト内すべての場所となり、どこからでも使えるのが基本ですが、関数内からグローバルスコープ変数を使う場合は global キーワードで変数を指定した後に使用する必要があります。

function functionName(){
    echo $val;
}
$val = 1;
functionName(); // 関数内からグローバルスコープの変数を呼べないためエラー

globalキーワードを使用しなかった場合は下記のようなエラーになります。 Undefined variable とは「変数が未定義である」というエラーの内容です。

Notice: Undefined variable: val in /sample/index.php on line 3

如果使用global关键字,在函数内使用全局变量也不会报错。

function functionName(){
    global $val; // globalキーワードで変数を指定
    echo $val;
}
$val = 1;
functionName(); // 1

函数级作用域

函数级作用域指的是在函数内声明的变量的范围。
如果试图在函数外使用在函数内声明的变量,就会产生错误。

function functionName(){
    $val = 1;
}
echo $val;
// [エラー] Notice: Undefined variable: val in /sample/index.php on line 5

你可以试着调用一次函数然后再使用变量,但仍会出现相同的错误。

function functionName(){
    $val = 1;
}
functionName();
echo $val;
// [エラー] Notice: Undefined variable: val in /sample/index.php on line 6

如果想在函数外部使用在函数内部声明的变量,则可以通过在return中返回该变量的值来实现同样的效果。

function functionName(){
    $val = 1;
    return $val;
}
$num = functionName();
echo $num; // 1

ただし、関数の呼び出しが終わると、関数の中で宣言された変数も消えてしまいますので、変数の値を保持したい時は static キーワードを使用します。

// 通常は関数呼び出しごとに内部の変数の値は消えるので
// 今回の場合だと何度呼び出しても結果は同じになる
function functionName(){
    $val = 0;
    $val = $val + 1;
    return $val;
}
echo functionName(); // 1
echo functionName(); // 1
// 変数にstaticキーワードを付けると値の保持が可能になり
// 2回目の関数呼び出し時は1回目の結果を引き継いだ状態からスタートする
function functionName(){
    static $val = 0;
    $val = $val + 1;
    return $val;
}
echo functionName(); // 1
echo functionName(); // 2

上記の例だと2回目の関数呼び出し時にも static $val = 0; で変数を初期化しているので、毎回変数が0に初期化されてしまうように見えますが、staticキーワードを使用した変数代入は1回目の関数呼び出しのときだけ行われるため、毎回初期化されるということにはならないのです。

另外,带有static关键字的变量可以用“数值、字符串等的实际值”(即字面量)或常量进行初始化,但不能使用变量等表达式进行初始化。

function functionName($num){
    static $val = $num; // 変数で初期化
    $val = $val + 1;
    return $val;
}
echo functionName(1);
// [エラー] Fatal error: Constant expression contains invalid operations in /sample/index.php on line 3

关于变量的值传递和引用传递

値渡しと参照渡しには、その変数の値のコピーを渡すか、その変数そのものを渡すか、という違いがあります。
関数のパラメータ(仮引数)でも、値渡しと参照渡しが可能です。
通常よく使用するのは値渡しの方で、これまで記載した関数の例と同様です。
こちらの値渡しの方法だと、あくまで値のコピーに対して操作をしているので、元の変数の値が変わるということはありません。

function functionName($num){
    $num++;
    echo $num;
}
$count = 0;
echo functionName($count); // 1
echo functionName($count); // 1

如果想要将参数作为引用传递,请在参数前面加上 &(安培商)符号。

function functionName(&$num){ // パラメータの頭にアンパサンドを追加
    $num++;
    echo $num;
}
$count = 0;
echo functionName($count); // 1
echo functionName($count); // 2

在使用引用传递的情况下,意味着对变量本身而不是复制品进行操作,因此在上述例子中$result的值发生了变化。

また、参照渡しは元の変数を見に行こうとするため、パラメータが参照渡しになっている関数に対し実引数では変数を与えない、ということをするとエラーになります。

function functionName(&$num){
    $num++;
    echo $num;
}
echo functionName(0); // 変数ではなく数値を実引数として与える
// [エラー] Fatal error: Only variables can be passed by reference in /sample/index.php on line 6

即使是通过引用传递的情况下,也可以在函数参数中指定默认值。

function functionName(&$num = 0){
    $num++;
    echo $num;
}
echo functionName(); // 1

返回值的引用

通常情况下,函数返回值会以值的副本的形式返回,但如果将函数名定义为 &函数名 并进行调用,则返回值将以引用的方式返回。

// 参照で値を返す時は関数名の先頭に&を付ける
function &functionName(&$a){
    return $a;
}
$num = 2;
$val = &functionName($num); // 引数の参照渡しは関数定義時のみでよい
$num = 5;
echo $val; // 5 // 返り値を参照にしているので、現在の$numの値が返されている

关于可变函数。

可变函数是将函数名称赋值给变量的一种方式,非常方便在需要条件分支调用函数时使用。只要在变量后面加上括号,就可以调用自定义函数和内置函数。

function test(){
    echo 'test関数です';
}
$name = 'test';
$name(); // test関数です
$name = 'count';
$arr = array(1, 2, 3);
echo $name($arr); // 3
function morning(){
    echo 'おはよう';
}
function afternoon(){
    echo 'こんにちは';
}
function night(){
    echo 'こんばんは';
}
$time = 10;
if($time > 6 && $time < 12){
    $functionName = 'morning';
} elseif($time >= 12 && $time < 18) {
    $functionName = 'afternoon';
} else {
    $functionName = 'night';
}
$functionName(); // おはよう

为了避免可变函数若没有指定的函数名将会出现错误,可以使用function_exists()在事前检查该函数是否存在。

如果指定的函数已经定义,返回 true

function morning(){
    echo 'おはよう';
}
function night(){
    echo 'こんばんは';
}

$res = function_exists('night');
var_dump($res); // bool(true)

$res = function_exists('afternoon');
var_dump($res); // bool(false)

由于`isset`、`echo`和`print`等不是函数而是语言结构,因此无法通过可变函数进行调用。在PHP手册页面中提到的所有内容都是类似的。

PHP手册-关键词列表

关于匿名函数

创建临时函数时,可以使用内置函数create_function()来创建匿名函数。临时用途例如在创建函数(回调函数)以用作函数参数时。匿名函数的函数名是自动分配的随机名称,因此不需要考虑函数名的繁琐工作。
在create_function()的第一个参数中,您可以指定要传递给创建的匿名函数的参数,而在第二个参数中,您可以以包括分号在内的形式描述处理的内容。

PHP手册: create_function — 创建匿名函数 (lambda表达式)

$fc = create_function('$val','echo $val;');
$fc('hello'); // hello
var_dump($fc); // string(9) "lambda_1" // lambda_1 という名前が自動で振られている

$fc = create_function('$val','echo $val;');
$fc('bye'); // bye
var_dump($fc); // string(9) "lambda_2" // lambda_2 という名前が自動で振られている

ただし、この create_function() を用いた匿名関数の作成は、処理内容を第二引数に文字列で記載する必要があり可読性・保守性が良いとは言えず、PHP 7.2.0 で非推奨となり、PHP 8.0.0 では削除されました。
この問題を解決するため、PHP 5.3からはラムダ関数・無名関数が導入されています。
「関数名を付ける必要がない」「関数の引数として用いるための関数(コールバック関数)を作成するのに便利」という基本的な位置付けは匿名関数と同様です。

PHP手册-匿名函数(闭包)

有一些內建函數可以將回調函數作為參數傳遞,例如array_map()、array_filter()、array_walk()和usort()。

PHP手册:array_map — 将回调函数应用于指定数组的元素
PHP手册:array_filter — 使用回调函数对数组元素进行过滤
PHP手册:array_walk — 将用户定义的函数应用于数组的所有元素
PHP手册:usort — 使用用户定义的比较函数按数组值进行排序

使用用户定义函数、匿名函数和无名函数(lambda函数和闭包)来示例利用回调函数作为参数的情况如下所示。

function square($num)
{
    return $num * $num;
}
$arr = array(1, 2, 3);
$res = array_map('square', $arr);
print_r($res); // Array ( [0] => 1 [1] => 4 [2] => 9 )
$func = create_function('$num','return $num * $num;');
$arr = array(1, 2, 3);
$res = array_map($func, $arr);
print_r($res); // Array ( [0] => 1 [1] => 4 [2] => 9 )

当将匿名函数赋值给变量时,必须在函数的最后添加分号。

$func = function($num) {
    return $num * $num;
}; // ←セミコロンが必要。ないとエラーになる。
$arr = array(1, 2, 3);
$res = array_map($func, $arr);
print_r($res); // Array ( [0] => 1 [1] => 4 [2] => 9 )

在处理PHP代码时输出HTML等内容的小技巧

如果在PHP代码中出现了PHP的结束标签?>和开始标签和开始标签 组合被视为一个PHP代码块,第二对 组合又被视为另一个PHP代码块,因此在这两个PHP代码块之间,插入了不是PHP代码的纯文本(这些文本成为函数的内容),这样写可能更容易理解。

关于PHP的编码规范

考虑到考试的内容并不相关,以下完全是离题的内容。如果一个文件只包含PHP代码,最近的编码惯例是省略PHP代码的结束标记”?>”。这是因为在PHP结束标记后面有多余的空格等内容时,程序可能会出现意外的行为。

关于这种编码规范,不同的公司和组织可能规定了各种内容,但其中主要的是由名为PHP-FIG(Framework Interoperability Group)的团体制定的被推荐的标准规范『PSR(PHP Standards Recommendations)』,建议您阅读一下。

以下是英语原版:
PSR-2:编码风格指南

提供日本語翻译的页面
PSR-2编码指南(日本语)

由于PSR-2建立在PSR-1的基础上,所以想要了解PSR-1的人可以点击这里。
PSR-1:基本编码规范。

请参阅网址。

PHP手册 – return
PHP手册 – 用户定义函数
【PHP技术者】函数命名规则,适当的输出字符转义函数,过滤函数的行为等
PHP – 使用\x7f-xff字符的函数或类名示例
PHP(编程语言)- 维基百科
关于不要在PHP的结尾标签 ?> 来讲个故事
PHP中使用lambda表达式编写函数的方法【初学者向】

广告
将在 10 秒后关闭
bannerAds