Laravel Eloquent で SELECT 処理を共通化する方法

# Laravel Eloquent で SELECT 処理を共通化する方法

## **はじめに**

Laravel の Eloquent を使ってデータを取得する際、 `where` 句を使ったクエリを何度も書くことが多いです。たとえば、以下のようなコードを頻繁に書くことになります。

```php
$customers = Customer::where('status', 'active')
    ->where('age', '>=', 30)
    ->get();
```

これを **共通メソッド** にまとめることで、可読性や保守性を向上させる方法を紹介します。

---

## **設計の方針**

共通の `selectCustomers()` メソッドを作成し、

- **さまざまな検索条件**（`equal`、`not_equal`、`in` など）を指定可能
- **取得方法をオプションで指定**（`first()`、`get()`、`paginate()` など）
- **条件を増やしてもコードの可読性を保つ**

ようにします。

---

## **キー名の設計**

検索条件を配列のキーとして統一し、以下のように指定できるようにします。

| キー名 | SQL演算子 | 例 |
|--------|----------|----|
| `equal` | `=` | `'equal' => ['status' => 'active']` |
| `not_equal` | `!=` | `'not_equal' => ['status' => 'inactive']` |
| `in` | `IN` | `'in' => ['id' => [1, 2, 3]]` |
| `not_in` | `NOT IN` | `'not_in' => ['id' => [4, 5, 6]]` |
| `greater` | `>` | `'greater' => ['age' => 18]` |
| `greater_or_equal` | `>=` | `'greater_or_equal' => ['age' => 20]` |
| `less` | `<` | `'less' => ['age' => 60]` |
| `less_or_equal` | `<=` | `'less_or_equal' => ['age' => 65]` |
| `like` | `LIKE` | `'like' => ['name' => '%田%']` |
| `between` | `BETWEEN` | `'between' => ['price' => [100, 500]]` |
| `is_null` | `IS NULL` | `'is_null' => ['deleted_at']` |

---

## **共通メソッドの実装**

```php
use App\Models\Customer;

function selectCustomers(array $conditions = [], array $options = [])
{
    $query = Customer::query();

    if (!empty($conditions['equal'])) {
        foreach ($conditions['equal'] as $column => $value) {
            $query->where($column, $value);
        }
    }

    if (!empty($conditions['not_equal'])) {
        foreach ($conditions['not_equal'] as $column => $value) {
            $query->where($column, '!=', $value);
        }
    }

    if (!empty($conditions['in'])) {
        foreach ($conditions['in'] as $column => $values) {
            $query->whereIn($column, $values);
        }
    }

    if (!empty($conditions['greater'])) {
        foreach ($conditions['greater'] as $column => $value) {
            $query->where($column, '>', $value);
        }
    }

    if (!empty($conditions['like'])) {
        foreach ($conditions['like'] as $column => $value) {
            $query->where($column, 'LIKE', $value);
        }
    }

    if (!empty($conditions['is_null'])) {
        foreach ($conditions['is_null'] as $column) {
            $query->whereNull($column);
        }
    }

    // オプション処理
    if (!empty($options['orderBy'])) {
        $query->orderBy($options['orderBy'], $options['direction'] ?? 'asc');
    }

    if (!empty($options['first'])) {
        return $query->first();
    } elseif (!empty($options['paginate'])) {
        return $query->paginate($options['paginate']);
    } elseif (!empty($options['limit'])) {
        return $query->limit($options['limit'])->get();
    }

    return $query->get();
}
```

---

## **使用例**

### **1. `status` が `active` かつ `age` が 30 以上のデータを取得**
```php
$customers = selectCustomers([
    'equal' => ['status' => 'active'],
    'greater_or_equal' => ['age' => 30]
]);
```

### **2. `id` が `1, 2, 3` に含まれるが、`deleted_at` が `NULL` のデータを取得**
```php
$customers = selectCustomers([
    'in' => ['id' => [1, 2, 3]],
    'is_null' => ['deleted_at']
]);
```

### **3. 名前に「田」が含まれるデータを `10件` 取得**
```php
$customers = selectCustomers([
    'like' => ['name' => '%田%']
], ['limit' => 10]);
```

---

## **まとめ**

このように、 `selectCustomers()` を作成することで、

✅ **共通化により、コードの重複を削減**  
✅ **柔軟な検索条件を指定可能**  
✅ **拡張しやすい設計**  

というメリットがあります。Eloquent の活用をよりスムーズにするため、ぜひ参考にしてください！