Laravelを学習していると、こんなコードをよく見かけます。
Route::get('/mypage', function () {
return 'マイページ';
});
最初に見たとき、
functionはあるけど、関数名がないのはなぜ?
となりました。
今回は、この 無名関数(Closure) について整理します。
無名関数とは
普通の関数には名前があります。
function sayHello()
{
return 'こんにちは';
}
呼び出すときは、
sayHello();
一方で、無名関数は名前がありません。
function () {
return 'こんにちは';
}
その名の通り、
名前のない関数 = 無名関数です。
PHPでは、このような無名関数は Closure(クロージャ)
といいます。
Laravelではどこで使われる?
LaravelのRouteでよく登場します。
Route::get('/hello', function () {
return 'こんにちは';
});
見やすくすると、
Route::get(
'/hello',
function () {
return 'こんにちは';
}
);
Laravelに、
GET /hello にアクセスされたら、この処理を実行してね
と関数そのものを渡しているイメージです。
ゲームで考えると
普通の関数は、
名前付きの技です。
function slash()
{
return 'アバンストラッシュ';
}
slash();
「アバンストラッシュ」という名前を指定して使えます。
無名関数は、名前を付けていない技
のようなもので、
$skill = function () {
return '謎の攻撃!';
};
変数に入れれば、
$skill();
で実行できます。
無名関数(Closure)の重要ポイント
無名関数には、外側にある変数を持ち込めます。
そのときに使うのが、
useです。
例えば、
$enemy = 'ドラゴン';
$attack = function () use ($enemy) {
return $enemy . 'を攻撃!';
};
実行
echo $attack();
結果は、
ドラゴンを攻撃!
になります。
なぜuseが必要なの?
無名関数の { } の中は、基本的に外側とは別の範囲です。
そのため、
$enemy = 'ドラゴン';
$attack = function () {
return $enemy . 'を攻撃!';
};
と書いても、外側の $enemy をそのまま使うことはできません。
そこで、use ($enemy)と書くことによって使うことができます。
$attack = function () use ($enemy) {
return $enemy . 'を攻撃!';
};
意味としては、
外側にある $enemy を、この関数の中にも持ってきて
という感じです。
functionの引数とuseは何が違う?
$enemy = 'ドラゴン';
$attack = function ($weapon) use ($enemy) {
return $weapon . 'で' . $enemy . 'を攻撃!';
};
実行
echo $attack('剣');
結果
剣でドラゴンを攻撃!
このコードでは、
function ($weapon)と、use ($enemy)
では、値の入ってくるタイミングが違います。
$weapon
function ($weapon)
これは、関数を実行するときにもらう値です。
$attack('剣');
この '剣' が $weapon に入ります。
$enemy
use ($enemy)
これは、関数の外側から持ち込む値です。
$enemy = 'ドラゴン';
という情報を、無名関数の中でも使えるようにしています。
ゲームっぽくすると、
$weapon
→ 技を使う瞬間にもらう武器
$enemy
→ 技を作るときに覚えておく敵
となります。
function ($weapon) use ($enemy)
武器は発動するときにもらう
敵の情報は事前に持っておくというイメージです。
Laravelでもuseはよく登場する
例えばEloquentの whereHas。
$status = 'published';
$users = User::whereHas('posts', function ($query) use ($status) {
$query->where('status', $status);
})->get();
それぞれ、
$query
→ Laravel側から渡される
$status
→ 外側から自分で持ち込む
という違いがあります。
これを理解すると、LaravelのClosureがかなり読みやすくなりました。
普通の関数と無名関数、どっちを使う?
用途によって使い分けます。
普通の関数・メソッド
何度も使う処理や、名前を付けた方が分かりやすい処理に向いています。
function attack()
{
return '攻撃!';
}
無名関数・Closure
その場所でだけ使う短い処理に向いています。
Route::get('/hello', function () {
return 'こんにちは';
});
LaravelのRouteのように、
この場でこの処理だけ実行したい
という場合に便利です。
まとめ
短くてその場だけ使う
→ Closure
何度も使う
→ 普通の関数・メソッド
Routeの処理が大きくなる
→ Controllerへ分ける