【PHP】関数から複数の値を返す方法 | 配列・list()・分割代入・名前付き引数で返す全パターン解説

PHP PHP
主にPHPに関する記事

PHPでは、関数から複数の値を返すことが求められるシチュエーションが多くあります。この記事では、基本的な方法から応用までを解説し、それぞれのメリットとデメリットを確認していきます。

分割代入(PHP 7.1以降・推奨)

PHP 7.1以降では list() の代わりに短い構文で書けます。

// インデックス配列の分割代入
function getCoordinates(): array {
return [35.6895, 139.6917];
}
[$lat, $lng] = getCoordinates();

// 連想配列の分割代入(PHP 7.1以降)
function getUser(): array {
return ['name' => '千原', 'age' => 50];
}
['name' => $name, 'age' => $age] = getUser();

現在の実務ではこの書き方が主流です。
list() は古いコードベースで見かける程度になっています。

配列を使って複数の値を返す

PHPでは、配列を使用して複数の値を返すことが一般的です。

配列を使う方法のメリットは、シンプルで理解しやすい点です。ただし、配列の要素数が多くなるとコードの可読性が低下する可能性があります。

こちらはPHPの公式の例2にも記載されています。

function small_numbers() {
    return [0, 1, 2];
}

// 配列を展開させると、配列のそれぞれのメンバが個別に得られます。PHP 7.1.0以降
[$zero, $one, $two] = small_numbers();

// PHP 7.1.0 より前のバージョンではlistを使うしかありません
list($zero, $one, $two) = small_numbers();
PHP

連想配列を使う方法

複数の値に名前を付けて管理したい場合には、連想配列を使うと良いです。

連想配列は、各要素に名前を付けることで、可読性を向上させることができます。一方、配列の使い方に慣れていない場合は、コードがやや複雑に感じられることもあります。

値が文字列の場合はcompact()extract()を使って、少し簡潔に書くこともできるかと思います。

function small_numbers()
{
    return ['zero' => 0, 'one' => 1, 'two' => 2];
}

$small_numbers = small_numbers();
$zero = $small_numbers['zero'];
$one = $small_numbers['one'];
$two = $small_numbers['two'];
PHP

インスタンスを使う方法

オブジェクト指向のPHPでは、クラスのインスタンスを使って複数の値を返すことができます。
これは、データとその操作を1つの単位にまとめる際に便利です。

クラスを使うことで、より高度なデータ管理が可能になりますが、シンプルな値の返却にはオーバーヘッドが大きくなる場合があります。

class SmallNumbers()
{
    public $zero;
    public $one;
    public $two;
}

function small_numbers()
{
    $out = new SmallNumbers();
    $out->zero = 0;
    $out->one = 1;
    $out->two = 2;
    return $out;
}

$small_numbers = small_numbers();
$zero = $small_numbers->zero;
$one = $small_numbers->one;
$two = $small_numbers->two;
PHP

どの方法を使うべきか

実務での判断基準をまとめます。

状況推奨方法
シンプルな値を2〜3個返す分割代入(配列)
キー名で管理したい連想配列 + 分割代入
データと操作をセットにしたいクラスのインスタンス
古いPHP(7.1未満)のコードlist()

複数の値を返す場合は連想配列 + 分割代入の組み合わせが最も読みやすく、現代のLaravelプロジェクトでも自然に使える書き方です

まとめ

そもそも複数の戻り値が返るような設計は間違っていると思うのですが、やむをえない場合は上記から色々試してみてください。

上記の他にもyieldを使ったり参照渡しを使ったりするなど、いくつか方法があるのですが、難しかったり、見通しが悪くなったりするので、割愛しています。

必要になった際に、色々な実装方法があるとだけ覚えていれば、実装時やレビュー時に役に立つと思います。

著者

Webエンジニア歴30年、フリーランスバックエンドエンジニア。

PHP歴約30年(Laravel 7年・FuelPHP 5年・CakePHP・自作FW)、
JavaScript歴約20年(React・Vue各4年)。
AWS(EC2 / CloudFront / RDS / API Gateway など)・
GCP(BigQuery)を使ったバックエンド開発を中心に、
複数の事業会社・受託案件でシステム設計から実装・運用まで担当しています。

PHPがバージョン4の時代から書いており、
Laravelが普及する前のフレームワーク乱立期も経験しています。
「昔はこう書いていたが今はこう」という変遷を肌で知っているエンジニアとして、
単なるコマンドの使い方だけでなく、なぜそうするのかの背景まで伝えることを意識して書いています。

このブログでは、実務で実際に詰まった箇所・調べたこと・気づいたことを
そのまま記事にしています。誰かの「詰まり」が解決するきっかけになれば幸いです。

千原 耕司をフォローする

役にたったと思ったら応援をお願いします m(._.)m

PHP
スポンサーリンク
シェアする
千原 耕司をフォローする
タイトルとURLをコピーしました