前回でアプリ用のDBの作成が終わりました。
DB用の接続情報を設定してからModelとマイグレーションファイルを作ってみます。
DB接続情報の記述
.envファイルの11 - 16行目がDB接続情報の記述欄です。
デフォルトでMySQLになっているので、DB名、ユーザ名、パスワードだけを修正すれば良いです。
.envファイルのDB接続情報 |
Modelの作成
フレームワークの中で直接SQL文を書くものもありますが、大体のフレームワークではテーブルを隠蔽してオブジェクトとしてプログラムから操作できる場合が多いですね。
ただテーブル間のリレーションがシンプルなら良いのですが、以前のプロジェクトでサブクエリとか使いまくって酷く歪なテーブルリレーションのプロジェクトに当たったことがあります。
思わず「テーブルの正規化とかスタースキーマとか勉強して出直して来い」って言いたくなるほどでした。そういうプロジェクトには適用しずらいでしょうね。
閑話休題
Laravelには2種類のデータベースにアプローチする方法があるようです。
DBクラス(クエリビルダ)
DBクラスを使う方法
ただ、この機能はControllerの中で呼び出すみたいですね。
Controllerの中でDBクラスを呼び出して必要なデータを取得してから、Viewに渡して結果を表示する感じです。
use Illuminate\Support\Facades\DB;の機能です。
SQL文をそのまま書きます。
一般形は
$items = DB::命令文の種類('実際のSQL文', パラメータ);
実際のSQLの中に":キー"という書式を埋め込むことができます。
これはSQL文中にある:idのように、あとからそこに値を割り当てるものでプレースホルダといいます。
後からくる値(パラメータで渡す)のために場所を取っておく感じです。
単なる値でも複数の値を配列で渡すこともできます。
例:
クエリビルダを使う方法
実際のSQLの中に":キー"という書式を埋め込むことができます。
これはSQL文中にある:idのように、あとからそこに値を割り当てるものでプレースホルダといいます。
後からくる値(パラメータで渡す)のために場所を取っておく感じです。
単なる値でも複数の値を配列で渡すこともできます。
例:
- DB::select('select * from テーブル名 where id = :id', $id);
- DB::insert('insert into テーブル名 (id, name) values (:column1,:column2)', $param);
- DB::update('update テーブル名 set column1 = :column1, column2 = :column2' where id = :id, $param);
- DB::delete('delete * from テーブル名 where id = :id', $id);
クエリビルダを使う方法
この機能もControllerの中で呼び出すみたいですね。
Controllerの中でクエリビルダを呼び出して必要なデータを取得してから、Viewに渡して結果を表示する感じです。
上記のDBクラスは直接SQL文が書けるので、SQL文が分かっている人にとっては便利でしょうね。
SQLクライアントを使ってSQL文を実行して想定した結果が得られることを確認してからソースコードにコピペして変数の部分だけパラメータ渡しにすれば良いです。
私的にはこれで全然問題ないのですが、
SQLクライアントを使ってSQL文を実行して想定した結果が得られることを確認してからソースコードにコピペして変数の部分だけパラメータ渡しにすれば良いです。
私的にはこれで全然問題ないのですが、
- SQL文にパラメータの値を組み込んで最終的なSQL文を生成するので正しいSQL文が実行されているか分かりずらい。
- 渡す値によっては予想外のSQL文が実行される危険がある。
- PHPでプログラムを書いているのにDBアクセスのところだけ別の言語で書かないといけないのはストレスになる。
DBクラスと違って直接SQL文を書くことはなく、必要なメソッドを呼び出してパラメータを渡すことでSQL文を生成してくれます。
なので最終的なSQL文は表面上には現れません。
use Illuminate\Support\Facades\DB;を使います。
DB::table(テーブル名)
でビルダ(\Illuminate\Database\Query\Builder)を取得します。
ビルダはSQLクエリ文を生成するための機能を提供します。
例:
- DB::table(テーブル名)->get();
- DB::table(テーブル名)->insert($param);
- DB::table(テーブル名)->where('id', $id)->update($param);
- DB::table(テーブル名)->where('id', $id)->delete();
対象のテーブルのビルダを取得して用意されてるメソッドを使って操作するのでSQL文の書き間違いは無くなるでしょうね。
ただクエリビルダで複数テーブルをジョインするような場合はどうするんだろう?
Eloquent(ORM)
EloquentはORM(Object-Relational Mapping)で「エロクアント」と読みます。
DBのテーブルやレコードをオブジェクトとして扱える仕組みです。
DBのテーブルやレコードをオブジェクトとして扱える仕組みです。
Eloquentを使用する場合、各データベーステーブルに対応する「モデル」があり、そのテーブル操作に使用します。Eloquentモデルは、データベーステーブルからレコードを取得するだけでなく、テーブルへのレコード挿入、更新、削除も可能です。
ようやくModelが出てきました。
モデルは通常app\Models
ディレクトリにあり、Illuminate\Database\Eloquent\Model
クラスを拡張します。make:model
Artisanコマンドを使用して、新しいモデルを生成します。
$php artisan make:model モデル名
でモデルを生成できます。
1点注意が必要です。 モデル名はテーブル名に合わせる必要があります。
例:
モデル名 | テーブル名 |
---|---|
Flight | flights |
AirTrafficController | air_traffic_controllers |
公式に以下の説明があります。
クラス名の複数形をスネークケースにしたものが自動的にテーブル名と見なされます。
これに適合しない場合はモデルのtableプロパティに設定します。
テーブル名
上記の例をちょっと見て、どのデータベーステーブルがFlightモデルに対応するかをEloquentに知らせていないことにお気づきかもしれません。別の名前を明示的に指定しない限り、クラスの複数形の「スネークケース」をテーブル名として使用します。したがって、この場合、EloquentはFlightモデルがflightsテーブルにレコードを格納し、AirTrafficControllerモデルはair_traffic_controllersテーブルにレコードを格納すると想定できます。
モデルの対応するデータベーステーブルがこの規約に適合しない場合は、モデルにtableプロパティを定義してモデルのテーブル名を自分で指定できます。
以下の気になる記述が公式にありました。
はっきり言って嫌いですね。 下手なテーブル定義の温床です。
きっちりテーブル設計すれば、”id”なんていう主キーを定義する必要はないはずです。
これについてはアンチパターンとして議論がされているようです。
主キー
Eloquentは、各モデルの対応するデータベーステーブルにidという名前の主キーカラムがあることも想定しています。必要に応じて、モデルのprotected $primaryKeyプロパティを定義して、主キーとして機能する別のカラムを指定できます。
主キーについては、さらに下記の記述があります。
これは問題ないですね。PostgreSQLなどだと主キーにシリアルを設定して複数ユーザが同時にレコード挿入しても自動的にバッティングしない値になることが保証されています。
設計の都合上、非数値にしたい場合でも設定が可能です。
さらに、Eloquentは、主キーが増分整数値であることも想定しています。これは、Eloquentが主キーを自動的に整数にキャストすることを意味します。非インクリメントまたは非数値の主キーを使用する場合は、モデルにpublicのこの記事では、モデルの作成、マイグレーションファイル作成、シードの作成まで行こうと思っていましたが長くなってきたので次の記事で書くことにます。$incrementing
プロパティを定義し、false
をセットする必要があります。
0 件のコメント:
コメントを投稿