LaravelでCRUDするのにやったこと
Laravelを使うための環境設定は別の記事で紹介します。
今回はXampp環境で最小構成のTodoを作成しました。
作成・修正を行ったファイルとその意味について整理します。
フォルダが多くてきついと思っていた!
一通り作ると結構すくないもんなんだな。
使用ファイル
- マイグレーションファイル
- フロント用bladeファイル
- コントローラファイル
- ルーティングファイル:web.php
- modelファイル
- 使う人には.env
マイグレーション:DBテーブルの作成
マイグレーションは、アプリフォルダ内にDBの構成を記録しておくファイルです。
xamppの環境下であればphp artisan migrateコマンドを打てば、DBが自動で作成されるため便利です。
今回は、テーブル名のposts、カラム名(id,title,content,timestamp)のDBを作成します。
database\migrationsフォルダの中にあるよ。
<?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('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('posts');
}
};
尚、マイグレーションがうまくいかないときは、.envファイルをいじるよ!
以下参考まで。
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:********************************************
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_DATABASE=laravel_posting_app
DB_USERNAME=root
DB_PASSWORD=
bladeファイル:MVCのV(View)Laravelで使うhtmlはこのファイルに書き込みます。
hoge.blade.phpのように、ファイル名と拡張子の間にbladeという文字が挟まれます。
@foreachや@if等の制御文が書け、マスタッシュ構文{{}}にてDBの中身を出力したりできます。
resources\views\postsフォルダの中にあるよ!
Todoのいいところは大体のアプリの材料になるよ!
フロントのここら辺をいじれば、chatにも掲示板にもなるよ!
@foreach($posts as $post)
<div>
<div>
<h2>{{ $post->title }}</h2>
<p>{{ $post->content }}</p>
<div>
<a href="{{ route('posts.show', $post) }}">詳細</a>
<a href="{{ route('posts.edit', $post) }}">編集</a>
<form action="{{ route('posts.destroy', $post) }}" method="post">
@csrf
@method('delete')
<button type="submit">削除</button>
</form>
</div>
</div>
</div>
@endforeach
index.blade.php:初期表示画面
`
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>投稿一覧</title>
</head>
<body>
<header>
<nav>
<div>
</div>
</nav>
</header>
<a href="{{ route('posts.index') }}">投稿アプリ</a>
<main>
<article>
<div>
<h1>投稿一覧</h1>
@if (session('flash_message'))
<p>{{ session('flash_message') }}</p>
@endif
<div>
<a href="{{ route('posts.create') }}">新規投稿</a>
</div>
@foreach($posts as $post)
<div>
<div>
<h2>{{ $post->title }}</h2>
<p>{{ $post->content }}</p>
<div>
<a href="{{ route('posts.show', $post) }}">詳細</a>
<a href="{{ route('posts.edit', $post) }}">編集</a>
<form action="{{ route('posts.destroy', $post) }}" method="post">
@csrf
@method('delete')
<button type="submit">削除</button>
</form>
</div>
</div>
</div>
@endforeach
</div>
</article>
</main>
<footer>
<p>© 投稿アプリ All rights reserved.</p>
</footer>
</body>
</html>
create.blade.php:新規投稿画面
`
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新規投稿</title>
</head>
<body>
<header>
<nav>
<div>
<a href="{{ route('posts.index') }}">投稿アプリ</a>
</div>
</nav>
</header>
<main>
<article>
<div>
<h1>新規投稿</h1>
@if ($errors->any())
<div>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div>
<a href="{{ route('posts.index') }}">< 戻る</a>
</div>
<form action="{{ route('posts.store') }}" method="post">
@csrf
<div>
<label for="title">タイトル</label>
<input type="text" name="title" value="{{ old('title') }}">
</div>
<div>
<label for="content">本文</label>
<textarea name="content">{{ old('content') }}</textarea>
</div>
<button type="submit">投稿</button>
</form>
</div>
</article>
</main>
<footer>
<p>© 投稿アプリ All rights reserved.</p>
</footer>
</body>
</html>
edit.blade.php:投稿編集画面
`
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>投稿編集</title>
</head>
<body>
<header>
<nav>
<div>
<a href="{{ route('posts.index') }}">投稿アプリ</a>
</div>
</nav>
</header>
<main>
<article>
<div>
<h1>投稿編集</h1>
@if ($errors->any())
<div>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div>
<a href="{{ route('posts.index') }}">< 戻る</a>
</div>
<form action="{{ route('posts.update', $post) }}" method="post">
@csrf
@method('patch')
<div>
<label for="title">タイトル</label>
<input type="text" name="title" value="{{ $post->title }}">
</div>
<div>
<label for="content">本文</label>
<textarea name="content">{{ $post->content }}</textarea>
</div>
<button type="submit">更新</button>
</form>
</div>
</article>
</main>
<footer>
<p>© 投稿アプリ All rights reserved.</p>
</footer>
</body>
</html>
show.blade.php:詳細画面表示
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>投稿詳細</title>
</head>
<body>
<header>
<nav>
<div>
<a href="{{ route('posts.index') }}">投稿アプリ</a>
</div>
</nav>
</header>
<main>
<article>
<div>
<h1>投稿詳細</h1>
@if (session('flash_message'))
<p>{{ session('flash_message') }}</p>
@endif
<div>
<a href="{{ route('posts.index') }}">< 戻る</a>
</div>
<div>
<div>
<h2>{{ $post->title }}</h2>
<p>{{ $post->content }}</p>
</div>
<div>
<a href="{{ route('posts.edit', $post) }}">編集</a>
<form action="{{ route('posts.destroy', $post) }}" method="post">
//↓クロスサイトリクエストフォージェリ対策
@csrf
@method('delete')
<button type="submit">削除</button>
</form>
</div>
</div>
</div>
</article>
</main>
<footer>
<p>© 投稿アプリ All rights reserved.</p>
</footer>
</body>
</html>
コントローラ:MVCのC!VとMを制御するよ!
php artisan make:controller コントローラ名 で生成する。
コントローラ名は、やり取りするモデルに合わせて名前を変えるのが一般的。
今回は、postモデルとやり取りするので、Postcontrollerとする。
app/Http/Controllersフォルダの中にあるよ!
`<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
class PostController extends Controller {
// 一覧ページ
public function index() {
$posts = Post::latest()->get();
return view('posts.index', compact('posts'));
}
// 作成ページ
public function create() {
return view('posts.create');
}
// 作成機能
// 作成機能
public function store(Request $request) {
$request->validate([
'title' => 'required',
'content' => 'required',
]);
$post = new Post();
$post->title = $request->input('title');
$post->content = $request->input('content');
$post->save();
return redirect()->route('posts.index')->with('flash_message', '投稿が完了しました。');
}
// 詳細ページ
public function show(Post $post) {
return view('posts.show', compact('post'));
}
//更新
public function edit(Post $post) {
return view('posts.edit', compact('post'));
}
// 更新機能
public function update(Request $request, Post $post) {
$post->title = $request->input('title');
$post->content = $request->input('content');
$post->save();
return redirect()->route('posts.show', $post)->with('flash_message', '投稿を編集しました。');
}
// 削除機能
public function destroy(Post $post) {
$post->delete();
return redirect()->route('posts.index')->with('flash_message', '投稿を削除しました。');
}
}
ルーティング:経路制御をするよ!
「このURLにアクセスしたときは○○コントローラの□□アクションを実行する」のように、ユーザーからのリクエストに応じてコントローラを選択する役割を担う。
routes\web.phpに記述するよ!
基本コードは
`Route::HTTPリクエストメソッド名('URL', [コントローラ名::class, 'アクション名']);
//例えばPostコントローラのindexアクションであれば
Route::get('/posts', [PostController::class, 'index']);
設定する際に以下のようにname()メソッドを使うことで、そのルートに名前を付けられる
`
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
ルートに名前を設定すると、bladeファイルにて、route()ヘルパーを使うことで簡易に呼び出すことができる。
`<!-- 通常のリンク -->
<a href="/posts">投稿アプリ</a>
<!-- 名前付きルート -->
<a href="{{ route('posts.index') }}">投稿アプリ</a>
また、use宣言でルーティングを設定するコントローラを宣言するを忘れないこと!
`// ルーティングを設定するコントローラを宣言する
use App\Http\Controllers\PostController;
ルーティングの中身
`web.php
<?php
use Illuminate\Support\Facades\Route;
// ルーティングを設定するコントローラを宣言する
use App\Http\Controllers\PostController;
Route::get('/', function () {
return view('welcome');
});
/// 投稿の一覧ページ
Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
// 投稿の作成ページ
Route::get('/posts/create', [PostController::class, 'create'])->name('posts.create');
// 投稿の作成機能
Route::post('/posts', [PostController::class, 'store'])->name('posts.store');
// 投稿の詳細ページ
Route::get('/posts/{post}', [PostController::class, 'show'])->name('posts.show');
// 投稿の更新ページ
Route::get('/posts/{post}/edit', [PostController::class, 'edit'])->name('posts.edit');
// 投稿の更新機能
Route::patch('/posts/{post}', [PostController::class, 'update'])->name('posts.update');
// 投稿の削除機能
Route::delete('/posts/{post}', [PostController::class, 'destroy'])->name('posts.destroy');
モデルの作成:データベースとやりとりしてデータの作成、読み取り、更新、削除といった処理を行う
php artisan make:model モデル名というコマンドを打つと、
app/Models
のフォルダの中に生成されるよ。
モデル名は必ずテーブル名の単数形にすること。(今回:posts⇒post)
そうすると不思議機能でDBとやり取りしてくれる。
DBの数だけモデルがいるよ!
びっくりするくらい記述が少ないけどなぜか動くよ!
`post.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
}
一応これで最小構成のTodoアプリが作れるはず?
お好みで、BootStrapで成形してやってね!