PHP
機能プログラミング
サーチ…
前書き
PHPの関数型プログラミングは関数に依存します。 PHPの関数は、一連のアクションを実行するための、組織化された再利用可能なコードを提供します。関数はコーディングプロセスを簡素化し、冗長ロジックを防止し、コードを簡単にフォローします。このトピックでは、PHPの関数、引数、パラメータ、return文およびスコープの宣言と使用について説明します。
変数への代入
匿名関数は、コールバックが必要なパラメータとして変数に代入することができます。
$uppercase = function($data) {
return strtoupper($data);
};
$mixedCase = ["Hello", "World"];
$uppercased = array_map($uppercase, $mixedCase);
print_r($uppercased);
これらの変数は、スタンドアロンの関数呼び出しとしても使用できます。
echo $uppercase("Hello world!"); // HELLO WORLD!
外部変数の使用
use
構文は、変数を匿名関数のスコープにインポートするために使用されます。
$divisor = 2332;
$myfunction = function($number) use ($divisor) {
return $number / $divisor;
};
echo $myfunction(81620); //Outputs 35
変数は参照によってインポートすることもできます。
$collection = [];
$additem = function($item) use (&$collection) {
$collection[] = $item;
};
$additem(1);
$additem(2);
//$collection is now [1,2]
コールバック関数をパラメータとして渡す
call_user_func()
、 usort()
、 array_map()
など、ユーザ定義のコールバック関数をパラメータとして受け入れるいくつかのPHP関数があります。
ユーザー定義のコールバック関数がどこに定義されているかによって、それらを渡すさまざまな方法があります。
手続きスタイル:
function square($number)
{
return $number * $number;
}
$initial_array = [1, 2, 3, 4, 5];
$final_array = array_map('square', $initial_array);
var_dump($final_array); // prints the new array with 1, 4, 9, 16, 25
オブジェクト指向スタイル:
class SquareHolder
{
function square($number)
{
return $number * $number;
}
}
$squaredHolder = new SquareHolder();
$initial_array = [1, 2, 3, 4, 5];
$final_array = array_map([$squaredHolder, 'square'], $initial_array);
var_dump($final_array); // prints the new array with 1, 4, 9, 16, 25
静的メソッドを使用したオブジェクト指向スタイル:
class StaticSquareHolder
{
public static function square($number)
{
return $number * $number;
}
}
$initial_array = [1, 2, 3, 4, 5];
$final_array = array_map(['StaticSquareHolder', 'square'], $initial_array);
// or:
$final_array = array_map('StaticSquareHolder::square', $initial_array); // for PHP >= 5.2.3
var_dump($final_array); // prints the new array with 1, 4, 9, 16, 25
組み込み関数をコールバックとして使用する
引数としてcallable
関数では、PHPの組み込み関数で文字列を入力することもできます。配列のすべての文字列から先頭と末尾の空白を削除するには、 array_map
パラメータとしてtrim
を使用するのが一般的です。
$arr = [' one ', 'two ', ' three'];
var_dump(array_map('trim', $arr));
// array(3) {
// [0] =>
// string(3) "one"
// [1] =>
// string(3) "two"
// [2] =>
// string(5) "three"
// }
匿名関数
匿名関数は名前を持たないだけの機能です。
// Anonymous function
function() {
return "Hello World!";
};
PHPでは、無名関数は式のように扱われます。このため、セミコロンで終わらなければなりません;
。
無名関数は変数に代入する必要があります。
// Anonymous function assigned to a variable
$sayHello = function($name) {
return "Hello $name!";
};
print $sayHello('John'); // Hello John
または、別の関数のパラメーターとして渡す必要があります。
$users = [
['name' => 'Alice', 'age' => 20],
['name' => 'Bobby', 'age' => 22],
['name' => 'Carol', 'age' => 17]
];
// Map function applying anonymous function
$userName = array_map(function($user) {
return $user['name'];
}, $users);
print_r($usersName); // ['Alice', 'Bobby', 'Carol']
あるいは、別の関数から返ってきたことさえあります。
自己実行する匿名機能:
// For PHP 7.x
(function () {
echo "Hello world!";
})();
// For PHP 5.x
call_user_func(function () {
echo "Hello world!";
});
自己実行型の匿名関数に引数を渡す:
// For PHP 7.x
(function ($name) {
echo "Hello $name!";
})('John');
// For PHP 5.x
call_user_func(function ($name) {
echo "Hello $name!";
}, 'John');
範囲
PHPでは、無名関数は他のPHP関数と同じように独自のスコープを持ちます。
JavaScriptでは、無名関数は外部スコープの変数にアクセスできます。しかし、PHPでは、これは許可されていません。
$name = 'John';
// Anonymous function trying access outside scope
$sayHello = function() {
return "Hello $name!";
}
print $sayHello('John'); // Hello !
// With notices active, there is also an Undefined variable $name notice
閉鎖
クロージャーは、外部のスコープにアクセスできない無名関数です。
匿名関数をそのように定義すると、その関数の "名前空間"が作成されます。現在のところ、その名前空間にのみアクセスできます。
$externalVariable = "Hello";
$secondExternalVariable = "Foo";
$myFunction = function() {
var_dump($externalVariable, $secondExternalVariable); // returns two error notice, since the variables aren´t defined
}
外部変数にはアクセスできません。外部変数にアクセスするためにこの名前空間にこの権限を与えるには、それをクロージャ( use()
)で導入する必要があります。
$myFunction = function() use($externalVariable, $secondExternalVariable) {
var_dump($externalVariable, $secondExternalVariable); // Hello Foo
}
これは、PHPのタイトな変数スコープに大きく起因しています。変数がスコープ内で定義されていない場合、またはglobal
インポートされていない場合は存在しません。
また注意してください:
親スコープから変数を継承することは、グローバル変数を使用することと同じではありません。グローバル変数はグローバルスコープ内に存在します。グローバルスコープは、どの関数が実行されていても同じです。
クロージャの親スコープは、クロージャが宣言された関数です(必ずしも呼び出された関数である必要はありません)。
PHPでは、クロージャーは早期バインディングアプローチを使用します。これは、closureが定義されたときに、 use
キーワードをuse
してクロージャの名前空間に渡される変数が同じ値を持つことを意味します。
この振る舞いを変更するには、変数を参照で渡す必要があります。
$rate = .05;
// Exports variable to closure's scope
$calculateTax = function ($value) use ($rate) {
return $value * $rate;
};
$rate = .1;
print $calculateTax(100); // 5
$rate = .05;
// Exports variable to closure's scope
$calculateTax = function ($value) use (&$rate) { // notice the & before $rate
return $value * $rate;
};
$rate = .1;
print $calculateTax(100); // 10
クロージャの有無にかかわらず無名関数を定義するときには、デフォルトの引数は暗黙のうちに必要とされません。
$message = 'Im yelling at you';
$yell = function() use($message) {
echo strtoupper($message);
};
$yell(); // returns: IM YELLING AT YOU
純粋な関数
純粋な関数は、同じ入力を与えられた場合、常に同じ出力を返し、 副作用がない関数です。
// This is a pure function
function add($a, $b) {
return $a + $b;
}
いくつかの副作用は、ファイルシステムの変更、 データベースとのやりとり 、画面への印刷です。
// This is an impure function
function add($a, $b) {
echo "Adding...";
return $a + $b;
}
関数としてのオブジェクト
class SomeClass {
public function __invoke($param1, $param2) {
// put your code here
}
}
$instance = new SomeClass();
$instance('First', 'Second'); // call the __invoke() method
__invoke
メソッドを持つオブジェクトは、ほかの関数とまったく同じように使用できます。
__invoke
メソッドは、オブジェクトのすべてのプロパティにアクセスでき、任意のメソッドを呼び出すことができます。
PHPの一般的な関数メソッド
マッピング
配列のすべての要素に関数を適用する:
array_map('strtoupper', $array);
これがコールバックが最初に来るリストの唯一のメソッドであることに注意してください。
縮小(または折り畳み)
配列を単一の値に減らす:
$sum = array_reduce($numbers, function ($carry, $number) {
return $carry + $number;
});
フィルタリング
コールバックがtrue
返す配列項目のみを返しtrue
。
$onlyEven = array_filter($numbers, function ($number) {
return ($number % 2) === 0;
});