- 投稿日:2021-01-15T21:38:29+09:00
Laravel × Dacapo データベースマイグレーションサポートツールの使い方
ダカーポとは
https://github.com/ucan-lab/laravel-dacapo
Laravelマイグレーションのサポートライブラリです。
データベースのテーブル定義をYAMLファイル(スキーマファイル)で管理し、マイグレーションファイルの生成を行います。※初期の開発時期に利用されることを想定しています。
2021.01.11 v4.0.0 リリース!
2020.01.11 Laravel Dacapo v4.0 Released !https://t.co/qCFAAkaDtm #Laravel #PHP pic.twitter.com/VbbuFSNdAu
— ucan@Qiita新人賞 (@ucan_lab) January 11, 2021v3.0から1年の時を経て、ついにバージョンv4.0をリリース致しました!?♂️
以前の古いコードをすべて破棄して新しく書き直してます。
少し挙動が異なる部分もあるのでこの機会に改めて使い方をご紹介します。以前のダカーポの記事
ダカーポの由来
ダ・カーポ(da capo)は音楽用語で「始めに戻って繰り返す」という意味があります。
PHPのパッケージ管理ツールであるComposerも作曲家という音楽用語であり、マイグレーションファイルをすべて削除して、最初から生成し直すことからピッタリな名前だなと思いました。
ダカーポを作った理由
デフォルトのマイグレーションのツラミ
- make:migration で自動生成された日付がバラバラで見にくい
- make:migration のコマンドの実行時間が遅い
- テーブル定義 → インデックス定義 → 外部キー制約の順に定義する手間
- ゴミマイグレーションが残る
- 最終的なテーブル構成はDBを直接見ないと把握しづらい
ダカーポの歴史
- 2018.11.06 v0.0.1 4files 初回リリース
- 2019.08.22 v1.0.0 22files 1ファイルで収まらなくなり、すべて書き直し
- 2019.08.22 v2.0.0 24files schema.ymlを分割可能、全カラムタイプに対応
- 2019.11.10 v3.0.0 35files 細々とバグFIXを続ける
- 2021.01.11 v4.0.0 144files メタプロでメンテしづらく、すべて書き直し
v1.0では4ファイルだけで書いてました...1日で主機能を書き上げたのでとてもFatなソースコードになってましたね。
それに比べて最新のv4.0ではファイル数が36倍に増えましたww
今後のバージョンアップに備えてLaravelでサポートされているカラムタイプやカラム修飾子をすべてクラスで管理するようにしました。ダカーポのインストール
$ composer require --dev ucan-lab/laravel-dacapoダカーポの執筆時バージョン
- Dacapo: 4.0.1
ダカーポのサポート
- PHP 7.4 以降
- Laravel 6.x 以降
- MySQL
- PostgreSQL
- SQL Server(サポート対象外)
- SQLite(サポート対象外)
ダカーポの初期化
$ php artisan dacapo:init
dacapo:init
Artisanコマンドを使用して、ダカーポの初期化を行います。
database/schemas/default.yml
が生成されます。
また、database/migrations
ディレクトリ内のマイグレーションファイルも削除されます。--no-clear オプション
$ php artisan dacapo:init --no-clear
database/migrations
ディレクトリ内のマイグレーションファイルの削除は行いません。--laravel6, --laravel7 オプション
$ php artisan dacapo:init --laravel6 $ php artisan dacapo:init --laravel7 $ php artisan dacapo:init --laravel8 # defaultそれぞれLaravel6, Laravel7のマイグレーションファイルを生成します。
デフォルトでは、Laravel8のマイグレーションファイルを生成します。
それぞれのバージョンで微妙にテーブル定義内容が異なるので、テンプレートを分けています。
database/schemas/default.yml
database/schemas/default.yml
には、Laravelフレームワークにて予め用意されている(database/migrations)マイグレーション3ファイルのテーブルの定義しています。database/schemas/default.ymlusers: columns: id: bigIncrements name: string email: type: string unique: true email_verified_at: type: timestamp nullable: true password: string rememberToken: true timestamps: true password_resets: columns: email: type: string index: true token: string created_at: type: timestamp nullable: true failed_jobs: columns: id: true uuid: type: string unique: true connection: text queue: text payload: longText exception: longText failed_at: type: timestamp useCurrent: trueダカーポの実行
$ php artisan dacapo
database/schemas/*.yml
からテーブル構成を読み込んでdatabase/migrations/1970_01_01_*.php
のLaravelマイグレーションファイルを生成します。
また、ダカーポで生成された古いマイグレーションファイルはコマンド実行の都度削除されます。続けて、
php artisan migrate:fresh
コマンドが実行されます。
すべてのテーブルの削除、及びマイグレーションの実行が行われます。--seed オプション
$ php artisan dacapo --seed
php artisan migrate:fresh
に続けて
php artisan db:seed
コマンドが実行されます。--no-migrate オプション
$ php artisan dacapo --no-migrateスキーマファイルからマイグレーションファイルを実行したあと、
php artisan migrate:fresh
コマンドを実行しまいオプションです。--refresh オプション
$ php artisan dacapo --refreshロールバック処理が動作するか、動作確認のためのオプションです。
スキーマの定義フォーマット
テーブル名: columns: カラム名: カラムタイプ カラム名: type: カラムタイプ args: カラムタイプの引数(任意) indexes: - columns: [カラム名] type: [インデックス修飾子] name: インデックス名(任意) foreign_keys: - columns: [カラム名] references: [カラム名] on: テーブル名スキーマの定義
カラムの定義
database/schemas/default.ymlusers: columns: # カラムタイプのみ指定する場合 votes: integer # カラムタイプに引数を指定する場合 amount: type: double args: 8, 2上記のYAMLを定義して
php artisan dacapo
を実行すると、下記のマイグレーションファイルが出力されます。database/migrations/1970_01_01_000001_create_users_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->integer('votes'); $table->double('amount', 8, 2); $table->string('email')->nullable(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }利用可能なカラムタイプ
*.columns.*.type
に指定できるカラムタイプです。
Laravelマイグレーションで利用可能なカラムタイプはすべて対応してます。bigIncrements, bigInteger, binary, boolean, char, dateTime, dateTimeTz, date, decimal, double, enum, float, foreignId, geometryCollection, geometry, id, increments, integer, ipAddress, jsonb, json, lineString, longText, macAddress, mediumIncrements, mediumInteger, mediumText, morphs, multiLineString, multiPoint, multiPolygon, nullableMorphs, nullableTimestamps, nullableUuidMorphs, point, polygon, rememberToken, set, smallIncrements, smallInteger, softDeletes, softDeletesTz, string, text, timestamps, timestampsTz, timestamp, timestampTz, time, timeTz, tinyIncrements, tinyInteger, unsignedBigInteger, unsignedDecimal, unsignedInteger, unsignedMediumInteger, unsignedSmallInteger, unsignedTinyInteger, uuidMorphs, uuid, year
カラム修飾子
上記リストのカラムタイプに加え、データベーステーブルにカラムを追加するときに使用できるカラム「修飾子」もあります。
users: columns: email: type: string nullable: true上記のYAMLを定義して
php artisan dacapo
を実行すると、下記のマイグレーションファイルが出力されます。database/migrations/1970_01_01_000001_create_users_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->string('email')->nullable(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }利用可能なカラム修飾子
alwaysModifier, autoIncrementModifier, charsetModifier, collationModifier, commentModifier, defaultModifier, defaultRawModifier, fromModifier, generatedAsModifier, indexModifier, nullableModifier, storedAsModifier, uniqueModifier, unsignedModifier, useCurrentModifier, useCurrentOnUpdateModifier, virtualAsModifier
利用不可なカラム修飾子
下記のカラム修飾子はダカーポではサポート対象外となっております。
after, change, first, renameColumn, dropColumn, dropMorphs, dropRememberToken, dropSoftDeletes, dropSoftDeletesTz, dropTimestamps, dropTimestampsTz, constrained, onUpdate, onDelete
インデックス修飾子
database/schemas/default.ymlusers: columns: id: bigIncrements name: string email: string indexes: - columns: [name, email] type: index name: users_name_index
- 1970_01_01_000001_create_users_table.php
- 1970_01_01_000002_create_users_index.php
- インデックスの定義ファイルは
000002
のプレフィックスが付きます。database/migrations/1970_01_01_000001_create_users_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }database/migrations/1970_01_01_000002_create_users_index.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersIndex extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function (Blueprint $table) { $table->index(['name', 'email'], 'users_name_index'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('users', function (Blueprint $table) { $table->dropIndex('users_name_index'); }); } }利用可能なインデックス修飾子
primary, unique, index, spatialIndex
外部キー制約
database/schemas/default.ymlusers: columns: id: bigIncrements name: string email: string posts: columns: id: bigIncrements user_id: unsignedBigInteger content: string foreign_keys: - columns: [user_id] references: [id] on: users
- 1970_01_01_000001_create_users_table.php
- 1970_01_01_000001_create_posts_table.php
- 1970_01_01_000003_constraint_posts_foreign_key.php
- 外部キーの定義ファイルは
000003
のプレフィックスが付きます。database/migrations/1970_01_01_000001_create_users_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('users', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('users'); } }database/migrations/1970_01_01_000001_create_posts_table.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreatePostsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->bigIncrements('id'); $table->unsignedBigInteger('user_id'); $table->string('content'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); } }database/migrations/1970_01_01_000003_constraint_posts_foreign_key.php<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class ConstraintPostsForeignKey extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('posts', function (Blueprint $table) { $table->foreign(['user_id'])->references(['id'])->on('users'); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::table('posts', function (Blueprint $table) { $table->dropForeign(['user_id']); }); } }その他
通常のマイグレーションファイルと併用可能
$ php artisan make:migration create_flights_table
php artisan dacapo
でdatabase/migrations
ディレクトリ内のマイグレーションファイルが削除されますが、
ダカーポで生成されたファイルのみ削除されます。(1970_01_01
のプレフィックスが付いたファイルのみ)YAMLで表現できないようなテーブル定義は通常のマイグレーションファイルを作成してください。
複数のスキーマファイルを利用可能
database/schemas/*.yml
ファイルを読み込むので、YAMLを分けて定義できます。
database/schemas/user.yml
database/schemas/staff.yml
ユーザー関連のテーブル、スタッフ関連のテーブル等、グループ分けをしてテーブルを定義していくこともできます。
今後の予定
ざっくり今後のダカーポについて検討していることを書きます。
あくまで予定で、全機能実装できるかは未定です...。v4.0
年末年始に一気に書き殴ったので、しばらくはリファクタリングに勤しみます。
新機能 v4.1
dacapo --mixin オプション
SQLiteは外部キー制約を書く場合は、テーブル定義と同じタイミングで実行する必要があるみたいです。
懸念点としては、制約を貼る順番によってはエラーになりそうなので生成順序を気にしないといけなさそう...?
難しそうなのでこのオプションの実装悩んでます。。dacapo --squash オプション
Laravel8に搭載されたマイグレーションスカッシングのイメージです。
ただ、mysqldump
コマンド入れてる必要があったり、.sql
ファイルで出力されちゃったりと不満があります。
--squash
オプションは1ファイルのマイグレーションファイルにまとめるオプションです。
これは需要ありそうかなと思ってるんですけどどうでしょうか??新機能 v4.2
テンプレート生成するコマンド
$ php artisan dacapo:generate:model $ php artisan dacapo:generate:factory $ php artisan dacapo:generate:seeder $ php artisan dacapo:generate:validationスキーマYAMLから各種テンプレートを生成する機能です。
v3系には合ったのですが、バージョンアップの兼ね合いで一旦コマンドを削除しました。v4.0系でも実装しようと思ったのですが、
Laravel8でモデルファクトリ書き方が丸っと変わったのでちょっと断念しました。新機能 v4.3
データベースからスキーマYAMLを逆生成するコマンド
$ php artisan dacapo:db:importこの機能が欲しくてv4.0の書き直しをしたので、なんとしてでもこの機能は実装する!
新機能 v4.4
データベースとスキーマYAMLの差分からマイグレーションを生成するコマンド
$ php artisan dacapo:db:diff
import
コマンドが実装できたら現行のテーブル構成とスキーマYAMLの差分ができたらいいなと思ってます。
これは実装難しそうなので悩んでます。
- 投稿日:2021-01-15T21:24:23+09:00
Laravel ウェブサイト サイバーセキュリティ#2 -SQLインジェクション-
概要
Laravelを用いたウェブサイトのサイバーセキュリティについて考察。
サイバーセキュリティに関して全く考えずにコーディングした後、「あれ、セキュリティのこと全く考えてないな」と気づいて調べてみたところ、結果的にlaravelフレームワークでほとんど対策できていた。第二回は、SQLインジェクションとディレクトリトラバーサル。
参考: https://www.ipa.go.jp/security/vuln/websecurity.html環境
- Windows 10
- PHP 8.0.0
- laravel 8.16.1
SQLインジェクション
概要
データベースを操作するSQL文を操作し、データベースを不正利用する攻撃。
【流れ】
1. 攻撃者が、入力フォームにSQL文の一部を入力し送信する。
2. サイト内で、入力情報をもとにSQL文を処理する際、意図しないデータベース操作が行われてしまう。脅威
- 非公開データの流出
- データの改ざん、消去
- 不正ログイン
Laravelにおける対策
まずは、クエリビルダを使うことを考える。
クエリビルダを使うことによって、PDO(*1)パラメータによるバインディング(*2)が自動的に使用されることになるため、追加の対策は不要。
*1: PHP Data Objectsの略。データベースの違いを吸収してくれる。
*2: 命令の一部を変数にすること。クエリビルダを使わず、生のSQL文を使用する場合は、SQL文の条件となるユーザからの入力値に対して、エスケープ処理を施すことが対策となる。ここでは、
' => ''
\ => \\
の変換を行えばよい。
こちらは、laravel特有ではなく、一般的なSQLインジェクション対策。ディレクトリトラバーサル
概要
設計者が意図しないファイルにアクセスされる攻撃。
脅威
- ファイルの不正閲覧、ダウンロード
Laravelにおける対策
まずは、外部パラメータをファイルパスとして指定しないようにする。
それが避けられない場合、固定ディレクトリ+ファイル名の構成にする。ファイル名の抽出は、
basename
関数を用いる。さらに保険として、ログイン中のユーザIDなどで、適切なアクセス制限をかけると尚良い。
まとめ
XSSやCSRFと同じく、外部からの入力を直接埋め込まないことが基本的な考え方になる。
今回は、Laravel特有のクエリビルダやPHPのbaseline関数を使う方法を紹介した。
- 投稿日:2021-01-15T21:06:38+09:00
【Laravel】php artisan コマンド
Laravelで使う php artisanコマンド
artisan アルチザンと読むらしい。アルチザンとは、 職人。技工。とかの意味らしい。
対話モード
$ php artisan tinkerこれで対話モードができる。
データベースの中身などを調べるときに使える。例えば,,,
User::all()このように行えば、Userテーブルのデータを確認することができる。
マイグレーション
$ php artisan migrateこれで、マイグレーションの実行ができる.
マイグレーションのやり直し
$ php artisan migrate:freshこれで、一旦全てのテーブルを削除しマイグレーションをやりなおすことができる。
seedデータの投入
$ php artisan db:seedseedファイルで作成したデータをDBに保存する
- 投稿日:2021-01-15T20:59:50+09:00
laravel をブラウザで表示しようとしてcould not be opened in append mode: failed to open stream: Permission deniedとなった時の解決法
larval をローカル環境であれこれ編集しようとして、
途中経過をブラウザで表示しようとしていたのですが、could not be opened in append mode: failed to open stream: Permission denied
とエラーが起きていつまでも解決しませんでした。
上記のエラーメッセージの手前に該当箇所のファイルの階層が示されており
そこの編集権限がない?といったメッセージ内容。解決できそうな参考記事をあれこれあたってみても、
sudo chmod 777 storage -R
と書かれていて、バカ正直にそのまま打ち込むと、
-R なんてファイルは存在しません。(No such file or directory) と出てくる。。。
そりゃそうか。誰かこの先詰まった時の参考になれば良いと思い書き残しておきます。
・エラーの意味
Permission denied : 権限が拒否されました。
つまり何かしら権限を書き換える必要がありそう。・どこの権限がない?
laravel プロジェクトが入っているXAMMP内の、~/laravelプロジェクト名/strage/logs/laravel.log で編集権限がないと言われました。
larval 開発の最初って多分このエラーにぶち当たることが多いのか。。?・やったこと
logsディレクトリ以下の権限を書き換えられるように以下のコードを
自分のディレクトリ名に合わせて実行(エラーで表示されたディレクトリ名を最後のファイル名除いてコピペ)$ sudo chmod 777 /Applications/XAMPP/xamppfiles/htdocs/laravelプロジェクト名/strage/logs
→ 実行これで権限の書き換えができるのでエラーが起きているファイルをリロード。
表示されました!めちゃくちゃスッキリした。。
- 投稿日:2021-01-15T18:12:39+09:00
laravel/uiを利用した際に発生したエラーの解決
現在、Laravel(ver6.20.9)を使って、個人でWebサービスを制作している者です。
Laravel6.xからBootstrapやVueなどがデフォルトでは含まれなくなったそうなので、それらをLaravelで使えるようにしてくれる「laravel/ui」をダウンロードすることにしました。
しかし、その過程で出たエラーに詰まったのでメモしていきたいと思います。
(といっても非常に簡単なことでした。笑)laravel/uiのダウンロード
laravel/uiのダウンロードについては、以下を参考にしました。
laravel/uiの公式ドキュメント
Laravel/UIのインストール(Qiita記事)自分なりに手順をまとめると、
ターミナル①cdコマンドで、laravel/uiを利用したいディレクトリまで移動 ②composer require laravel/ui "1.x" --dev (composer必須) ③php artisan ui bootstrap (Bootstrapを使う場合) php artisan ui vue (Vueを使う場合) php artisan ui react (Reactを使う場合) ④npm install ⑤npm run dev②の"1.x"部分については、以下の表を参考にご自身のLaravelのバージョンに合わせて変えてください。
laravel/uiのバージョン Laravelのバージョン 1.x 5.8、6.x 2.x 7.x 3.x 8.x ④と⑤については、Node.jsのパッケージを管理するNPM(Node Package Manager)を利用しています。
④npm installにより、用意されている便利な機能(パッケージ)をインストールすることができ、⑤でwebpack.mix.jsというファイル内に書いてある指示を実行できるようです。
ここでエラーが…
先ほどの手順④を実行した時に
ターミナル(中略) found 1 high severity vulnerability run `npm audit fix` to fix them, or `npm audit` for detailsん? 何か出てきた。
日本語訳してみると
「1つの重要度の高い脆弱性が見つかりました。
npm audit fix
でこれらを修正してください。また、npm audit
で詳細を確認できます」とのことです。
そこで、指示通り「npm audit fix」を実行すると、
ターミナル% npm audit fix + axios@0.21.1 added 1 package from 3 contributors and updated 1 package in 5.855s 51 packages are looking for funding run `npm fund` for details fixed 1 of 1 vulnerability in 1096 scanned packages無事解決できたようです。
「あ〜よかった」と思ったのも束の間、手順⑤の「npm run dev」を実行したところ…
ターミナルInvalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema. - configuration.context: The provided value "/Users/ユーザー名/Laravel_CRUD/Atsumare!" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax. -> The base directory (absolute path!) for resolving the `entry` option. If `output.pathinfo` is set, the included pathinfo is shortened to this directory. - configuration.module.rules[8].exclude should be one of these: RegExp | string | function | [(recursive)] | object { and?, exclude?, include?, not?, or?, test? } | [RegExp | string | function | [(recursive)] | object { and?, exclude?, include?, not?, or?, test? }] -> One or multiple rule conditions Details: * configuration.module.rules[7].exclude[0]: The provided value "/Users/ユーザー名/Laravel_CRUD/Atsumare!/resources/sass/app.scss" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax. * configuration.module.rules[7].exclude[0]: The provided value "/Users/ユーザー名/Laravel_CRUD/Atsumare!/resources/sass/app.scss" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax. * configuration.module.rules[8].exclude[0]: The provided value "/Users/ユーザー名/Laravel_CRUD/Atsumare!/resources/sass/app.scss" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax. * configuration.module.rules[8].exclude[0]: The provided value "/Users/ユーザー名/Laravel_CRUD/Atsumare!/resources/sass/app.scss" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax. - configuration.output.path: The provided value "/Users/ユーザー名/Laravel_CRUD/Atsumare!/public" contains exclamation mark (!) which is not allowed because it's reserved for loader syntax. -> The output directory as **absolute path** (required). npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! @ development: `cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the @ development script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /Users/ユーザー名/.npm/_logs/2021-01-xxTxx_xx_xx_135Z-debug.log npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! @ dev: `npm run development` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the @ dev script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /Users/ユーザー名/.npm/_logs/2021-01-xxTxx_xx_xx_168Z-debug.logなんか赤い字でいっぱい出てきた!
ここで僕は少し詰まってしまいましたが、ある記事を見つけました。
Shawn Dhaveさんの回答を引用します。
Had the same error. The problem seems to be in the path of your folder. It must not contain an exclamation mark(!). Change folder 'HelloWorld!' to just 'HelloWorld' without the exclamation mark.
Hope this solves the problem.日本語訳すると
「自分も同じエラーを経験したよ。
フォルダーのパスに問題があるように見えるね。フォルダーのパスに感嘆符(!)を含めたらいけないんだ。だから、フォルダー名を『HelloWorld!』じゃなくて、感嘆符のない『HelloWorld』だけに変えてみて。これが解決策になりますように」になります。
ん?
フォルダー名に「!」をつけたらだめ?pwdコマンドで自分のフォルダ名(パス)を確認してみます。
ターミナル/Users/ユーザー名/Laravel_CRUD/Atsumare!つけてんじゃん!!
僕は「Atsumare!(あつまれ!)」という名前で募集掲示板型のサービスを作ろうとしており、それに合わせてフォルダー名も「Atsumare!」にしていたのですが…
どうやらそれがエラーの原因になっていたようです。というわけで、「「Atsumare!」を「Atsumare」に修正しました。
そして⑤の「npm run dev」を実行すると…
ターミナル> @ dev /Users/ユーザー名/Laravel_CRUD/Atsumare > npm run development > @ development /Users/ユーザー名/Laravel_CRUD/Atsumare > cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --config=node_modules/laravel-mix/setup/webpack.config.js DONE Compiled successfully in 7151ms 16:36:11 Asset Size Chunks Chunk Names /css/app.css 178 KiB /js/app [emitted] /js/app /js/app.js 1.08 MiB /js/app [emitted] /js/app無事実行できました!!
教訓
「フォルダー名(ディレクトリ名)に「感嘆符(!)」をつけるのはやめましょう」
という教訓でした?
皆様もお気をつけて!
- 投稿日:2021-01-15T16:58:33+09:00
Laravel8→6系に変えたら色々苦戦した
はじめに
私は現在、PHP/Laravelでポートフォリオ作成をしている学習中の者です。
もし間違っている箇所があればお知らせいただけたら幸いです。ポートフォリオを作成中に、Laravelのバージョン8系では記述の仕方が変わっていたり、(新しいため)情報も少なく、長い目でみて時間ロスが多く発生すると思い、6系に変えてみようと思いました。
開発初期段階だったので、軽い気持ちで変えてみたら色々エラーが出たので記事にしました。
こちらの記事よりDockerの環境構築をさせていただきました。Laravelのバージョンを指定して環境構築するやり方も載っています。
最強のLaravel開発環境をDockerを使って構築する【新編集版】 - QiitaLaravel8に関してはこちらの記事が参考になりました。
Laravel8がリリースされました!新機能の翻訳 | WEBコンサルティング・WEB制作のフリーランス uiuifreeLaravelのバージョンについてはこちらの記事が参考になりました。
Laravelのバージョンのおすすめは?2020年から学び始めるなら - ネビ活 | ネットビジネス生活
Laravel6系に変更後
バージョン変更に関しては割愛します。
プロジェクト内のデータが8系の時のままだと以下のようなエラーが出ます。シーディング実行エラー
ターミナル$ php artisan migrate:fresh --seed //注意してお使いください。 //このコマンドはデータベースの中身を全部クリアにしてからシーディングデータを入れ直すものです。このコマンドでデータベースにデータを入れようとしたところ以下のエラーが発生
エラー内容Illuminate\Contracts\Container\BindingResolutionException : Target class [PostTableSeeder] does not exist.解決法
8系と6系とでは記述が変わっていた為、
seederファイル
を修正database/seeds/PostTableSeeder.php<?php //namespace Database\Seeders;←削除 use Illuminate\Database\Seeder; //use Illuminate\Support\Facades\DB;←削除 class PostsTableSeeder extends Seeder { //~~Modelファイルエラー
$ php artisan serveでlocalhostに繋ぎ確認してみると以下のエラーに
Trait 'Illuminate\Database\Eloquent\Factories\HasFactory' not found解決法
Laravel8ではHttp/Modelディレクトリの配下に入ってましたが、Laravel6ではHttpディレクトリの配下に直接入れるのがデフォルトのようです。
Httpディレクトリ配下に移し空になったModelディレクトリを削除。
Modelファイルを一部書き換えます。app/Http/Post.php<?php //namespace App\Models; //↓以下に修正 namespace App; use Illuminate\Database\Eloquent\Factories\HasFactory;//削除 use Illuminate\Database\Eloquent\Model; class Post extends Model { use HasFactory;//削除Controllerエラー
Controllerファイルも書き換えます。
app/Http/Controllers/PostController.php<?php namespace App\Http\Controllers; //use App\Models\Post; //↓以下に修正 use App\Post; use Illuminate\Http\Request; class PostController extends Controller {Routingエラー
Routingファイルも書き換えます
routes/web.php<?php use Illuminate\Support\Facades\Route; //use App\Http\Controllers\TestController; //削除 //Route::get('/',[PostController::class, 'index']); //↓以下のように修正 Route::get('/', 'PostController@index');
ひとまずこれにて無事に6系での開発が進めらる状態になりました。
特に初学者の方はLaravelで何か作り始める前にバージョンはよく考えて決めましょう(笑)
- 投稿日:2021-01-15T14:53:08+09:00
Laravel/uiのインストールの注意
自分が出会ったエラーと解決法を書いています。
環境
laravel:7.30.2
php:7.4※ php8だとlaravel/uiは使えない
laravel8ならjetstream??使うのがいいのかな?laravel/ui インストールでエラー
composer require laravel/ui
とコマンドを叩いた際に下記のエラーが出た。Installation failed, reverting ./composer.json to its original content.どうやらバージョンの重複が...という感じらしくこれを回避するコマンドを叩かないといけない。
composer require laravel/ui:3.*自分は
composer require laravel/ui:2.*
で動いた。web.phpでのエラー
インストールはできたけどweb.phpで新たなエラーが出ていた。
原因はlaravel/uiをインストールしたときにweb.phpにAuth::routes();
が生成されるが、namespaceの問題みたい。
てことで、use Illuminate\Support\Facades\Auth;
を記述すると解決する。
- 投稿日:2021-01-15T11:07:28+09:00
laravel6 ジョブを使ってみる
目的
- laravel6のジョブを使って非同期処理を体験する
環境
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2 GHz クアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHP バージョン 7.4.11 Homebrewを用いてこちらの方法で導入→Mac HomebrewでPHPをインストールする Laravel バージョン 6.X commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.21 for osx10.15 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 情報
- jobの実行を体験することがメインなので非同期で実行される処理はログ出力のみとする。
- 筆者はMacに直接構築したLaravel環境をもちいて本記事の検証を行った。
- ログの出力は
アプリ名ディレクトリ/storage/logs/laravel.log
に出力されるものとする。- 実行するコマンドは特筆しない限り前のコマンドと同じディレクトリで実行するものとする。
条件
- 下記または
$ laravel new
コマンドを実行してlaravel6のアプリが作成されていること。- 前述のlaravelアプリのローカルサーバを起動しブラウザからページを確認する事ができること。
- 前述のlaravelアプリで
$ php artisan migrate
が実行できること。概要
- ジョブの作成と記載
- ルーティング情報の記載
- 確認
詳細
ジョブの作成と記載
アプリ名ディレクトリで下記コマンドを実行してジョブクラスのファイルを作成する。
$ php artisan make:job OutputLogJob下記コマンドを実行して作成されたジョブクラスのファイルを開く。
$ vi app/Jobs/OutputLogJob.php下記のように処理を追記する。(ジョブとして動作させたい処理はジョブクラスのhandle()メソッド内部に記載する.)
アプリ名ディレクトリ/app/Jobs/OutputLogJob.php<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; // 下記を追記 use Illuminate\Support\Facades\Log; class OutputLogJob implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * Create a new job instance. * * @return void */ public function __construct() { // } /** * Execute the job. * * @return void */ public function handle() { // 下記を追記 Log::info('これはジョブのテストです。'); } }ルーティング情報の記載
下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記のルーティング情報を追記する。
アプリ名ディレクトリ/routes/web.php<?php /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ // 下記を追記 use App\Jobs\OutputLogJob; Route::get('/', function () { return view('welcome'); }); Auth::routes(); Route::get('/home', 'HomeController@index')->name('home'); // 下記を追記 Route::get('/output_log_job', function(){ $job = new OutputLogJob; dispatch($job); return 'ジョブの実行完了'; }); // 上記までを追記確認
下記コマンドを実行してローカルサーバを起動する。
$ php artisan serve下記にアクセスする。
下記のように表示される。
下記コマンドを実行してログファイルを開く。
$ vi storage/logs/laravel.log下記の一文がログに出力されていることを確認する。
アプリ名ディレクトリ/storage/logs/laravel.log[YYYY-MM-DD HH:MM:SS] local.INFO: これはジョブのテストです。
- 投稿日:2021-01-15T11:00:56+09:00
【Laravel】モデル(Model)とは何か?命名規則やマイグレーションとの関連性について
Laravelでよく出てくるモデル(Model)や、マイグレーション、Eloquentの関係性などがわからなかったので調べてみた。
・参考:Laravel公式 Eloquent (Model)
目次
Modelとは?
Databaseのデータを操作する機能のこと。
DBのテーブルに対応するモデルがあり、コントローラでそのモデルを操作するとDBに書き込むデータを指定したりできる。
参考:steemit.comコントローラはユーザーリクエストに基づいてDBデータが必要な場合にモデルに指令を出す。
↓
コントローラからの指令に基づいてDBからデータを抽出 or 保存する。
↓
コントローラは受け取ったデータをビューに渡す。
↓
ユーザーにはビューが描画される。
ModelとDBテーブルの関連付け
DBの各テーブル毎に対応するモデルを作成する。
テーブル名とモデル名の命名規則を守れば、laravelが自動で対応してくれる。▼命名規則
DBのテーブル名は複数形とし、Model名はその単数形とする。・DBのテーブル名: 複数形のスネークケース
・対応するModel名: 冒頭大文字のキャメルケース<例1>
・DBのテーブル名: articles
・対応するModel名: Article<例2>
・DBのテーブル名: maker_codes
・対応するModel名: MakerCode(補足)テーブル名の主な命名規則
DBのテーブル名には命名規則がある。
- 複数形
- スネークケース
- 省略表記しない
テーブル名(例) 判定 articles ○ article × Article × maker_codes ○ MakerCodes × maker_code × mk_code ×
マイグレーションとは?
DBに関連する機能でマイグレーションがある。
マイグレーション(migration)は移行という意味で、ここではDBの構造をLaravelに移行し連動させている。
DB操作ならModelだけあればいいのでは?と思ったので、マイグレーションの役割とモデルとの違いについて。
マイグレーションとモデルの違い
どちらもDBを操作するが、操作対象が異なる。
マイグレーションは、列(カラム)の追加や削除、型の指定を行う。
モデルはDBからデータの取り出し処理を記述する。(Eloquentでクエリを投げる)
▼マイグレーション
- カラムの作成・削除
- 型の指定
- バージョン管理(過去のテーブルの構造がわかる)
- 保存場所: app > Models
- ファイル名はタイムスタンプ & テーブル名
migrationファイルの記述例public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); //idカラム $table->string('name'); //nameカラム $table->string('email')->unique(); //emailカラム $table->timestamps(); //タイムスタンプカラム }); }マイグレーションファイルに追加したいカラムを記述し、マイグレーションを実行すれば、連携するモデルとDBのテーブルにカラムが追加される。
▼モデル
- 取得するデータを指定
- 取得するデータのフォーマットを指定
- 保存場所: app > database > migrations
- ファイル名がテーブルと対応
modelの記述例class User extends Model { $user = User::find(1); // id番号1のユーザー情報を取得 $user->email; // users.email の値を取得 }
Eloquentとは?
LaravelのModelやMigrationなど、DBについて調べていると必ずEloquent(エロクアント)という用語が出てくる。
Eloquentというのは、LaravelでDBを操作するコマンドのこと。
EloquentにはDB操作するためのメソッドが用意されており、それらをモデルやコントローラに記述することでDB操作が実行できる。
▼使い方・
名前空間::Eloquentメソッド名
Eloquentメソッドの例use App\Models\User; //対象のテーブルのモデルのuse宣言 $user = User::all()->toArray();usersテーブルからすべてのデータを抽出し配列化したものを、変数userに格納。
主なEloquentのメソッド
実例はusersテーブル(Userモデル)に対して操作する場合。
use App\Models\User;
メソッド 内容 実例 all() すべてのデータを抽出 $names = User::all() find(int) 指定したid番号のレコードを抽出 $user1 = User::find([10, 20, 30]); get() 結果を取得する $data = User::orderBy('created_at')->get(); where('フィールド名', 条件) 指定したフィールド名のカラムから条件に一致するものを抽出 $data = User::where('id',1)->get() where('フィールド名', '不等号' ,条件) 指定フィールドで条件を満たすものを抽出 $data = User::where('id','>=', 10)->get() toArray() 配列に変換する $arr = User::all()->toArray() findOrFail 条件に一致しない場合、例外処理をする User::findOrFial(1) count() 数を数える $count = User::::where('active', 1)->count(); max('フィールド名') 最大値を取得する $maxNum = User::max('id'); sum('フィールド名') 合計値を取得する $totalPrice = User::sum('price'); 基本的に一般に使えるメソッドは、Eloquentでも使える。
Eloquentでも使えるメソッド一覧
・Laravel公式 Eloquentコレクション
・Laravel公式 Eloquent実例
クエリビルダとは?
LaravelでDBを操作するコードは、Eloquent以外にクエリビルダという方法もある。
▼クエリビルダの使い方
use Illuminate\Support\Facades\DB; $変数名 = DB::table('フィールド名')->メソッド->get();クエリビルダを使うには、DBファサードのtableメソッドを使う。
これはEloquentのuse 名前空間
と同じ。実際、Eloquentはクエリビルダで使えるすべてのメソッドを使用できる。
Eloquentモデルはクエリビルダですから、クエリビルダで使用できる全メソッドを確認しておくべきでしょう。Eloquentクエリでどんなメソッドも使用できます。
- 投稿日:2021-01-15T00:16:14+09:00
Docker for MacでLaravelを速くする方法
皆さんこんにちは。tyamahoriです。Docker for Mac使って開発してますか?遅くてキレ散らかしてませんか。。?
そんなあなたに朗報です。
2021年1月、tyamahoriはDocker for Mac が遅い問題に立ち向かいました。LaravelのサンプルプロジェクトをGitHubにあげておりますので見てください。vendorディレクトリをそのままマウントしない!
composer install したら、vendorディレクトリができます。これをコンテナにマウントするさいに一工夫必要です。
じゃあどうするか?
ローカル開発だと、 docker-composeをほとんどの場合使うと思います。その際には、volumesを使うようにして、Macローカルにファイルを置かないようにします。
落とし穴。。
ただ、ローカルにvendorディレクトリがないと、PhpStormなどで補完が効きません。。いくらスピードが速くなるといえ、補完が聞かないと意味ないですよね。。。?
さらなる一工夫
コンテナ内でcomposerインストールをしたあとに、vendorディレクトリをMacのローカルに持ってきます。
docker cp
のコマンドがあるので、それを使って、コンテナないから、Macローカルにディレクトリをコピーします!細かいところ
じゃあ、いつのタイミングで
docker cp
やるのか? 新しくcomposer install でなにか追加した場合どうするのか。。などなどあります。そういうときは、スクリプトを組んで、色々と試行錯誤をしましょう。サンプルプロジェクトにスクリプトを置いてありますので、参考にしてみてください。我慢するところ
docker cp
でvendorディレクトリをMacローカルに持ってきたら、PhpStormはvendorディレクトリを読み込みます。その際にMacのファンがブンブン回るので、そこだけは我慢する必要があります。。結論
本当に速くなるかはまず試してもらえればと思います。サンプルプロジェクトをクローンして、Docker for Macを使って、立ち上げて見てください!皆様のご感想お待ちしております!
GitHubでのプロジェクト