🐕

LaravelのEloquentで複数項目の条件指定のスマートな実装

2024/01/13に公開

悪い例

LaravelのEloquentで複数の項目に基づく条件指定を行うには、以下のように実装できます。

// 条件に一致する求人情報を取得
function get(array $criteria)
{
	$query = table::query();
	
	// salaryがmin_salary以上のレコードを取得
	if (isset($criteria['min_salary'])) {
		$query->where('salary', '>=', $criteria['min_salary']);
	}

	// prefが一致するレコードを取得
	if (isset($criteria['pref'])) {
		$query->where('pref', $criteria['pref']);
	}

	// cityが一致するレコードを取得
	if (isset($criteria['city'])) {
		$query->where('city', $criteria['city']);
	}

	return $qurey->get();
}

しかし、この実装では新しいクエリ項目を追加するごとにwhereを追加しなければならず、可読性と拡張性の両方の観点でよろしく無いです。

良い例

代わりに、連想配列とforeachを活用して以下のように実装できます。

function get(array $criteria)
{
	$query = table::query();

	$conditions = [
		'min_salary' => 'salary >= ?',
		'pref' => 'pref = ?',
		'city' => 'city = ?',
	];

	foreach ($criteria as $key => $value) {
		if (array_key_exists($key, $conditions) && isset($value)) {
			$query->whereRaw($conditions[$key], [$value]);
		}
	}

	return $qurey->get();
}

この実装であれば、新たなクエリ項目を追加する場合は$conditionsに条件式を記述するだけで済むので拡張性がありますし、$conditionsを見れば大体クエリの内容が分かるので可読性もあります。

また、配列形式のクエリ項目を追加したい場合(例えば、複数の都道府県、市区町村指定に対応したい場合など)は、以下のように実装できます。

function get(array $criteria)
{
	$query = table::query();

	$arrayConditions = [
		'pref' => 'pref',
		'city' => 'city',
	];

	foreach ($arrayConditions as $criteriaKey => $field) {
		if (isset($criteria[$criteriaKey]) && is_array($criteria[$criteriaKey])) {
			$query->whereIn($field, $criteria[$criteriaKey]);
		}
	}

	return $qurey->get();
}

このように、連想配列とforeachを活用すれば大体のケースで複数条件指定のEloquentをスッキリと書くことが出来ます。

Discussion