Memo

メモ > 技術 > フレームワーク: Laravel9 > データベースを扱う

データベースを扱う
■データベースの作成
$ sail mysql mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | laravel9 | | testing | +--------------------+ 3 rows in set (0.00 sec) mysql> USE laravel9; mysql> SHOW TABLES; Empty set (0.00 sec)
もともとデータベース「laravel9」が作成済みになっているので、これをそのまま利用する ■テーブルの作成 マイグレーションを作成
$ sail artisan make:migration create_articles_table
以下のファイルが作成される database/migrations/2024_04_02_101902_create_articles_table.php
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('articles', function (Blueprint $table) { $table->id(); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('articles'); } };
以下のとおり、マイグレーションを修正する(titleとcontentを追加する)
Schema::create('articles', function (Blueprint $table) { $table->id(); $table->timestamps(); }); ↓ Schema::create('articles', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('content'); $table->timestamps(); });
マイグレーションを実行する
$ sail artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (57.38ms) Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table (46.95ms) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (50.15ms) Migrating: 2019_12_14_000001_create_personal_access_tokens_table Migrated: 2019_12_14_000001_create_personal_access_tokens_table (69.67ms) Migrating: 2024_04_02_101902_create_articles_table Migrated: 2024_04_02_101902_create_articles_table (25.10ms)
テーブルの作成を確認できる
$ sail mysql mysql> USE laravel9; mysql> SHOW TABLES; +------------------------+ | Tables_in_laravel9 | +------------------------+ | articles | | failed_jobs | | migrations | | password_resets | | personal_access_tokens | | users | +------------------------+ 6 rows in set (0.00 sec) mysql> SHOW COLUMNS FROM articles; +------------+-----------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-----------------+------+-----+---------+----------------+ | id | bigint unsigned | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | content | text | NO | | NULL | | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | +------------+-----------------+------+-----+---------+----------------+ 5 rows in set (0.01 sec)
■データの作成 シーダーを作成
$ sail artisan make:seeder ArticlesSeeder
以下のファイルが作成される database/seeders/ArticlesSeeder.php
<?php namespace Database\Seeders; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; class ArticlesSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // } }
以下のとおり編集する
<?php namespace Database\Seeders; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; class ArticlesSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table('articles')->insert([ 'title' => Str::random(20), 'content' => Str::random(200), 'created_at' => now(), 'updated_at' => null, ]); } }
以下のファイルを編集して、シーダーを呼び出す database/seeders/DatabaseSeeder.php
// \App\Models\User::factory(10)->create(); $this->call([ArticlesSeeder::class]);
シーダーを実行する
$ sail artisan db:seed Seeding: Database\Seeders\ArticlesSeeder Seeded: Database\Seeders\ArticlesSeeder (15.77ms) Database seeding completed successfully.
データの登録を確認できる
$ sail mysql mysql> USE laravel9; mysql> SELECT id, title FROM articles; +----+----------------------+ | id | title | +----+----------------------+ | 1 | bhkWrdUVSauoQh9h5lcX | +----+----------------------+ 1 row in set (0.00 sec)
確認できたら、いったんデータは削除しておく
mysql> TRUNCATE TABLE articles;
■モデルの作成 モデルを作成
$ sail artisan make:model Article
以下のファイルが作成される app/Models/Article.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Article extends Model { use HasFactory; }
■ファクトリーの作成 ファクトリーを作成
$ sail artisan make:factory ArticleFactory --model=Article
以下のファイルが作成される database/factories/ArticleFactory.php
<?php namespace Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Article> */ class ArticleFactory extends Factory { /** * Define the model's default state. * * @return array<string, mixed> */ public function definition() { return [ // ]; } }
以下のとおり編集する
<?php namespace Database\Factories; use Illuminate\Database\Eloquent\Factories\Factory; /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Article> */ class ArticleFactory extends Factory { /** * Define the model's default state. * * @return array<string, mixed> */ public function definition() { return [ 'title' => $this->faker->realText(20), 'content' => $this->faker->realText(200), 'created_at' => now(), 'updated_at' => null, //'created_at' => $this->faker->datetime($max = 'now', $timezone = date_default_timezone_get()), //'updated_at' => $this->faker->datetime($max = 'now', $timezone = date_default_timezone_get()), ]; } }
日本語の設定に変更する config/app.php
'faker_locale' => 'en_US', ↓ 'faker_locale' => 'ja_JP',
以下のファイルを編集する database/seeders/ArticlesSeeder.php
<?php namespace Database\Seeders; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; //use Illuminate\Support\Facades\DB; //use Illuminate\Support\Str; use App\Models\Article; class ArticlesSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { //DB::table('articles')->insert([ // 'title' => Str::random(20), // 'content' => Str::random(200), // 'created_at' => now(), // 'updated_at' => null, //]); Article::factory()->count(10)->create(); } }
シーダーを実行する
$ sail artisan db:seed Seeding: Database\Seeders\ArticlesSeeder Seeded: Database\Seeders\ArticlesSeeder (171.08ms) Database seeding completed successfully.
データの登録を確認できる
$ sail mysql mysql> USE laravel9; mysql> SELECT id, title, created_at, updated_at FROM articles; +----+--------------------------------------------------------------+---------------------+------------+ | id | title | created_at | updated_at | +----+--------------------------------------------------------------+---------------------+------------+ | 1 | かけにはないのが、ぱっと窓まどから私の。 | 2024-04-03 10:48:49 | NULL | | 2 | かたあとだと思い出していると包つつまし。 | 2024-04-03 10:48:49 | NULL | | 3 | のあるい実みもらだの今だってそのいらっ。 | 2024-04-03 10:48:49 | NULL | | 4 | 覆ひおおきく天井てんじゅうに、一足さき。 | 2024-04-03 10:48:49 | NULL | | 5 | ドをかすが少しおずおずしない水に落おと。 | 2024-04-03 10:48:49 | NULL | | 6 | れたまって、まあ、すすんで、そのまって。 | 2024-04-03 10:48:49 | NULL | | 7 | まにもついているんです」「お母さんも眼。 | 2024-04-03 10:48:49 | NULL | | 8 | といつかまわりにいっぱんの方で、黒い洋。 | 2024-04-03 10:48:49 | NULL | | 9 | ついてあらまあ、切符きっとみちがすと喧。 | 2024-04-03 10:48:49 | NULL | | 10 | いせいよ光っていました。「ああ、孔雀く。 | 2024-04-03 10:48:49 | NULL | +----+--------------------------------------------------------------+---------------------+------------+ 10 rows in set (0.00 sec)
■記事の表示 以下のとおり編集する app/Http/Controllers/Article/IndexController.php
<?php namespace App\Http\Controllers\Article; use App\Http\Controllers\Controller; use App\Models\Article; use Illuminate\Http\Request; class IndexController extends Controller { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function __invoke(Request $request) { $articles = Article::all(); return view('article.index', [ 'articles' => $articles, ]); } }
resources/views/article/index.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Article</title> </head> <body> <h1>Article</h1> <ul> @foreach ($articles as $article) <li>{{ $article->id }} / {{ $article->title }}</li> @endforeach </ul> </body> </html>
以下にアクセスして表示を確認する http://laravel.local/article/ ■記事の投稿 リクエストを作成
$ sail artisan make:request Article/CreateRequest
以下のファイルが作成される app/Http/Requests/Article/CreateRequest.php
<?php namespace App\Http\Requests\Article; use Illuminate\Foundation\Http\FormRequest; class CreateRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return false; } /** * Get the validation rules that apply to the request. * * @return array<string, mixed> */ public function rules() { return [ // ]; } }
以下のとおり編集する
<?php namespace App\Http\Requests\Article; use Illuminate\Foundation\Http\FormRequest; class CreateRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array<string, mixed> */ public function rules() { return [ 'title' => 'required|max:20', 'content' => 'required|max:200', ]; } }
コントローラーを作成
$ sail artisan make:controller Article/CreateController --invokable
以下のファイルが作成される app/Http/Controllers/Article/CreateController.php
<?php namespace App\Http\Controllers\Article; use App\Http\Controllers\Controller; use Illuminate\Http\Request; class CreateController extends Controller { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function __invoke(Request $request) { // } }
以下のとおり編集する
<?php namespace App\Http\Controllers\Article; use App\Http\Controllers\Controller; use App\Models\Article; use App\Http\Requests\Article\CreateRequest; class CreateController extends Controller { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function __invoke(CreateRequest $request) { $article = new Article; $article->title = $request->title; $article->content = $request->content; $article->save(); return redirect()->route('article.index')->with('message', '投稿しました。'); } }
routes/web.php
Route::get('/article', \App\Http\Controllers\Article\IndexController::class); ↓ Route::get('/article', \App\Http\Controllers\Article\IndexController::class)->name('article.index'); Route::post('/article/create', \App\Http\Controllers\Article\CreateController::class)->name('article.create');
resources/views/article/index.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Article</title> </head> <body> <h1>Article</h1> @if (session('message')) <p>{{ session('message') }}</p> @endif <form action="{{ route('article.create') }}" method="post"> @csrf <dl> <dt>タイトル</dt> <dd> <input type="text" name="title" value="{{ old('title', isset($article) ? $article->title : '') }}"> @error('title') <p>{{ $message }}</p> @enderror </dd> <dt>本文</dt> <dd> <textarea name="content" rows="5" cols="50">{{ old('content', isset($article) ? $article->content : '') }}</textarea> @error('content') <p>{{ $message }}</p> @enderror </dd> </dl> <p><button type="submit">投稿</button></p> </form> <ul> @foreach ($articles as $article) <li>{{ $article->id }} / {{ $article->title }}</li> @endforeach </ul> </body> </html>
config/app.php
'locale' => 'en', 'fallback_locale' => 'en', ↓ 'locale' => 'ja', 'fallback_locale' => 'ja',
$ sail composer require laravel-lang/lang:~10.3 $ cp -R vendor/laravel-lang/lang/locales/ja lang/ja
lang/ja/validation.php
], 'attributes' => [ 'title' => 'タイトル', 'content' => '本文', ], ];
以下にアクセスして表示を確認する http://laravel.local/article/ ■記事の編集 ※コントローラーを Update 内に置くか否かは考えたい ※登録処理も含めて、この時点では authorize() を false にしておく方が自然か。検証したい ファイルを作成
$ sail artisan make:request Article/UpdateRequest $ sail artisan make:controller Article/EditController --invokable $ sail artisan make:controller Article/UpdateController --invokable
以下のとおり編集する app/Http/Requests/Article/UpdateRequest.php (変更箇所は CreateRequest.php と同じ)
<?php namespace App\Http\Requests\Article; use Illuminate\Foundation\Http\FormRequest; class UpdateRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array<string, mixed> */ public function rules() { return [ 'title' => 'required|max:20', 'content' => 'required|max:200', ]; } }
app/Http/Controllers/Article/EditController.php
<?php namespace App\Http\Controllers\Article; use App\Http\Controllers\Controller; use App\Models\Article; use Illuminate\Http\Request; class EditController extends Controller { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function __invoke(Request $request) { $id = (int) $request->route('id'); $article = Article::where('id', $id)->firstOrFail(); return view('article.edit', [ 'article' => $article, ]); } }
app/Http/Controllers/Article/UpdateController.php
<?php namespace App\Http\Controllers\Article; use App\Http\Controllers\Controller; use App\Models\Article; use Illuminate\Http\Request; class UpdateController extends Controller { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function __invoke(Request $request) { $article = Article::where('id', $request->id)->firstOrFail(); $article->title = $request->title; $article->content = $request->content; $article->save(); return redirect()->route('article.edit', ['id' => $request->id])->with('message', '編集しました。'); } }
resources/views/article/edit.blade.php
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Article</title> </head> <body> <h1>Article</h1> <p><a href="{{ route('article.index') }}">戻る</a></p> @if (session('message')) <p>{{ session('message') }}</p> @endif <form action="{{ route('article.update', ['id' => $article->id]) }}" method="post"> @method('PUT') @csrf <dl> <dt>タイトル</dt> <dd> <input type="text" name="title" value="{{ old('title', isset($article) ? $article->title : '') }}"> @error('title') <p>{{ $message }}</p> @enderror </dd> <dt>本文</dt> <dd> <textarea name="content" rows="5" cols="50">{{ old('content', isset($article) ? $article->content : '') }}</textarea> @error('content') <p>{{ $message }}</p> @enderror </dd> </dl> <p><button type="submit">編集</button></p> </form> </body> </html>
resources/views/article/index.blade.php
<li>{{ $article->id }} / {{ $article->title }}</li> ↓ <li>{{ $article->id }} / {{ $article->title }} <a href="{{ route('article.edit', ['id' => $article->id]) }}">編集</a></li>
routes/web.php
Route::get('/article/edit/{id}', \App\Http\Controllers\Article\EditController::class)->name('article.edit')->where('id', '[0-9]+'); Route::put('/article/update/{id}', \App\Http\Controllers\Article\UpdateController::class)->name('article.update')->where('id', '[0-9]+');
以下にアクセスして表示を確認する http://laravel.local/article/ ■記事の削除 ファイルを作成
$ sail artisan make:controller Article/DeleteController --invokable
以下のとおり編集する app/Http/Controllers/Article/DeleteController.php
<?php namespace App\Http\Controllers\Article; use App\Http\Controllers\Controller; use App\Models\Article; use Illuminate\Http\Request; class DeleteController extends Controller { /** * Handle the incoming request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function __invoke(Request $request) { $id = (int) $request->route('id'); $article = Article::where('id', $id)->firstOrFail(); $article->delete(); return redirect()->route('article.index')->with('message', '削除しました。'); } }
resources/views/article/edit.blade.php
<form action="{{ route('article.delete', ['id' => $article->id]) }}" method="post"> @method('DELETE') @csrf <p><button type="submit">削除</button></p> </form>
routes/web.php
Route::delete('/article/delete/{id}', \App\Http\Controllers\Article\DeleteController::class)->name('article.delete');

Advertisement