coiai Logo

MVC とは?を理解するために簡単なアプリをつくる with Laravel

❓ これは何

ソフトウェアを構築するには、様々な設計モデルがあります。

今回はバックエンドの開発で基礎的で代表的な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

これで完成です!
実行し、確認してみましょう。

この記事をシェア

投稿日: 2024年7月16日
カテゴリ: Laravel, おすすめ
タグ: プログラミング
coiai

coiai

この記事もおすすめ

デフォルトサムネイル

【WSL入門】Ubuntu on WSL2 に開発ツールを一式そろえる — Git / nvm / pnpm / AWS CLI / Terraform

前回の記事では、Windows に WSL2 を導入して Ubuntu が動くところまでを扱いました。ただ、素の Ubuntu はあくまで「まっさらな Linux」です。ここから実際に開発を始めるには、バージョン管理・ランタイム・クラウド操作のツールを自分で入れていく必要があります。 この記事では、すべて公式ドキュメントに載っている手順だけを使って、次のツールを順番にセットアップします。 各セクションの末尾に出典 URL を置いてあるので、手順が古くなったと感じたらそこを見に行ってください。記事末尾には出典一覧もまとめています。 検証環境Windows 11 / WSL2 / Ubuntu 24.04 LTS(x86_64)確認日:2026年7月28日 バージョン番号は執筆時点のものです。インストールコマンド自体は基本的に「常に最新を取ってくる」形になっているので、そのまま実行して問題ありません。 はじめに:WSL開発の大原則 コマンドに入る前に、ひとつだけ。Microsoft の公式ドキュメントが繰り返し書いている重要な原則があります。 使う予定のツールと同じ OS 側にファイルを置く。Linux ツールで Linux コマンドラインから作業しているなら、最速のパフォーマンスを出すためにファイルは WSL ファイルシステムに格納します。 具体的には、プロジェクトは次の場所に置きます。 /mnt/c/ 配下はファイルシステムをまたぐため、npm install や git status が体感でわかるほど遅くなります。第2弾でこれから入れるツールも、すべて Linux 側のホームディレクトリを前提に使ってください。 出典:WSL 開発環境を設定する — Microsoft Learn 1. まずは基本ツール Ubuntu を起動したら、最初にやることはパッケージの更新です。Microsoft の公式ドキュメントにもこう書かれています。 ディストリビューションの優先パッケージ マネージャーを使用して、パッケージを定期的に更新およびアップグレードすることをお勧めします。Windows [&hellip;]

デフォルトサムネイル

WindowsでWSL2をセットアップしてUbuntuを使えるようにする

TerraformやAWS CLI、Dockerを快適に使うために、WindowsにWSL2を導入しました。 この記事では、実際に行ったセットアップ手順と、途中で遭遇したエラーへの対処方法をまとめます。 なぜWSLを使うのか? WSL(Windows Subsystem for Linux)は、Windows上でLinux環境を動かすための仕組みです。 AWSやTerraform、Dockerなど、多くの開発ツールはLinux環境との相性が良いため、Windowsで開発する場合でもWSL2を利用するのが一般的です。 今回の開発環境では以下のような構成を想定しています。 1. WSLをインストール PowerShell(管理者)を開き、以下を実行します。 2. Ubuntuの初回セットアップ Ubuntuを起動すると、Linuxユーザー名とパスワードの設定を求められます。 例 好きなユーザー名を入力します。 続いてパスワードを設定します。 ※入力中は文字が表示されませんが正常な動作です。 3. パッケージを更新 Ubuntuを起動したら、まず最新状態へ更新します。 4. エラーが表示された アップグレード中に次のようなメッセージが表示されました。 一見エラーに見えますが、今回は最後まで と表示され、更新自体は正常に完了していました。 WSLではsystemd関連の処理で、このような警告が表示されることがあります。 5. WSLの状態を確認 PowerShellで以下を実行します。 今回は となっていました。 6. Docker DesktopとUbuntuの違い ここで少し混乱しやすいポイントがあります。 Docker Desktopをインストールすると、docker-desktopというWSLディストリビューションが作成されます。 しかし、これはDockerが内部で利用するためのもので、普段の開発を行う場所ではありません。 おすすめの構成は次の通りです。 開発はUbuntuで行い、Docker Desktopはコンテナ実行基盤として利用します。 7. Ubuntuを既定のディストリビューションに変更 現在登録されているWSLを確認します。 Ubuntuがインストールされていることを確認したら、 を実行します。 これで だけでUbuntuが起動するようになります。 今後インストール予定 WSL環境では今後以下を導入していきます。 この環境をベースに、AWS Organizations、IAM [&hellip;]

AWS IAM Identity Centerとは?IAM Userを使わないAWS認証・権限管理のベストプラクティス

AWS IAM Identity Centerとは?IAM Userを使わないAWS認証・権限管理のベストプラクティス

AWS Organizationsによるマルチアカウント環境を構築した後、次に設定したのがAWS IAM Identity Centerです。 以前はAWSへログインするためにIAM Userを作成することが一般的でしたが、現在AWSでは、人がAWSへログインする場合はIAM Identity Centerの利用を推奨しています。 今回は、IAM Identity Centerを導入した理由と、実際の設定内容についてまとめます。 IAM Identity Centerとは IAM Identity Center(旧 AWS Single Sign-On)は、複数のAWSアカウントやAWSアプリケーションへの認証・認可を一元管理するサービスです。 従来のように各AWSアカウントへIAM Userを作成する必要はなく、 というメリットがあります。 AWS Organizationsと組み合わせることで、マルチアカウント環境の運用が大幅に容易になります。 なぜIAM UserではなくIdentity Centerなのか 以前は、このような構成が一般的でした。 しかし、この方法では といった課題があります。 Identity Centerを利用すると、ユーザー情報は一元管理され、各AWSアカウントには必要な権限だけを割り当てる運用になります。 AWS Well-Architected Frameworkでも、人によるアクセスにはフェデレーション認証を利用し、長期認証情報(IAM Userのアクセスキーなど)をできる限り利用しないことが推奨されています。 今回の構成 今回は次のようなシンプルな構成にしました。 グループ Administrators AWS環境全体を管理するメンバーです。 現在は を所属させる予定です。 Developers アプリケーションやインフラ開発を行うメンバー向けです。 今回はまだ利用していませんが、開発メンバーが増えた際に使用します。 将来的には などを割り当てる予定です。 ReadOnly 閲覧専用グループです。 監査やレビュー、外部アドバイザー向けとして利用します。 今回は技術メンターにReadOnly権限を付与することを想定しています。 Permission [&hellip;]

この記事を書いた会社

株式会社coiaiは、「想像できることを美しく実現」を掲げ、XR・Web・アプリ・システム開発およびDX支援を行う会社です。 創業2022年、東京都練馬区に本社を置き、要件のヒアリングからPoC(概念実証)、本番運用まで一貫して伴走します。 まずはお気軽にご相談ください。

商号株式会社 coiai創業2022年1月設立2025年1月23日資本金1,500,000円(設立時点)本社所在地東京都練馬区関町北 3-6-9代表者代表取締役 竹村 啓佑 / 代表取締役 服部 陽良

主なご相談内容

会社概要・役員紹介を見る

詳しい会社情報は会社概要ページでご覧いただけます。

資料請求・無料相談

導入要件のヒアリングからPoC、本番運用まで伴走します。まずはお気軽にご相談ください。

お問い合わせの前に 個人情報保護方針 をご確認ください。

MVC とは?を理解するために簡単なアプリをつくる with Laravel | 株式会社coiai