[PHP] コールバック関数について

PHPのコールバック関数とは、呼び出し先関数の中でさらに呼び出される関数のことを言います。コールバック=「後で呼び出される」という意味があります。

ここではコールバック関数の基本的な使い方、無名関数を使った呼び出し、コールバック関数を使ったいくつかの例についてまとめていきます。

コールバック関数

実装例

コールバック関数はcallable型で定義され、呼び出された関数内で実行(コールバック)されます。

以下の例は一番簡単な例です。test_callback関数の引数にコールバックさせたい関数名を指定して、test_callback内でコールバックしています。

コード

function test_function() {
    print __FUNCTION__ . "\n";
}

function test_callback(callable $function) {
    $function();
}

test_callback("test_function");    

実行結果

$ php test_callback.php
test_function

無名関数で指定する実装例

callable型は以下のように無名関数で指定することも可能です。

コード

function test_callback(callable $function) {
    $function();
}

test_callback(function() {
    print __FUNCTION__ . "\n";
});

実行結果

無名関数で指定した場合、関数名が無いので __FUNCTION__ は以下のように出力されます。

$ php test_callback.php
{closure}

array_map関数

配列の全要素に対して処理を行う

array_map関数は配列の全要素に対して処理を行うための関数です。従来配列の全要素に対して処理を行う場合、for文やforeach文を使用して記述していましたが、これが簡潔に記述できるようになります。

なお、array_map関数は引数に指定した配列を直接変更するのではなく、処理した結果の配列を返します。

コード

以下のコードでは、配列 $array には連想配列のリストを保持しており、array_map関数でこの連想配列のname属性を大文字に変換したものを保存しています。

$array = [
    ["key" => 1, "name" => "Apple"],
    ["key" => 2, "name" => "Lemon"],
    ["key" => 3, "name" => "Strawberry"],
];

print_r($array);

$array_upper = array_map(function($value) {
    $value['name'] = strtoupper($value['name']);
    return $value;
}, $array);

print_r($array_upper);

実行結果

$ php test_callback.php
Array
(
    [0] => Array
        (
            [key] => 1
            [name] => Apple
        )
    [1] => Array
        (
            [key] => 2
            [name] => Lemon
        )
    [2] => Array
        (
            [key] => 3
            [name] => Strawberry
        )
)
Array
(
    [0] => Array
        (
            [key] => 1
            [name] => APPLE
        )
    [1] => Array
        (
            [key] => 2
            [name] => LEMON
        )
    [2] => Array
        (
            [key] => 3
            [name] => STRAWBERRY
        )
)

配列の全要素に対して、もう一方の配列を使って処理を行う

array_map関数は第三引数以降にさらに配列を受け取ることが出来ます。第三引数以降に渡された配列は、callable型のfunctionの引数で受け取ることが出来ます。

つまり複数の配列に対して順に、対応した要素をもって処理することが出来ます。

コード

以下のコードでは、配列$array に対して 配列$prices から対応した値を1.1倍して、price要素として追加しています。

$array = [
    ["key" => 1, "name" => "Apple"],
    ["key" => 2, "name" => "Lemon"],
    ["key" => 3, "name" => "Strawberry"],
];

$prices = [100, 150, 200];

print_r($array);

$array_upper = array_map(function($value, $price) {
    $value['price'] = (int) ($price * 1.10);
    return $value;
}, $array, $prices);

print_r($array_upper);

実行結果

$ php test_callback.php
Array
(
    [0] => Array
        (
            [key] => 1
            [name] => Apple
        )
    [1] => Array
        (
            [key] => 2
            [name] => Lemon
        )
    [2] => Array
        (
            [key] => 3
            [name] => Strawberry
        )
)
Array
(
    [0] => Array
        (
            [key] => 1
            [name] => Apple
            [price] => 110
        )
    [1] => Array
        (
            [key] => 2
            [name] => Lemon
            [price] => 165
        )
    [2] => Array
        (
            [key] => 3
            [name] => Strawberry
            [price] => 220
        )
)

usort関数

オブジェクトに対して特定のルールで並べ替えを行う

usort関数を使うと、オブジェクトに対して特定のルールで並べ替えを行います。

第一引数で並べ替えの比較のためのルールをcallable型の引数で指定し、第二引数で並べ替える配列を指定します。

なお、usort関数は第二引数で指定された配列を直接変更します。

コード

以下の例ではPerson型のオブジェクトに対して、age属性の昇順で並べ替えを行っています。

なお、比較演算子の <=> は、宇宙船演算子と言って、左辺が小さければ-1、左辺が大きければ1、同じであれば0を返します。

class Person {
    private int $id;
    private string $name;
    private int $age;

    public function __construct(int $id, string $name, int $age) {
        $this->id = $id;
        $this->name = $name;
        $this->age = $age;
    }

    public function getId() : int {
        return $this->id;
    }

    public function getName() : string {
        return $this->name;
    }

    public function getAge() : int {
        return $this->age;
    }
}

$persons = [
    new Person(1, 'Test Name 1', 30),
    new Person(2, 'Test Name 2', 20),
    new Person(3, 'Test Name 3', 25),
];

usort($persons, function(Person $p1, Person $p2) {
    return $p1->getAge() <=> $p2->getAge();
});

print_r($persons);

実行結果

実行結果を確認すると、age属性の昇順でソートされていることが確認できます。

$ php test_callback.php
Array
(
    [0] => Person Object
        (
            [id:Person:private] => 2
            [name:Person:private] => Test Name 2
            [age:Person:private] => 20
        )
    [1] => Person Object
        (
            [id:Person:private] => 3
            [name:Person:private] => Test Name 3
            [age:Person:private] => 25
        )
    [2] => Person Object
        (
            [id:Person:private] => 1
            [name:Person:private] => Test Name 1
            [age:Person:private] => 30
        )
)

アロー関数

上記コードのusort関数の呼び出しは、アロー関数によって以下のように置き換えることが可能です。

usort($persons, fn(Person $p1, Person $p2) => $p1->getAge() <=> $p2->getAge());

実行結果は同じです。

コメント

このブログの人気の投稿

docker-compose up で proxyconnect tcp: dial tcp: lookup proxy.example.com: no such host

docker-compose で起動したweb、MySQLに接続できない事象

【PHP】PHP_CodeSnifferを使う(コーディングルールのカスタマイズ)