ORM

ORMとは

ORM(オブジェクトリレーショナルマッパー)は、ソフトウェア開発において、データベースとオブジェクト指向プログラミングの間でデータを効果的にマッピングするための設計パターンです。

オブジェクトとテーブルのマッピング

ORMはデータベーステーブルとプログラム内のEntity(エンティティ)の間で、フィールド(プロパティ)の対応関係を定義します。

CRUD操作

CRUDにより、データ作成、読み込み、更新、削除などのデータ操作がオブジェクト指向プログラムで簡単に実行できます。

クエリ言語の抽象化

ORMは、プログラミングでSQLなどのクエリを書かずにデータ操作できます。また異なるテーブル間のリレーションシップに対応し、関連データを取得できます。

SQLとORMの比較

SQLの場合

DB操作するにはSQLが必要です。以下は「users」テーブルのデータを取得するSQLです。

SELECT * FROM users;

このSQLを実行するには、DB接続プログラミングを作成しなければいけません。

$db_connection = 'mysql';
$db_name = 'my_shop';
$db_host = 'localhost';
$db_user = 'root';
$db_password = '';

$dsn = "{$db_connection}:dbname={$db_name};host={$db_host}";
try {
    $pdo = new PDO($dsn, $db_user, $db_password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch (PDOException $e) {
    echo "接続失敗: " . $e->getMessage();
    exit;
}

$sql = 'SELECT * FROM users;';
$stmt = $pdo->query($sql);
$users = $pdo->fetchAll(PDO::FETCH_ASSOC);

ORMの場合

データベース接続やSQL実行などをORMに委任することで、プログラムのソースコードが削減できます。

Eloquent
$users = User::all();

QueryBuilder

QueryBuilderとは

QueryBuilder(クエリビルダー)は、SQL文を直接記述するのではなく、直感的なメソッドチェーンを使ってデータベース操作するライブラリです。直接SQLを実行することも可能で、比較的高速に処理できるのがメリットです。

PDOベース

QueryBuilderはPHPのDBライブラリにPDO( PHP Data Objects)ベースで設計されているため、面倒なDBまわりの処理を隠蔽しながらプログラミングできます。SQLインジェクションに対応しているため、アプリのフォームから悪意のあるリクエストを送信しても、クエリの誤動作を防ぎます。

DBファサード

DBファサードはデータベース操作するための抽象化レイヤーです。DBファサードを使用することで、CRUD処理をはじめとするDBクエリ操作を、Staticな構文で実行できます。

DBファサードの利用

QueryBuilderを利用するには、DBファサードIlluminate\Support\Facades\DB で読み込みます。

use Illuminate\Support\Facades\DB;

DBファサードの種類

DBファサードのはSQLライクな構文です。

$users = DB::table('users')->get(); // usersテーブルからデータを取得

$newUser = DB::table('users')->insert([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'password' => bcrypt('secret'),
]); // 新しいユーザーを挿入

$updatedUser = DB::table('users')
    ->where('id', 1)
    ->update(['name' => 'Jane Doe']); // IDが1のユーザーの名前を更新

$deletedUser = DB::table('users')
    ->where('id', 1)
    ->delete(); // IDが1のユーザーを削除

table()

table() はDBテーブルを指定して、オブジェクトを取得します。

DB::table(テーブル名);

get()

get() はテーブルのレコードをすべて取得します。

// SELECT * FROM items;
DB::table('items')->get();

count()

count() はレコード件数を取得します。

// SELECT count(*) FROM items;
$count = DB::table('items')->count();

max(), min()

max(), min() は指定したカラムの最大値、最小値を取得します。

//  SELECT max(price) FROM items;
$max_price = DB::table('items')->max('price');

//  SELECT min(price) FROM items;
$min_price = DB::table('items')->min('price');

Eloquent

Eloquentとは

Eloquent(エロクエント)は、Laravelで最も簡単なORMライブラリで、QueryBuilderをベースに拡張したライブラリです。artisasnコマンドでモデル作成すれば、Eloquentをすぐ利用できるように設計されています。

  • Eloquent:DB操作が高機能で簡単だが、自由度が低い
  • QueryBuilder:DB操作が比較的高速で、自由度が高い

Eloquentの基本

モデルファイルは「Model」クラスを継承しており、Eloquentを簡単に利用できます。クラスにプロパティやメソッドを追加して、より柔軟なDB操作ができます。

App/Models/Item.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    use HasFactory;
}

テーブル名

もう一度、現在のテーブルを確認しておきます。

itemsテーブル

項目 カラム名 データ型 NOT NULL オプション
ID id bigint unsigned Yes Primary Key, auto_increment
商品名 name varchar(255) Yes
値段 price int Yes
作成日 created_at timestamp Yes
更新日 updated_at timestamp Yes

テーブル名自動認識

Eloquentでは、パスカルケースのクラス名に対して、スネークケース複数形のテーブル名として自動認識するようになっています。

  • クラス名:パスカルケース「Item」
  • テーブル名:スネークケースの複数形「items」

テーブル名の任意指定

テーブル名を任意で指定したいときは、クラスプロパティ「$table」にテーブル名を指定します。

protected $table = "テーブル名";

fillableとguarded

fillable

fillableは、明示的にデータを代入するためのテーブルカラムの配列で、ホワイトリスト化ともいいます。例えば「name」「price」のデータをユーザが任意に代入するときに設定します。

protected $fillable = [
    'name',
    'price',
];
  • テーブルカラムの配列
  • ホワイトリスト化

guarded

guardedfillableとは逆にデータを代入させないブラックリストのテーブルカラムです。例えば「id」「created_at」「updated_at」などのデータは、フレームワークのプログラムやSQLで自動更新させず、ユーザに設定はさせません。

protected $guarded = [
    'id',
    'created_at',
    'updated_at',
];
  • テーブルカラムの配列
  • ブラックリスト化

レコード挿入

Eloquentのメソッド

Eloquentの機能は、インスタンス経由やモデルクラス経由(Facade)で実行できます。

インスタンス経由

$model = new Model();
$model->method();

モデルクラス経由(Facade)

Model::method();

実行されるSQL

Eloquentを利用すると、SQLを直接コーディングしなくても実行できます。

Eloquent
$posts = ['name' => 'Alice', 'age' => 20];
User::create($posts);
$user = User::find(1);
SQL
INSERT INTO users (name, age) VALUES('Alice', 20);
SELECT * FROM users WHERE id = 1;
  • create()
  • save()

save()

save() はモデルインスタンスを生成して、fill() でデータを代入してDB保存します。

$posts = ['name' => 'Alice', 'age' => 20];
$user = new User();
$user->fill($posts);
$user->save();

create()

create() はモデルクラスのStaticメソッドでDB保存します。データは連想配列を代入します。

$posts = ['name' => 'Alice', 'age' => 20];
User::create($posts);

商品データ追加

モデル利用

「ItemController」で「Item」モデルをuseします。

ItemController.php
use App\Models\Item;

「use Item」と入力して、コードアシスタント機能を使うと便利です。

レコード追加

ItemControllerstore() に「items」テーブルのレコード追加処理を実装します。

ItemController.php
    public function store(Request $request)
    {
        $posts = $request->all();
        Item::create($posts);
        return redirect()->route('item.index');
    }

レコード取得

get()

get() はすべてのレコードを取得するメソッドです。

Item::get();

「items」レコード取得

ItemControllerの*index()* で「items」テーブルのレコードをすべて取得します。取得したデータは、dd() でデバッグします。

ItemController.php
    public function index()
    {
        $items = Item::get();
        dd($items);
        return view('item.index');
    }

ブラウザで確認すると、「items::array」で「items」データが確認できます。

結果

データ取得

「items」テーブルからレコードを取得し、データをViewに受け渡します。

ItemController.php
    public function index()
    {
        $items = Item::get();
        $data = ['items' => $items];
        return view('item.index', $data);
    }

foreachディレクティブ

Bladeでは、データの繰り返しは foreachディレクティブで記述できます。

@foreach (配列 as 変数)
処理
@endforeach

foreachディレクティブで、データはモデルクラスのオブジェクトとしてアクセスします。

@foreach ($items as $item)
$item->id
$item->name
$item->price
@endforeach

商品一覧表示

foreachディレクティブで商品一覧表示します。

item/index.blade.php
@extends('layouts.app')

@section('content')
<h2>商品</h2>
<div>
    <a href="{{ route('item.create') }}">新規追加</a>
</div>
<div>
    <table class="table">
    <tr>
        <th></th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
    @foreach ($items as $item)
    <tr>
        <td><a href="{{ route('item.edit', $item->id) }}">編集</a></td>
        <td>{{ $item->name }}</td>
        <td>{{ $item->price }}</td>
    </tr>
    @endforeach
    </table>
</div>
@endsection

「item/」にアクセスして、「Item」モデルのデータが一覧表示できるか確認してみましょう。

動作確認

Laravel超入門