❓ これは何
ソフトウェアを構築するには、様々な設計モデルがあります。
今回はバックエンドの開発で基礎的で代表的なMVCモデルを少しわかったつもりになるために、
簡単なメモアプリを作ります。
この記事では Laravel を使っています。
まだ Hello World ができていない方は、先に済ませておきましょう。
M1 mac でLaravel のHelloWorldする方法
このページでの🐏はコラムです。読み飛ばしてOKです。
今回完成すると次のようなものになります。
この記事ではスタイリングなどの解説はしていません。
1時間内でとりあえず作ることを目標にしています。
🪴 環境
この記事では Apple Silicon に合わせた書き方になっている箇所があります。(Docker関係)
ご注意ください。
- Apple m1 MacBook Air
- 14.5(23F79)
🔧 やり方
MVC(Model-View-Controller)は、ソフトウェア設計の基本原則の一つです。
アプリケーションの構造を
- Model
- View
- Controller
の3つの部分に分けることで、保守性と可読性を向上させます。
🐳 初期設定
ここではApple m1 での設定となっています。
主にDockerに関する操作についてです。
docker-compose.yml は次のようにしました。
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: laravel-app
container_name: laravel-app
restart: unless-stopped
working_dir: /var/www
volumes:
- .:/var/www
networks:
- laravel
environment:
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=your_database_name
- DB_USERNAME=your_database_user
- DB_PASSWORD=your_database_password
webserver:
image: arm64v8/nginx:alpine
container_name: webserver
restart: unless-stopped
ports:
- "8000:80"
volumes:
- .:/var/www
- ./nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- laravel
db:
image: arm64v8/mariadb:10.5
container_name: db
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=your_database_name
- MYSQL_USER=your_database_user
- MYSQL_PASSWORD=your_database_password
volumes:
- dbdata:/var/lib/mysql
ports:
- "3306:3306"
networks:
- laravel
volumes:
dbdata:
networks:
laravel:
driver: bridge
.env ファイルに次のコードを追記します。
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=your_database_name
DB_USERNAME=your_database_user
DB_PASSWORD=your_database_password
コンテナを起動し、コンテナにアクセスします。
docker-compose up -d
docker-compose exec app bash
migrate したら exit します。
php artisan migrate
マイグレーションファイルの作成
Laravelでは、マイグレーションファイルを使ってデータベーススキーマ(スキーマとは簡単にいうと構造のこと)の変更を定義します。
マイグレーションファイルは、PHPコードでデータベースのテーブルやカラムの追加、削除、変更を記述します。
database/migrationsディレクトリに新しいマイグレーションファイルを生成します。
notes というテーブルが作成されます。
実行後、database/migrations/ホゲホゲcreate_notes_table.php というファイルが作成されていると思います。(ホゲホゲには日付などが入っているはず)
php artisan make:migration create_notes_table --create=notes
🐏 php artisan とは?
- command: 実行するコマンド(例: make:migration, serve, migrateなど)
- options: オプションとして指定するもの(例: –force, –quietなど)
- arguments: コマンドに渡す引数(例: マイグレーションの名前など)
php artisan [command] [options] [arguments]
create_notes_table.php
function up()の中身を次のように追記します。
upメソッド
マイグレーションを適用する際に実行されます。
例では、notesテーブルを作成し、
id, title, content, timestamps
のカラムを定義しています。
downメソッド
マイグレーションをロールバックする際に実行されます。
例では、notesテーブルを削除しています。
ロールバックとはデータベースのマイグレーションを元に戻す操作を指します。具体的には、適用されたマイグレーションを取り消し、以前の状態に戻すことです。
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('notes', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('notes');
}
};
マイグレーションを実行します。
このコマンドで上記コードのupが実行されることになります。。
php artisan migrate
📦 MODEL
メモモデルの作成
モデルはデータベースとのやり取りや、データの検証の実装を担当します。
メモアプリケーションでは、Noteモデルがこれに該当します。Noteモデルはメモのデータ(タイトルと内容)を管理します
メモモデルの作成
php artisan make:model Note
modelsの中の Note.php に次のコードを記述します。
use HasFactory;
Laravelのファクトリ機能を使用します。
protected $fillable = [‘title’, ‘content’];:
マスアサインメントを許可する属性を指定します。
マスアサインメント(Mass Assignment)とは、配列やオブジェクトからモデルの複数の属性に一括で値を割り当てることです。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Note extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'title',
'content',
];
}
🐏 use HasFactory; とは?
ファクトリは、テストデータを作成するクラスである
Factoryを使用して、データベーステーブルにランダムなデータを生成する機能です。
🎮 CONTROLLER
controller の作成
コントローラーはユーザーの入力に応じてモデルとビューを調整します。
リクエストを受け取り、適切なモデルとビューを呼び出してレスポンスを返します。
メモアプリケーションでは、NoteControllerがコントローラーに該当します。
NoteControllerはメモの作成、表示、編集、削除のロジックを担当します。
メモコントローラの作成
php artisan make:controller NoteController --resource
app/Http/Controllers/NoteController.php に次のコードを追加します。
各メソッドは、特定のアクション(一覧表示、作成、保存、表示、編集、更新、削除)を担当します。
リクエストを処理し、適切なビューを返します。
$request->validate([
'title' => 'required', // タイトルは必須
'content' => 'required', // 内容も必須
]);
こういった書き方で、バリデーションを実装できます。
<?php
namespace App\Http\Controllers;
use App\Models\Note;
use Illuminate\Http\Request;
class NoteController extends Controller
{
// メモの一覧を表示するメソッド
public function index()
{
// データベースからすべてのメモを取得
$notes = Note::all();
// 'notes.index'ビューを表示し、取得したメモをビューに渡す
return view('notes.index', compact('notes'));
}
// 新しいメモを作成するフォームを表示するメソッド
public function create()
{
// 'notes.create'ビューを表示
return view('notes.create');
}
// 新しいメモを保存するメソッド
public function store(Request $request)
{
// リクエストデータをバリデート
$request->validate([
'title' => 'required', // タイトルは必須
'content' => 'required', // 内容も必須
]);
// リクエストデータを使って新しいメモを作成
Note::create($request->all());
// メモの一覧ページにリダイレクトし、成功メッセージを表示
return redirect()->route('notes.index')
->with('success', 'Note created successfully.');
}
// 特定のメモを表示するメソッド
public function show(Note $note)
{
// 'notes.show'ビューを表示し、特定のメモをビューに渡す
return view('notes.show', compact('note'));
}
// 特定のメモを編集するフォームを表示するメソッド
public function edit(Note $note)
{
// 'notes.edit'ビューを表示し、特定のメモをビューに渡す
return view('notes.edit', compact('note'));
}
// 特定のメモを更新するメソッド
public function update(Request $request, Note $note)
{
// リクエストデータをバリデート
$request->validate([
'title' => 'required', // タイトルは必須
'content' => 'required', // 内容も必須
]);
// 特定のメモを更新
$note->update($request->all());
// メモの一覧ページにリダイレクトし、成功メッセージを表示
return redirect()->route('notes.index')
->with('success', 'Note updated successfully');
}
// 特定のメモを削除するメソッド
public function destroy(Note $note)
{
// 特定のメモを削除
$note->delete();
// メモの一覧ページにリダイレクトし、成功メッセージを表示
return redirect()->route('notes.index')
->with('success', 'Note deleted successfully');
}
}
ルートの設定
ルートの設定
routes/web.php に次のコードを追記します。
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\NoteController;
Route::get('/', [NoteController::class, 'index']);
Route::resource('notes', NoteController::class);
👁️ VIEW
Viewの作成
ビューはユーザーインターフェースを表示します。
データの表示やユーザーの入力を受け付けます。
メモアプリケーションでは、index.blade.php、create.blade.php、edit.blade.php、show.blade.phpがビューに該当します。
これらのビューは、メモのリスト表示、作成フォーム、編集フォーム、詳細表示を担当します。
まずは resources/views に layout.blade.php を作ります。
共通レイアウトを定義し、各ビューで使用します。
ヘッダーやフッターなど、どのページでも使うものもここに書いておくと、このファイルの役割がわかりやすいでしょう。
<!DOCTYPE html>
<html>
<head>
<title>Memo App</title>
</head>
<body>
@yield('content')
</body>
</html>
Resources/views フォルダに notes というディレクトリを作り、下記ファイルを作成します。
- index.blade.php
- create.blade.php
- edit.blade.php
- show.blade.php
index.blade.php
メモの一覧を表示し、各メモに対して詳細表示、編集、削除のリンクがあります。
@extends('layout')
@section('content')
<h1>Notes</h1>
<a href="{{ route('notes.create') }}">Create a new note</a>
<ul>
@foreach ($notes as $note)
<li>
<a href="{{ route('notes.show', $note->id) }}">{{ $note->title }}</a>
<a href="{{ route('notes.edit', $note->id) }}">Edit</a>
<form action="{{ route('notes.destroy', $note->id) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit">Delete</button>
</form>
</li>
@endforeach
</ul>
@endsection
🐏 hoge.blade.php とは?
hoge.blade.php とかくと、Laravelが提供するテンプレートエンジンの「Blade」が使用できます。
BladeはPHPのテンプレートエンジンで、HTML, PHP をより見やすく、書きやすくすることが出来ます。
- @extends(‘layout’)は、layout.blade.phpを継承することを示しています。
- @section(‘content’)と@endsectionの間に、レイアウトに挿入するコンテンツを記述します。
- @foreachループを使って、$notesコレクションの各メモを表示します。
- @csrfはCSRFトークンを生成し、フォームの送信を保護します。
- @method(‘DELETE’)はHTMLフォームでDELETEメソッドを使うためのBladeディレクティブです。
🐏 CSRFトークンとは?
CSRF(Cross-Site Request Forgery、クロスサイトリクエストフォージェリ)は、
ユーザーが意図しないリクエストをWebアプリケーションに送信する攻撃です。
CSRFトークンは、この攻撃を防ぐために使用されるセキュリティ機構です。
基本的にPOSTの時には @csrf と書いておけばいいでしょう()
create.blade.php
メモの作成フォームです。
@extends('layout')
@section('content')
<h1>Create Note</h1>
<form action="{{ route('notes.store') }}" method="POST">
@csrf
<label>Title:</label>
<input type="text" name="title">
<label>Content:</label>
<textarea name="content"></textarea>
<button type="submit">Create</button>
</form>
@endsection
edit.blade.php
メモの編集フォームです。
@extends('layout')
@section('content')
<h1>Edit Note</h1>
<form action="{{ route('notes.update', $note->id) }}" method="POST">
@csrf
@method('PUT')
<label>Title:</label>
<input type="text" name="title" value="{{ $note->title }}">
<label>Content:</label>
<textarea name="content">{{ $note->content }}</textarea>
<button type="submit">Update</button>
</form>
@endsection
show.blade.php
メモの詳細画面です。
@extends('layout')
@section('content')
<h1>{{ $note->title }}</h1>
<p>{{ $note->content }}</p>
<a href="{{ route('notes.index') }}">Back to Notes</a>
@endsection
これで完成です!
実行し、確認してみましょう。
コメントを残す