- 投稿日:2020-01-25T18:22:29+09:00
PHP/Laravelで初の新規開発を行ったので利用したライブラリや概念などまとめてみる
概要
独学でちょい勉強して未経験エンジニアとしてスタートで、まだ働き始めて1年経たないですが、初めて新規での開発(バックエンド部分メイン)を担当したのでその感想として、利用したライブラリや概念などを紹介したいと思います。
1ヶ月ちょっととかで大体終わらせる感じだったのであまりライブラリ選定であったり設計にかける時間も
取れない中だったのですが、少しでも参考になればと思います。Formatなど記述や構造で注意したとこ
ディレクトリ構造
並列でポンポンフォルダ置くことは避けました。
特に名前が2単語3単語のファイルが出てくるときには、ディレクトリでカテゴリ作って
綺麗にできるように工夫しています。特にモデルをlaravel内でのファイル名からの
テーブル名識別に頼らずに積極的にリレーション系列はまとめて下層において分かりやすくしました。
例えばusersテーブルに対する、user_prefilesテーブルだったらModels----User.php | |-User----Profile.php作っているときに「これじゃやっぱわかりづれぇわ」なんてことは山ほどあったのでその度に何回も何回も
ディレクトリ構造変更していました?Routing
Route::get('/')->name('home')->uses('HomeController');ルーティングのフォーマットもnameをつけて全て指定したかったので、
nameがパッと見わかりやすいようなフォーマットで統一。多分、見やすい...タブンネ......?
Relation定義
public function keywords() { return $this->hasMany(Keyword::class); }よくStringとしてシングルクオーテーション使って定義しているの見ますけど、
PHPStorm使っている身としてはリレーション定義見たらジャンプして秒速でクラスの確認まで飛べたら嬉しい?
ってことで直接クラスを書いてのリレーション定義しています、この書き方できると知った時は感動しました?Transformer
モデルめちゃくちゃ使うPHP開発においては
覚えて損はない最強の概念だと思っています、
これを定義したおかげで秒速でコーティングが終わった部分も多く存在します?
私が執筆した記事があるのでよかったらそちらを参照してください。私の行った開発においてはリスト表示で使いたい配列を返すTransformerと、
詳細表示で使いたい配列を返すTransformerをそれぞれ二つ用意したりしました。
あとUser登録とUser情報編集など複数ページで似たようなデータ扱う兼ね合いもあり、
Request用にもTransformer作ったりしてます。https://qiita.com/fumifumitaro/items/21bde4e60a908915dde8
scopeクエリ
whereで検索する際nullが混入してしまうと、
うまく検索できなくなるためissetやis_nullでwhereに通さない処理を加えるのをよくみます、
ただあまりにメソッドが冗長になって気持ち悪いのでscopeでカスタムしたwhereを作成しました。public function scopeCustomWhere($query, string $column, string $param = null) { if (is_null($param) || $param == '') return; return $query->where($column, $param); }チェーンして繋げることもできるので楽です、traitとしていろんなモデルに入れて、
customWhereとして利用しました。
なんかnull弾いてwhereするメソッドってありそうですけど私が見つけてないんですかね?
にしてもいつまでもいい命名が出来ずに仮置きしたクソネームメソッドのままリリースしてしまった使用したライブラリ
マークダウン - SimpleMDE
マークダウンエディタを組み込むときに選んだのがこちらです。
導入がとても簡単ですが、奥が深く内部コードをしっかりと読み込んでカスタマイズしなければ
やや手に余ります。画像の追加機能などをカスタムしました。
ホントはvue.jsに色々あるので先にそちらを導入してみたのですが、
こちらのsimplemdeの場合は普通のhtml上のtextareaを拡張してそのまま利用できるため、
submitしたときtextareaに指定したname属性でsubmitされたり、
取り回しが楽そうなのでこちらに変更しました。フォーマッター - Cleave.js
郵便番号や電話番号にハイフンを強制したかったために導入しました。
(入力データの検索かけるときにハイフンなしとありが混在すると面倒、inputのtype="number"などで
数字入力を強制するのもありだと思ったけど個人的にはハイフンありの方がみやすいし入力ユーザー的には
ハイフンが強制された方がいいのかなと。。。)
導入も簡単な上とっても使いやすくて幸せになれました?https://nosir.github.io/cleave.js/
住所の自動入力 - yubinbango
クラス指定での導入だったためJS知らなくても楽にぶち込めちゃいます!
なんかajaxzipとかわかりづらくてもっと簡単なのないかなぁと思ってまして...笑
特によかったポイントが都道府県をプルダウン形式のセレクトでも
自動で入力する機能が備わっていたこと!
下の方にセレクトの場合とか書いています。
https://www.whizz-tech.co.jp/1843/https://github.com/yubinbango/yubinbango
ドラッグ&ドロップ - VueDraggable
ドラッグ&ドロップ機能を実装してから、仕事に対する現実逃避に
適当に作った項目の順番を数時間並べ換えていたのはここだけの話です
わかりやすいけどcssとかテーブルで融通が聞かなくてちょっと困った
多分私の勉強不足でしょうけど、とりあえずテーブルのヘッドだけ別途で作成したりして誤魔化しました。
vue.jsはstyleにSassが書けるのでデザイン変更したい時もやりやすい!
ちなみにこいつ自体には順番を保持する機能がなさげなのでv-forのindexを
inputしたいデータにうまいことバインドさせてDBまで連れてってあげる必要があります。https://www.npmjs.com/package/vue-draggable
ちょっとしたUI変更にて使用 element-ui
デザインが結構好み
ただし、レスポンシブ対応がびみょいので他の選択肢を探した方がいいかもしれない。
私は使いたいcomponentが少しだけだったのでcss軽くいじってflexで誤魔化しました。
使いたかったのがこのtransferと呼ばれる左右にリスト表示させて
選択と非選択をわかりやすく見せるUIを作成したかったために導入、
https://element.eleme.io/#/en-US/component/transferhttps://element.eleme.io/#/en-US
最後に
経験数的にもまだまだ未熟ですしもっと良いライブラリ選定ができたり、
設計技法が使えたろうなぁとは思っています。
他にもライブラリ導入などで開発スピードを上げられた部分や
保守運用を楽にできた場面も数多くあるでしょうし、今後も精進していきます。
- 投稿日:2020-01-25T18:11:16+09:00
Laravel DB.com アップデート「 ER図 →CRUD自動生成ツール&テストデータ 」
Laravel DB.com
「 テストデータ登録 」 までCODEを書かずに作成可能なツールにアップデートされました。
私の開発環境
- Laravel5.5/PHP7.2.1/MySQL5.6.38 (Mac: Chromeで確認)
LaravelDB.com 操作解説ページはこちらです。
【 Laravel 】CRUD『 表示・登録・更新・削除 』機能をCODEを書かず自動作成
https://qiita.com/daisu_yamazaki/items/3755467b39ef158b81a3
アップデート内容
faker自動生成(テストデータ生成処理)
注意点:テーブル作成後 → テストデータ投入 の順でコマンド打ってください。
ファイルの中はこんな感じです。
自動で文字が入ってるので、精度はまあこんなもんですかね。※文字列、数値、日付は自動で判定して入れてくれてるようです。
コマンド打って表示して見ましょう!!!!
php artisan migrate //既にmigrationファイルも設置済みであること php artisan db:seed //既にseederファイルも設置済みであること(上記写真を確認)
LaravelDB.com はじめての人はこちらからどうぞ !!! 慣れると最強ですね。
【 Laravel 】CRUD『 表示・登録・更新・削除 』機能をCODEを書かず自動作成
https://qiita.com/daisu_yamazaki/items/3755467b39ef158b81a3以上
- 投稿日:2020-01-25T18:11:16+09:00
ER図 からCRUD自動生成ツール。テストデータFakerも生成【Laravel DB.com 】
Laravel DB.com
「 テストデータ登録 」 までCODEを書かずに作成可能なツールにアップデートされました。
私の開発環境
- Laravel5.5/PHP7.2.1/MySQL5.6.38 (Mac: Chromeで確認)
LaravelDB.com 操作解説ページはこちらです。
【 Laravel 】CRUD『 表示・登録・更新・削除 』機能をCODEを書かず自動作成
https://qiita.com/daisu_yamazaki/items/3755467b39ef158b81a3
アップデート内容
faker自動生成(テストデータ生成処理)
注意点:テーブル作成後 → テストデータ投入 の順でコマンド打ってください。
ファイルの中はこんな感じです。
自動で文字が入ってるので、精度はまあこんなもんですかね。※文字列、数値、日付は自動で判定して入れてくれてるようです。
コマンド打って表示して見ましょう!!!!
php artisan migrate //既にmigrationファイルも設置済みであること php artisan db:seed //既にseederファイルも設置済みであること(上記写真を確認)
LaravelDB.com はじめての人はこちらからどうぞ !!! 慣れると最強ですね。
【 Laravel 】CRUD『 表示・登録・更新・削除 』機能をCODEを書かず自動作成
https://qiita.com/daisu_yamazaki/items/3755467b39ef158b81a3以上
- 投稿日:2020-01-25T18:11:16+09:00
【 laravel】ER図 からCRUD自動生成ツール。テストデータ生成も追加!【Laravel DB.com 】
2020/01/28最新バージョン:Laravel DB.com
「 テストデータ(faker)登録 」 までCODEを書かずに作成可能なツールにアップデートされました。
私の開発環境
- Laravel5.5/PHP7.2.1/MySQL5.6.38 (Mac: Chromeで確認)
LaravelDB.com 操作解説ページはこちらです。
【 Laravel 】CRUD『 表示・登録・更新・削除 』機能をCODEを書かず自動作成
https://qiita.com/daisu_yamazaki/items/3755467b39ef158b81a3
アップデート内容
faker自動生成(テストデータ生成処理)
【移行方法】
Macの場合: 「Optionキー + ドラッグ&ドロップ」 → 「結合」でフォルダの上書きではなく、結合になります。
Winの場合: 「ドラッグ&ドロップ」で結合できます。
ファイルの中はこんな感じです。
自動で文字が入ってるので、精度はまあこんなもんですかね。※文字列、数値、日付は自動で判定して入れてくれてるようです。
※ Fakerで使えるタイプ一覧、 自身で変更して使いたい場合はこちらを参考にすることをオススメします。注意点:テーブル作成後 → テストデータ投入 の順でコマンド打ってください。
コマンド打って表示して見ましょう!!!!
php artisan migrate //既にmigrationファイルも設置済みであること php artisan db:seed //既にseederファイルも設置済みであること(上記写真を確認)<< 注意点 >>
「address」や「url」を使う場合はカラムサイズに気をつけましょう!
ブラウザで確認
LaravelDB.com はじめての人はこちらからどうぞ !!! 慣れると最強ですね。
【 Laravel 】CRUD『 表示・登録・更新・削除 』機能をCODEを書かず自動作成
https://qiita.com/daisu_yamazaki/items/3755467b39ef158b81a3以上
- 投稿日:2020-01-25T17:02:12+09:00
Laravelのリレーション、Eloquentについて
Eloquentについて
データベースとモデルを紐つける機能
1対1
例題
今回はUsersとProfilesテーブルの連携について考えます。
ユーザーを管理するテーブルにはidとnameカラムがあります。
プロフィールを管理するテーブルにはidとuser_idとurlがあります。
1対1のリレーションでは1人のユーザーは1つのプロフィールを持っていることが前提となります。Userモデルの作成
$ php artisan make:model User -m Model created successfully. Created Migration: 2020_01_14_084605_create_users_tabledatabase/migrations/2020_01_14_084605_create_users_tablepublic function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); + $table->string('name'); $table->timestamps(); }); }Profileモデルの作成
$ php artisan make:model Profile -m Model created successfully. Created Migration: 2020_01_14_090207_create_profiles_tabledatabase/migrations/public function up() { Schema::create('profiles', function (Blueprint $table) { $table->bigIncrements('id'); + $table->integer('user_id'); + $table->string('url'); $table->timestamps(); }); }ポイント
UserモデルにhasOneを定義
テーブル間の関係はuserテーブルのidをprofileテーブルのuser_idで紐つける。
Userモデルに定義する
app/User.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function profile() { return $this->hasOne(Profile::class); } }Profileモデルに定義する
app/Profile.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class Profile extends Model { public function user() { return $this->belongsTo(User::class); } }データベースにデータを挿入する。
DatabaseSeeder.phpを編集
database/seeds/DatabseSeeder.phppublic function run() { $this->call(UsersTableSeeder::class); $this->call(ProfilesTableSeeder::class); }UsersTableSeeder.php
database/seeds/UsersTableSeeder.phpProfilesTableSeeder.php
database/seeds/ProfilesTableSeeder.phptinkerで確認
$ php artisan tinker Psy Shell v0.9.12 (PHP 7.3.13 — cli) by Justin Hileman >>> $user = User::find(1); [!] Aliasing 'User' to 'App\User' for this Tinker session. => App\User {#2980 id: 1, name: "Enomoto Riko", created_at: "2020-01-14 09:13:35", updated_at: "2020-01-14 09:13:35", } >>> $user->profile; => App\Profile {#2983 id: 4, user_id: 1, url: "https://1", created_at: "2020-01-14 09:22:02", updated_at: "2020-01-14 09:22:02", } >>>1対多
例)ユーザーを管理しているuserテーブルとユーザーが注文したNoを管理しているordersテーブルで考えてみる。ユーザーはたくさんの注文をしており、注文は整数のNoで管理されている。
Orderモデルの作成
php artisan make:model Order -m Model created successfully. Created Migration: 2020_01_23_124628_create_orders_tableodersテーブルを作成
database/migrations/2020_01_23_124628_create_orders_table.phppublic function up() { Schema::create('orders', function (Blueprint $table) { $table->bigIncrements('id'); $table->integer('user_id'); $table->integer('order_no'); $table->timestamps(); }); }$ php artisan migrate Migrating: 2020_01_23_124628_create_orders_table Migrated: 2020_01_23_124628_create_orders_table (0.03 seconds)seederファイルの作成
php artisan make:seeder OrdersTableSeeder Seeder created successfully.OrdersTableSeederの編集
database/seeds/OrdersTableSeederpublic function run() { DB::table('orders')->insert([ ['user_id' => 3,'order_no' => '00001','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 3,'order_no' => '00002','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 4,'order_no' => '00003','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 2,'order_no' => '00004','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 1,'order_no' => '00005','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 3,'order_no' => '00006','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 5,'order_no' => '00007','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 1,'order_no' => '00008','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 4,'order_no' => '00009','created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_id' => 5,'order_no' => '00010','created_at' => new Datetime(),'updated_at' => new Datetime()], ]); }DatabaseSeeder.phpの編集
seederの実行
tinkerで確認
$user = User::find(1); => App\User {#2973 id: 1, name: "Enomoto", created_at: "2020-01-23 13:15:07", updated_at: "2020-01-23 13:15:07", } >>> $user->order; => Illuminate\Database\Eloquent\Collection {#3001 all: [ App\Order {#2998 id: 5, user_id: 1, order_no: "00005", created_at: "2020-01-23 13:15:07", updated_at: "2020-01-23 13:15:07", }, App\Order {#2997 id: 8, user_id: 1, order_no: "00008", created_at: "2020-01-23 13:15:07", updated_at: "2020-01-23 13:15:07", }, ], }多対多
例)ユーザーテーブルとスキルテーブルで確認します。
スキルテーブルにはプログラミングの言語が入っています。
あるユーザは複数のプログラミングを扱えるとします。Skillモデルを作成します。
$ php artisan make:model Skill -m Model created successfully. Created Migration: 2020_01_24_134708_create_skills_tableskillsテーブルの作成
public function up() { Schema::create('skills', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('language'); $table->timestamps(); }); }migration実行
$ php artisan migrate Migrating: 2020_01_24_134708_create_skills_table Migrated: 2020_01_24_134708_create_skills_table (0.03 seconds)seederファイルの作成
$ php artisan make:seeder SkillsTableSeeder Seeder created successfully.seederを実行する
database/seeds/DatabaseSeeder.phppublic function run() { // $this->call(UsersTableSeeder::class); // $this->call(ProfilesTableSeeder::class); // $this->call(OrdersTableSeeder::class); $this->call(SkillsTableSeeder::class); }実行
$ php artisan db:seed Seeding: SkillsTableSeeder Database seeding completed successfully.中間テーブルuser_skillの作成
migrationファイルの作成
$ php artisan make:migration create_user_skill_table Created Migration: 2020_01_25_012117_create_user_skill_tableuser_skillテーブルの作成
database/migrations/2020_01_25_012117_create_user_skill_tablepublic function up() { Schema::create('user_skill', function (Blueprint $table) { $table->bigInteger('user_id')->unsigned(); $table->bigInteger('skill_id')->unsigned(); $table->primary(['user_id','skill_id']); //外部キー制約 $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); // $table->foreign('skill_id') ->references('id') ->on('skills') ->onDelete('cascade'); }); }migrateの実行
seeder関連
database/seeds/UserSkillTableSeederpublic function run() { DB::table('skill_user')->insert([ ['user_id' => 1, "skill_id" => 1], ['user_id' => 1, "skill_id" => 3], ['user_id' => 2, "skill_id" => 2], ['user_id' => 2, "skill_id" => 3], ['user_id' => 3, "skill_id" => 4], ['user_id' => 4, "skill_id" => 5], ['user_id' => 5, "skill_id" => 1], ]); }モデル関連の修正
Userモデル編集
app/User.phppublic function skills() { return $this->belongsToMany(Skill::class); }Skillモデルの編集
app/Skill.phppublic function users() { return $this->belongsToMany(User::class); }tinkerで確認
$ php artisan tinker Psy Shell v0.9.12 (PHP 7.3.13 — cli) by Justin Hileman >>> $skill = Skill::find(1); [!] Aliasing 'Skill' to 'App\Skill' for this Tinker session. => App\Skill {#2980 id: 1, language: "HTML", created_at: "2020-01-25 03:15:24", updated_at: "2020-01-25 03:15:24", } >>> $skill->users; => Illuminate\Database\Eloquent\Collection {#2981 all: [ App\User {#2984 id: 1, name: "Enomoto", created_at: "2020-01-25 03:15:24", updated_at: "2020-01-25 03:15:24", pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2983 skill_id: 1, user_id: 1, }, }, App\User {#2988 id: 5, name: "Sugihara", created_at: "2020-01-25 03:15:24", updated_at: "2020-01-25 03:15:24", pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2986 skill_id: 1, user_id: 5, }, }, ], } >>>番外編:id以外をprimary_keyにするuserのnameで紐つける
usersテーブルのmigrationファイルを修正
database/migrations/2020_01_14_084605_create_users_table.phppublic function up() { Schema::create('users', function (Blueprint $table) { // $table->bigIncrements('id'); $table->string('name')->primary(); $table->timestamps(); }); }profilesテーブルのmigrationファイルを修正
database/migrations/2020_01_14_090207_create_profiles_table.phppublic function up() { Schema::create('profiles', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('user_name'); $table->string('url'); $table->timestamps(); }); }ポイント:テーブル名プライマリーキー→username
Userモデルを編集
app/User.php<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { protected $primaryKey = "name"; protected $keyType = "string"; public $incrementing = false; public function profile() { return $this->hasOne(Profile::class); } }protected $primaryKey = "name";
nameカラムをプライマリーキーに設定
public $incrementing = false;
1づつ増えていく整数にしない場合
データベースにデータを挿入
usersテーブルに挿入するデータ
database/seeds/UsersTableSeeder.phppublic function run() { DB::table('users')->insert([ ['name' => 'Enomoto','created_at' => new Datetime(),'updated_at' => new Datetime()], ['name' => 'Amano','created_at' => new Datetime(),'updated_at' => new Datetime()], ['name' => 'Shimamura','created_at' => new Datetime(),'updated_at' => new Datetime()], ['name' => 'Hirai','created_at' => new Datetime(),'updated_at' => new Datetime()], ['name' => 'Sugihara','created_at' => new Datetime(),'updated_at' => new Datetime()], ]); } }profilesテーブルにデータを挿入
database/seeds/ProfilesTableSeeder.phppublic function run() { DB::table('profiles')->insert([ ['user_name' => 'Amano','url' => "https://AmanoYasushi",'created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_name' => 'Sugihara','url' => "https://SugiharaGensei",'created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_name' => 'Enomoto','url' => "https://EnomotoRiko",'created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_name' => 'Shimamura','url' => "https://ShimamuraMayu",'created_at' => new Datetime(),'updated_at' => new Datetime()], ['user_name' => 'Hirai','url' => "https://HiraiHana",'created_at' => new Datetime(),'updated_at' => new Datetime()], ]); } }tinkerで確認
$ php artisan tinker Psy Shell v0.9.12 (PHP 7.3.13 — cli) by Justin Hileman >>> $user = User::find('Amano'); [!] Aliasing 'User' to 'App\User' for this Tinker session. => App\User {#2980 name: "Amano", created_at: "2020-01-22 11:54:31", updated_at: "2020-01-22 11:54:31", } >>> $user->profile; => App\Profile {#2983 id: 1, user_name: "Amano", url: "https://AmanoYasushi", created_at: "2020-01-22 11:54:31", updated_at: "2020-01-22 11:54:31", }$user = User::find('Amano');
プライマリーキーのnameをAmanoで検索
$user->profile;
profilesテーブルからnameの"Amano"に該当する外部キーuser_nameからデータを取得