TECHBLOG

PHP > PHP一般

PHP の class インスタンスでメソッドチェーン

Create:

Category:PHPPHP一般

[ Version.19 ]

概要

Laravel の User モデルから status が active のデータ10件を取得する際は、下記のように記述します。

とても直感的で見やすく感動した覚えがあります。

$users = User::where('status', 'active')
	->take(10)
	->get();

この仕組みを知ると他でも利用できます。

弊社では、WordPressでカスタムフィールド(Advanced Custom Fields)の値を取得する際に使っています。下記はそのclassの一部です。

「グループフィールド「yyy」 の中のラジオフィールド「xxx」のラベルを取得」を記述しています。

$Model = new Model();
$yyy_xxx_label = $Model->acf('yyy', $post_id)->group('xxx')->radio('label')->get();

メソッドチェーンの中身

上記は、大きく分けて3つのチェーンで構成されています。ひとつ目は「->acf(‘yyy’)」。これはclassに値をセットするチェーン(セッター)。

二つ目は、処理するチェーン「->group(‘xxx’)->radio(‘label’)」。

三つめは、値を取得するチェーン「->get()」(ゲッター)。

Laravelでは、モデル(User)がセッターを兼ねてるので、少し異なりますが。

class コード

クラスで書くと下記のようになります。

class Model
{
	private $res;
	public function acf($acf_name, $post_id)
	{
		$this->res = get_field($acf_name, $post_id);
		return $this;
	}
	public function get()
	{
		return $this->res;
	}
	public function group($child_name)
	{
		$this->res = is_array($this->res) ? $this->res : [];
		if (isset($this->res[$child_key])) {
			$res = $this->res[$child_key];
		} else {
			$res = (object) $this->res;
		}
		$this->res = $res;
		return $this;
	}
	public function radio($res_type = 'both')
	{
		if ($res_type === 'both') {
			$temp = (object) [
				'value' => $this->res->value ?? $this->res['value'] ?? $this->res ?? 'error_value',
				'label' => $this->res->label ?? $this->res['label'] ?? $this->res ?? 'error_label',
			];
		} elseif ($res_type === 'value') {
			$temp = $this->res->value ?? $this->res['value'] ?? $this->res ?? 'error_value';
		} elseif ($res_type === 'label') {
			$temp = $this->res->label ?? $this->res['label'] ?? $this->res ?? 'error_label';
		} else {
			$temp = 'error_type';
		}
		$this->res = $temp;
		return $this;
	}
}

実際に使用しているコードではありませんが、メソッドチェーン説明用コードです。

ちょっと解説

class内の $this->res に値がセットされ、処理され、取得されます。各メソッドに return $this しているので、$this は、値もメソッドも保持したままです。これによりチェーンで記述できます。

サイトごとに記述する箇所には向いていないと思いますが、パッケージ化して管理する class などにはぴったりの記述です。

loading