ユーザー定義関数

引数の規定値

仮引数に規定値を設定できる

function getArea(float $base = 5, float $height = 1):float {
	return $base * $height / 2;
}

$area = getArea();//省略可能

規定値を持つ引数省略可能。 ただし省略した引数より後の引数は全て省略しなければならない。

function func($x, $y = 2, $z = 3) {
	echo $x, $y, $z;
}

func(1,,3); //Parse Error この呼び出しはエラー

PHP 8.1.0 以降では、 new ClassName() 記法を使ってオブジェクトも指定できます。

function makecoffee($coffeeMaker = new DefaultCoffeeMaker){...}

echo makecoffee(new FancyCoffeeMaker);

引数/戻り値の型宣言

function getArea(float $base = 5, float $height = 1):float {
	return $base * $height / 2;
}
型宣言で使用できる型(「*」は戻り値のみで使用可能)
型名概要
bool真偽値
float浮動小数点数
int整数
string文字列
array配列
iterable配列/Traversal型(= foreace 命令で利用できる型)
callableコールバック関数
object任意のオブジェクト
クラス/インターフェイス名指定されたクラス/インターフェイス
mixed任意の型 (php8.0)
self現在のクラス(メソッドでのみ利用可能)
*voidなにも返さない
*static最初に呼び出したクラス(遅延静的束縛 php8.0)

null許容型

型名の先頭に?をつける。
呼び出し元(実引数)で省略は不可

function myFunc(?int $value):void {
	var_dump($value);
}

myFunc(300);  //int(300)
myFunc(null); //NULL
myFunc();     //エラー

Union型

8.0以降

/function getArea(string|float $base, strign|float $height):float|false
{ ... }

false 擬似型

8.0以降

function getArea(string|float $base, strign|float $height):float|false
{ ... }

引数の参照渡し

仮引数の頭に&を付ける。

function increment(int &$num): int {
	$num++;
	return $num;
}

$value = 10;
print increment($value); //結果 11
print $value;            //結果 11

ただし、参照渡しされた引数を関数の中でunsetしても元の変数には影響しません。この場合、あくまでも引数そのものが破棄されるだけです。

参考記事

リファレンス

ジェネレーター

yieldという命令を利用することで、つど、その時々の値を返す。
returnも利用可能、最終的な結果を表す getReturn() メソッドを利用する。

function myLang() {
	yield 'あいうえお';
	yield 'かきくけこ';
	yield 'さしすせそ';

	return 'end';
}

$lang = myLang();
foreach($lang as $value) {
	print $value . '
'; } // 結果:あいうえお
かきくけこ
さしすせそ
print $lang->getReturn(); // 結果:end

foreach 文で処理する。
ジェネレーター関数の戻り値は、yield命令によって返された値そのものではなく、Generatorオブジェクトです。明示的に型宣言するなら、下記のようになる。

function myLang(): Generator { ~ }

ジェネレーターの中で別のジェネレーターに処理を委譲する。
yield from otherFunctoin();

return 戻り値

return 以降の命令は実行されない。
戻り値がない(return がない)、または空の return; は、null を返したとみなされる
ただし、戻り値の型宣言にvoidを指定している場合に、return null; とするのは不可。

静的変数 static命令

関数内のローカル変数を維持する。
初回呼び出し時にのみ初期化され、関数の処理が終了しても維持される。
static 変数はリテラルか定数で初期化
式で初期化できない。
static $x = 0: OK
static $x = $y NG

function checkStatic(): int {
	static $x = 0;
	return ++$x;
}

print checkStatic(); //結果:1
print checkStatic(); //結果:2

unsetの挙動に注意!
static命令の後にunsetしても静的変数の使用を解除し、ローカル変数を使用するという意味になる。静的変数$xに影響しない。

function checkStatic(): void {
	static $x = 0;
	print "unset前:{$x}";
	unset($x);
	$x = 10;
	print "unset後:{$x}";
}

checkStatic(); //unset前:1 unset後:10
checkStatic(); //unset前:2 unset後:10

global変数の場合も同様

$x = 10;

function checkScope(): int {
	global $x;
	unset($x);
	return ++$x;
}

print checkScope(); //1
print $x; //10

//global変数を破棄する場合
//unset($GLOBAL['X']);

名前付き引数

getArea( 仮引数名: 値 );

可変長引数

function total(float ...$args): float {
	$result = 0;
	foreach( $args as $arg ) {
		$result += $arg;
	}
	return $result;
}

print total(7, 3, 10); //20
print total(11, -5, 4, 88); //98

可変長引数は、より正しくは「0個以上の引数」。引数なしで total(); の呼び出しでも良い。
確実に一つ以上の引数を要求したい場合、1個目の引数を通常の引数として宣言する。

function total(float $init, float ...$args): float {
	$result = $init;
	foreach( $args as $arg ) {
		$result += $arg;
	}
	return $result;
}

「…」演算子による引数のアンパック
配列をアンパック(展開)して個々の値として渡すことができる。

function getArea(float $base, float $height): float {
	return $base * $height / 2;
}

print getArea(...[10, 5]);
// getArea(10, 5) と同義

//php 7.4以降、配列内でもアンパックできる
$data = ['山田', '田中'];
$member = ['太田', '若林', ...$data, '春日'];
print_r($member);

//結果:Array( [0] => 太田 [1] => 若林 [2] => 山田 [3] => 田中 [4] =>  春日)

可変変数

制御構造と言語構造では可変変数の形では使えない。
スーパーグローバルは可変変数として使用できない

キーワードはいずれも定数、クラス名、 関数名として使用することはできない。
キーワードのリスト(PHP マニュアル)

//include echo などは使えない
$func = 'include';
$func("example.php");

配列で使用する場合は曖昧さを解決する必要がある。
$$a[1] → $a[1] なのか、$$aまでの変数に添字[1]なのか、パーサが知る必要がある。
明示的に記述する → ${$a[1]}  ${$a}[1]

クラスのプロパティに、可変プロパティ名でアクセスできる。
可変プロパティ名の解決は呼び出し元のスコープで行われる。

$start = 'b';
$end = 'ar';
echo $foo->{$start . $end} . "\n";
// $foo->bar; と同義

可変関数(Variable Functions)

「$変数名()」の形式で呼び出せる関数。

function getArea(float $base, float $height): float {
	return $base * $heihgt / 2;
}

$name = 'getArea';
$area = $name(8, 10);
print "三角形の面積は{$area}です。";

高階関数

関数そのものを引数として渡したり、戻り値として返したりする。
条件に応じてコールバックを差し替えるなど。処理する関数を外から渡す。

function myArrayWalk(array $array, callable $func) : void {
  foreach ($array as $key => $value) {
    $func($value, $key);
  }
}
function showItem(mixed $value, int | string $key) :void {
  print "{$key}:{$value}
"; } $data = ['杉山', '長田', '杉沼', '和田', '土井']; myArrayWalk($data, 'showItem'); /* 結果: 0:杉山
1:長田
2:杉沼
3:和田
4:土井
*/

無名関数(クロージャー)

呼び出しコードに直接埋め込むことができる。

function( 仮引数, ・・・・) {
	// 任意の処理
	return 戻り値;
}

変数に代入することもできる。この場合、ブロックの末尾にセミコロン(;)が必要。{ ~ } はブロックの終わりではなく、いわゆる関数リテラルの一部であるから。

$triangle = function($base, $height) { ~ };

親スコープの変数を引き継ぐ場合は、use命令を使用する。既定は値渡しである点に注意。元の変数に変更を加えたい場合は参照渡しにする。

function myArrayWalk(array $array, callable $func) : void {
  foreach($array as $key => $value) {
    $func($value, $key);
  }
}

$data = [100, 50, 10, 5];
$result = 0;
myArrayWalk($data, function($value, $key) use(&$result) { //参照渡し
  $result += $value;
});

print "合計値:{$result}"; //結果:合計値:165

アロー関数

PHP 7.4 で追加されました。
アロー関数は 無名関数 と同じ機能をサポートしていますが、 親のスコープで使える変数が常に自動で使える点だけが異なります。(use を使わずに親スコープの変数が使える
アロー関数の記述より前に変数をセットしておく必要がある。値渡しのため外部変数を変更することは出来ない
最後にセミコロンが必要。
単一の式しか書けない。

$y = 1;
 
$fn1 = fn($x) => $x + $y;

// 無名関数で $y を値渡しするのと同じ
$fn2 = function ($x) use ($y) {
    return $x + $y;
};

var_export($fn1(3));  // 結果:4
var_export($fn2(3));  // 結果:4
echo $y;   // 結果:1