Memo

メモ > 技術 > フレームワーク: Laravel > データベース

■データベース
■マイグレーションとモデルの作成
php artisan make:migration create_articles_table ... 「create_articles_table」というマイグレーションクラスを作る php artisan make:migration create_articles_table --table=articles ... 「articles」テーブルを作成するカラのコードを追加する php artisan make:migration create_articles_table --create=articles ... 「articles」テーブルを作成・削除するコードを追加する php artisan make:model Article ... 「Article」というモデルを作成 php artisan make:model Person -m ... Personモデルとpeopleテーブルのマイグレーションをセットで作成。Person は people になる Model created successfully. Created Migration: 2016_12_05_151532_create_people_table
※コマンドラインで操作 ※artisan=職人 ■マイグレーションでエンジンを設定
$table->engine = 'InnoDB';
■マイグレーションで真偽値を設定
available TINYINT(1) NOT NULL COMMENT '有効',
MySQLでこのような定義を行いたい場合、以下のように指定する
$table->boolean('available')->comment('有効');
■マイグレーションでコメントを設定 [Laravel]マイグレーションでテーブルにコメントを入れる|atuweb - ヒーローになるIT人材育成研究室 https://ameblo.jp/atuweb/entry-12204289098.html Laravel - Laravel のマイグレーションでテーブルカラムにコメントを設定する(91732)|teratail https://teratail.com/questions/91732 ■既存のテーブル定義からマイグレーションを作成 Laravelで既存のDBからmigrationsファイルを作成する「migrations-generator」 - Qiita https://qiita.com/busyoumono99/items/a7173ad6b9b041da09dd ■基本的なリレーション モデルで以下のようなメソッドを定義
class User extends Authenticatable { public function entries() { return $this->hasMany('App\Entry'); }
コントローラで以下のようにして取得
$users = App\User::get(); foreach ($users as $user) { $result .= $user->id . ' | ' . $user->name . ' | ' . $user->email . '<br>'; foreach ($user->entries as $entry) { $result .= $entry->id . ' | ' . $entry->title . '<br>'; } $result .= '<br>'; }
Eloquent:リレーション 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent-relationships.html 親子関係のテーブルでのクエリーの作成(Eloquent編) - ララジャパン https://www.larajapan.com/2016/07/09/%E8%A6%AA%E5%AD%90%E9%96%A2%E4%BF%82%E3%81%AE%E3%83%86%E3%83%BC... ■リレーション先の情報で検索 【Laravel・whereHas】リレーション先でクエリ実行 | とものブログ https://se-tomo.com/2018/10/06/laravel%E3%81%A7%E3%81%AE%E3%83%AA%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A... Laravelでリレーション先の条件で検索 | webOpixel https://www.webopixel.net/php/1412.html 以下、リポジトリ内での検索例
if (isset($conditions['staff_company_number'])) { $query->whereHas('staffCompanies', function($query) use($conditions) { $query->where('company_number', $conditions['staff_company_number']); }); }
■N+1問題 以下のように with を使うと、あらかじめ関連するデータを取得する
$users = App\User::get(); ↓ $users = App\User::with('entries')->get();
Eloquent:リレーション 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent-relationships.html 「Eagerローディング」の項目を参照 width で読み込んだデータを対象に、whereで絞り込みを行うこともできる 「Eagerロードへの制約」の項目を参照 Laravel|STEP UP BLOG http://capella.3rin.net/Category/2/ ■記事とカテゴリ、記事とタグなど多対多のリレーション 「(33) 多対多のリレーション モデル/DB編」の解説によると、 ・「記事が複数のタグを持てる」のようなリレーションを行う場合は中間テーブルを使う ・中間テーブルは、テーブル名を関連するモデル名をアルファベット順で並べた名前にする(デフォルトの規約) ・中間テーブルのタイムスタンプを更新したい場合、withTimestamps() を指定する ・中間テーブルにオートインクリメントな主キーは、あっても無くてもいい みたい Eloquent:リレーション 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent-relationships.html#many-to-many 初めてのLaravel 5.1 : (33) 多対多のリレーション モデル/DB編 - ララ帳 https://laravel10.wordpress.com/2015/03/30/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AElaravel-5-33-%E5%A4%9... 初めてのLaravel 5.1 : (34) 多対多のリレーション UI編 - ララ帳 https://laravel10.wordpress.com/2015/03/31/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aelaravel-5-34-%e5%a4%9... Laravel5.4で基本的なリレーションを学んでみる | webOpixel http://www.webopixel.net/php/1261.html Laravel5.2で多対多(BelongsToMany)のリレーション | will STYLE Inc.|神戸にあるウェブ制作会社 https://www.willstyle.co.jp/blog/353/ ■外部キー制約 要検証 以下のようにすれば、entriesテーブルやtagsテーブルのデータが削除された時、自動でentry_tagのデータも削除される が、代理キーで管理するなら原則として削除されないことになる 「想定外のidが入らないように」という点では有効だが、外部キー制約を使うか否かは要検討 また、外部キー制約を付けるとしても、マイグレーションでは行わずにシーダーで行うほうがいい?
Schema::create('entry_tag', function(Blueprint $table) { $table->integer('entry_id')->unsigned()->index(); $table->integer('tag_id')->unsigned()->index(); $table->foreign('entry_id')->references('id')->on('entries')->onDelete('cascade'); $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade'); });
■子モデル更新時に親モデルのタイムスタンプを更新 未検証 子モデル側の $touches プロパティにリレーション先を設定する
protected $touches = ['post'];
Eloquent:リレーション 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent-relationships.html ■主キーをUUIDにする LaravelでUUIDを使う際の設定 - Qiita https://qiita.com/NewBieChan/items/3d0f8025accd770bd6d3 UUID - Qiita https://qiita.com/hththt/items/801bf4664332a0346650 UUIDはなぜ、分散環境で好き勝手に生成しても衝突しないのか。RFC4122規格とUUIDの性質。 | 三度の飯とエレクトロン http://blog.katty.in/5124 ■主キーを複合主キーにする 代理キーで管理するのが前提となっているみたい。 複合主キーに対応できないわけではないみたいだが、代理キーを使っておくのが無難 他の主要フレームワークも代理キー前提が基本なので、 「複合主キーを使いたいからLaravelは採用しない」とはならなさそう 複合主キーにしてリレーションに問題が起きないかは要検証 [Laravel]Eloquent ORMで複合主キーはオススメしない http://atuweb.net/201610_laravel-eloquent-orm-id-agreement/ PHP - Laravelで複合主キーを使ったモデルを更新できない(36627)|teratail https://teratail.com/questions/36627 Laravel5で複合キーを扱う - KaokenとLaravel https://laravel.cg0.xyz/handle-compound-keys-with-laravel-5/ LaravelのEloquentを使って複合主キーを使用したテーブルを操作する方法 - Qiita http://qiita.com/wrbss/items/7245103a5fef88cbdde9 Eloquentで多対多のリレーション - Laravel Room https://laravel-room.com/many-to-many-relationshop ■ユニークな複合キー
$table->unique(['first', 'last']);
データベース:マイグレーション 5.4 Laravel https://readouble.com/laravel/5.4/ja/migrations.html ■データを検索して一覧表示 検索機能の作成 - Laravel学習帳 http://laraweb.net/tutorial/607/ ■操作したユーザの自動記録 Laravelのeloquentのeventでcreated_byとかupdated_byとか更新するobserverとtrait - Qiita https://qiita.com/maimai-swap/items/6597c04721adbc48fec2 Soft delete: "deleting" event does not automatically update the model before it is soft deleted - Issue #4990 - laravel/framework https://github.com/laravel/framework/issues/4990 Eloquent: Getting Started - Laravel - The PHP Framework For Web Artisans https://laravel.com/docs/5.3/eloquent#events Eloquent:利用の開始 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent.html#events 各テーブルで created_by_user_id, updated_by_user_id, deleted_by_user_id これらの値を更新する必要があるが、都度コントローラから指定すると更新し忘れが発生する 自動で更新する仕組みを導入するといい 各モデルで必要に応じて以下のtraitを宣言すれば、自動で更新されるようにしている use RegisterAuthor; ■トランザクション 以下のように記述すると、ロールバックやコミットを自動で制御してくれる
DB::transaction(function () { DB::table('users')->update(['votes' => 1]); DB::table('posts')->delete(); });
もしくは以下を個別に呼び出す
DB::beginTransaction(); DB::rollBack(); DB::commit();
データベース:利用開始 5.4 Laravel https://readouble.com/laravel/5.4/ja/database.html Laravel5.3でselect for update する方法 - Qiita https://qiita.com/taichi_akippa/items/465e986462be05a3ae42 Laravelで行ロックとテーブルロックする方法【lockForUpdate】 | みんたく https://mintaku-blog.net/laravel-lockforupdate/ ■生SQLの指定 Laravel5のアーキテクチャから学ぶより良いクラス設計 - Qiita http://qiita.com/nunulk/items/2c637d3952096ef74677
$users = DB::table('users') ->join('contracts', 'contracts.user_id', '=', 'users.id') ->select('users.id', DB::raw('count(*) as contract_count')) ->orderBy('users.id') ->groupBy('users.id') ->having(DB::raw('count(*)'), '>', $count) ->get() ; ↓ $sql =<<<EOQ; SELECT u.id, count(*) as contract_count FROM users INNER JOIN contracts c ON c.user_id = u.id GROUP BY u.id HAVING count(*) > ? ORDER BY u.id EOQ; $users = DB::select($sql, [$count]);
■ソフトデリート マイグレーションを作成
php artisan make:migration alter_articles_table
マイグレーションを修正
public function up() { Schema::table('articles', function (Blueprint $table) { $table->softDeletes(); //$table->timestamp('deleted_at')->nullable()->after('updated_at'); }); } public function down() { Schema::table('articles', function (Blueprint $table) { $table->dropColumn('deleted_at'); }); }
マイグレーションを実行
php artisan migrate
モデルを修正 C:\localhost\home\test\public_html\laravel\test\app\Article.php
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Article extends Model { use SoftDeletes; /** * 日付へキャストする属性 * * @var array */ protected $dates = ['created_at', 'updated_at', 'deleted_at']; }
データベース:マイグレーション 5.4 Laravel https://readouble.com/laravel/5.4/ja/migrations.html Eloquent:利用の開始 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent.html 削除処理の流れ データ削除時、通常は \test\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php 内の delete() が呼ばれる その中で performDeleteOnModel() が呼ばれており、これにより削除処理が走る SoftDeletesトレイトでこのメソッドを上書きしているので、これにより削除時の挙動が変わる 取得処理の流れ Laravelの機能で、モデルは「boot + トレイト名」を最初に実行する よって bootSoftDeletes() が最初に実行される このメソッド内でスコープを渡し、データ取得時はそれによって構築されるクエリが変化する http://qiita.com/niisan-tokyo/items/d3be588b53df8fa0278c ■複数代入 \test\app\Article.php
/** * 複数代入する属性 * * @var array */ protected $fillable = ['subject', 'detail'];
\test\app\Http\Controllers\ArticleController.php
// 通常の代入 $article = new Article; $article->subject = $request->subject; $article->detail = $request->detail; $article->save(); // 複数代入 $article = new Article; $article->fill($request->all())->save(); // このようにも書ける Article::create($request->all());
複数代入を使用する場合、意図しない代入を防ぐためあらかじめモデルで $fillable で代入を許可する項目を指定するか $guarded で代入を許可しない項目を指定するか を定義しておく必要がある。原則として $fillable での指定で良さそう
// 編集ならこのように書けば良さそう Article::find(15)->update($request->all()); // 削除ならこのように書けば良さそう Article::find(15)->delete(); Article::findOrFail(15)->delete();
【Laravel:Eloquentクラス】fillableとguardedの指定はどちらかだけでいい - Qiita http://qiita.com/kk_take/items/3e0639ed605f74c34619 Article::findOrFail(15) の書き方については、以下の「Not Found例外」を参照 Eloquent:利用の開始 5.4 Laravel https://readouble.com/laravel/5.4/ja/eloquent.html ■モデルの型キャスト 【Laravel】DBから取得した値を$castsで型変換する【Attribute Casting】 - Qiita http://qiita.com/amymd/items/7cba844b03754f9c849b

Advertisement