Laravel第3段です。
今回はデータベース周りを学んだので、その復習(アウトプット)をしたいと思います。参考にしたサイトは以下。
Laravelを使って何かアプリケーションを作るとき、必ず必要となるのがデータベースとデータベースに格納するデータです。
Laravelは簡単にPHPとデータベースの連携、データの操作、テストデータの作成ができるので、今回はその辺りを復習したいと思います。
PHPとデータベースの連携
データベースに格納しているデータに対して操作を行うとき、データベースに接続してSQLを使います。しかし、LaravelはPHPなので、PHPからデータベースへ接続、SQLを使う必要があります。
さらに、データベースには様々な種類があり、接続方法も種類によって異なります。
これらを自身で実装するのは、とても大変なのでLaravelにはORM(Object Relational Mapping)が搭載されています。
Eloquent ORM(Eloquent Object Relational Mapping)
Laravelに搭載しているORMの名称です。
ORMとは、名前の通り、オブジェクト指向プログラムとリレーショナルデータベースをマッピングしてくれる機能です。LaravelはORMのEloquentと呼ばれるものを使っています。これを使うことでPHPからデータベースへの接続、データの操作を簡単に行うことができます。
Active Recode
Active Recodeという言葉を目にすることがあります。
これはテーブルとクラスを一対一で結び付けて、CRUD(Create、Read、Update、Deleteのこと)操作をクラスでやりましょうというデザインパターンの1つです。Eloquentはこのデザインパターンにそって実装されています。
余談ですが、RubyのRailsもActive Recodeのデザインパターンを採用したActive Recodeという名のORMがあり(LaravelでいうEloquentに代わるもの)、混在して書かれてる記事が多いので、ややこしいです。(= = ;;)
データの操作
前回のControllerのソースを一部抜粋しました。
Folderクラス(DBのテーブル名はfolders)のall()、find()、where()を使って、データベースに格納しているデータに対して操作していることがわかります。ちゃんとActive Recodeのデザインパターンになっていることがわかりますね。
■ TaskController(一部抜粋) namespace App\Http\Controllers; use App\Folder; use App\Task; class TaskController extends Controller { public function index(int $id) { // ① (DB)Folderテーブルから全件取得 $folders = Folder::all(); // ② HTTPリクエストから取得した$idをキーに(DB)Folderテーブルから検索 $current_folder = Folder::find($id); // ③ (DB)Taskテーブルから②と一致するデータを取得 $tasks = Task::where('folder_id', $current_folder->id)->get();
テストデータの作成
Webアプリケーションやシステムを作成していると、「あー、データがほしいなぁ」と思うことがあります。やはり、データがないとアプリケーションやシステムが動いてる感がでないですよね。
LaravelにはSeederと呼ばれる簡単にテストデータを用意する機能が搭載されています。
Seeder
これはfoldersテーブルにデータを追加するSeederの例です。
runメソッドの中でデータを追加(insert)しているのがわかると思います。
ここでの学びは、Seederは上記で学んだEloquentを使っていない点です。Eloquentの継承先にあるDBクラスを直接呼び出して、PHPでSQLっぽく書いています。これをデータベースクエリビルダと呼びます。
■ FoldersTableSeeder use Carbon\Carbon; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; class FoldersTableSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { $titles = ['プライベート', '仕事', '旅行']; foreach ($titles as $title) { ① DBクラスを直接呼び出してクエリビルダを使ってデータを追加(insert) DB::table('folders')->insert([ 'title' => $title, 'created_at' => Carbon::now(), 'updated_at' => Carbon::now(), ]); } } }
Eloquentとデータベースクエリビルダの違い
Eloquentを使用して取得したデータとデータベースクエリビルダを使用して取得したデータには違いがあります。
Eloquentを使用して取得したデータは、テーブルのクラスのオブジェクトとしてデータを取得しますが、データベースクエリビルダを使用して取得したデータは、stdClassのオブジェクトとしてデータを取得します。
そのため、データベースクエリビルダを使用すると前回で学んだアクセサ等が使えなくなります。
■データベースクエリビルダを使用してデータを取得 >>> var_dump(DB::table('folders')->get()); object(Illuminate\Support\Collection)#2939 (1) { ["items":protected]=> array(4) { [0]=> object(stdClass)#2932 (4) { ["id"]=> int(1) ["title"]=> string(18) "プライベート" ["created_at"]=> string(19) "2019-07-04 15:02:24" ["updated_at"]=> string(19) "2019-07-04 15:02:24" } [1]=> object(stdClass)#2938 (4) { ["id"]=> int(2) ["title"]=> string(6) "仕事" ["created_at"]=> string(19) "2019-07-04 15:02:24" ["updated_at"]=> string(19) "2019-07-04 15:02:24" } [2]=> object(stdClass)#2949 (4) { ["id"]=> int(3) ["title"]=> string(6) "旅行" ["created_at"]=> string(19) "2019-07-04 15:02:24" ["updated_at"]=> string(19) "2019-07-04 15:02:24" } [3]=> object(stdClass)#2946 (4) { ["id"]=> int(4) ["title"]=> string(9) "テスト" ["created_at"]=> string(19) "2019-07-13 05:08:33" ["updated_at"]=> string(19) "2019-07-13 05:08:33" } } } => null ■Eloquentを使用してデータを取得 >>> Folder::all(); [!] Aliasing 'Folder' to 'App\Folder' for this Tinker session. => Illuminate\Database\Eloquent\Collection {#2950 all: [ App\Folder {#2952 id: 1, title: "プライベート", created_at: "2019-07-04 15:02:24", updated_at: "2019-07-04 15:02:24", }, App\Folder {#2953 id: 2, title: "仕事", created_at: "2019-07-04 15:02:24", updated_at: "2019-07-04 15:02:24", }, App\Folder {#2954 id: 3, title: "旅行", created_at: "2019-07-04 15:02:24", updated_at: "2019-07-04 15:02:24", }, App\Folder {#2955 id: 4, title: "テスト", created_at: "2019-07-13 05:08:33", updated_at: "2019-07-13 05:08:33", }, ], } >>>
最後に
今回はデータベース周りについて学びました。Eloquentとデータベースクエリビルダの違いは、私もすごく勉強になりました。できる限りEloquentを使用する方がコードをキレイに書くことができそうです。
では、また自分自身の理解も兼ねて引き続きアウトプットしていきたいと思います。( = = )ノ