【PHP】PHP組み込み関数をメソッドチェーンで連続して呼び出す簡易なクラスの書き方

  • 2022年5月10日
  • PHP

 メソッドチェーンはメソッドをつなげて記述する書き方のことです。よく JavaScript で見る書き方であり、次の様に一時変数を用意せずにコードを書けます。

// メソッドチェーンなし
const ho = "hoge".slice(0,2);
const HO = ho.toUpperCase();
const result = HO.padStart(4,"0")
console.log(result); // 00HO

// メソッドチェーンあり
const result = "hoge".slice(0,2)
  .toUpperCase()
  .padStart(4,"0");
console.log(result); // 00HO

 これが PHP 組み込み関数でもできる書き方を紹介します。普通の PHP の書き方をあえて壊すような方法なため実際に使うことはそうそうありませんが、メソッドチェーンの影響の方が PHP の慣例より強い時もあるのでそういった時に使うやもしれません。またそういう書き方がされているコードを読む時、あらかじめ知っていると楽できます。この書き方は次の様にできます。

<?php
class Str {
    /** PHPの組み込み関数の第一引数に使う値をプロパティとしてセット */
    public function __construct(
        public string $str
    ){}

    /**
     * このクラスで外部に公開していない名前のメソッドが呼ばれた場合に動作するマジックメソッド
     * @see https://www.php.net/manual/ja/language.oop5.overloading.php#object.call
     */
    public function __call($name, $arguments)
    {
        // 呼ばれたメソッド名の関数を第一引数を最初に与えたプロパティ、
        // 第二引数以降を呼ばれた際の引数として実行
        $result = $name($this->str, ...$arguments);
        // 関数の返り値が文字列ならば返り値を元に自身のインスタンスを生成して返却
        // 関数の返り値が文字列でないならば返り値をそのまま返却
        return is_string($result) ? new self($result) : $result;
    }
}
$s = new Str('hoge');
echo $s->substr(0, 2)
    ->strtoupper()
    ->str_pad(4, '0', STR_PAD_LEFT)
    ->str;
    // 00HO

Online PHP editor | output for ejrVt#上記コードのデモ

 第一引数をプロパティにし、各関数をマジックメソッドの __call で呼び出して実行することによって例の様にできます。これによって PHP 組み込み関数をメソッドの実装として呼び出せ、メソッドチェーンが組めます。
 この簡易なクラスのままでは制約があり、改善の必要があります。上記コードでは第一引数をプロパティの値に固定して関数を呼ぶ都合上、第二引数以降にプロパティの値を渡したい時、都度その関数をクラス内に増やす必要があります。例えばexplode関数の場合は次です。

<?php
class Str {
    /** PHPの組み込み関数の第一引数に使う値をプロパティとしてセット */
    public function __construct(
        public string $str
    ){}

    /**
     * このクラスで外部に公開していない名前のメソッドが呼ばれた場合に動作するマジックメソッド
     * @see https://www.php.net/manual/ja/language.oop5.overloading.php#object.call
     */
    public function __call($name, $arguments)
    {
        // 呼ばれたメソッド名の関数を第一引数を最初に与えたプロパティ、
        // 第二引数以降を呼ばれた際の引数として実行
        $result = $name($this->str, ...$arguments);
        // 関数の返り値が文字列ならば返り値を元に自身のインスタンスを生成して返却
        // 関数の返り値が文字列でないならば返り値をそのまま返却
        return is_string($result) ? new self($result) : $result;
    }

    /** __call に処理を渡さず、第二引数にプロパティの値を渡して explode 関数を実行するメソッドを用意する */
    public function explode(string $separator, ?int $limit = PHP_INT_MAX)
    {
        return explode($separator, $this->str, $limit);
    }
}
$s = new Str('hoge');
$res = $s->substr(0, 2)
    ->strtoupper()
    ->str_pad(4, '0', STR_PAD_LEFT)
    ->explode('H');
var_dump($res);
/*
array(2) {
  [0]=>
  string(2) "00"
  [1]=>
  string(1) "O"
}
*/

Online PHP editor | output for 17rYQ#上記コードのデモ

 こんな感じで PHP の組み込み関数でもメソッドチェーンができます。より実用的にするならば PHP のドキュメントに対応した ide_helper 的なコメントが欲しくなります。
 
 

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG