人気のPHPフレームワーク「Laravel」によるWebサイトの作り方を解説します。

LaravelでWebサイトを作ってみよう!

基本

お問い合わせページを作ってみよう

更新日:

データベースの用意

MySQLクライアントを起動します。

> mysql -u root -p

MySQLクライアントで以下のコマンドを入力してデータベースを作成し、ユーザーを割り当てます。

mysql> create database laravel;
Query OK, 1 row affected (0.00 sec)

mysql> create user laravel@localhost identified by 'laraveldb';
Query OK, 0 rows affected (0.01 sec)

mysql> grant all privileges on laravel.* to laravel@localhost;
Query OK, 0 rows affected (0.00 sec)

データベースにアクセスするための設定

データベースにアクセスするための設定は、.env ファイルに記述します。
VSCodeで .env ファイルを開き、以下の部分を修正します。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=laraveldb

これで、LaravelからMySQLにアクセスできるようになりました。
Laravelには、デフォルトでユーザーやキャッシュ関連のマイグレーションが用意されているので、これを実行しておきます。

> php artisan migrate

   INFO  Preparing database.

  Creating migration table ............................................................. 27.16ms DONE

   INFO  Running migrations.

  0001_01_01_000000_create_users_table ................................................. 79.36ms DONE
  0001_01_01_000001_create_cache_table ................................................. 29.63ms DONE
  0001_01_01_000002_create_jobs_table .................................................. 69.06ms DONE

ユーザー認証機能を有効にする

お問い合わせには関係ないけど、ユーザー認証機能を有効にしておきます。

> composer require laravel/breeze
> php artisan breeze:install

お問い合わせに対応するモデルを作成する

お問い合わせは、多くのサイトでは Contact のようなページが用意されていますので、お問い合わせに対応するモデルの名前は Contact とします。

Laravelでモデルを作成する場合は、コマンドラインから以下のコマンドを実行します。

> php artisan make:model Contact -m

最後の「-m」はマイグレーションファイルも同時に生成するためのオプションです。

これを実行すると、以下のファイルができます。

  • app\Models\Contact.php
  • database\migrations\yyyy_mm_dd_hhmmss_create_contacts_table.php
  • Contact.php

    以下の内容を追加します。これは、Webアプリからこれらのフィールドにデータの保存を許可することを意味します。

    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class Contact extends Model
    {
        use HasFactory;
        protected $fillable = [
            'name',
            'email',
            'body',
        ];
    
    }
    
    yyyy_mm_dd_hhmmss_create_contacts_table.php

    データベースの contacts テーブルに作成するカラムを指定します。

    <?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('contacts', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->string('email');
                $table->text('body');
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         */
        public function down(): void
        {
            Schema::dropIfExists('contacts');
        }
    };
    

    ビューを作成する

    LaravelのViewに対応するファイルは、resources\views フォルダに作成されます。

    以下のコマンドでお問い合わせページに対応するビューを作ります。

    > php artisan make:view contact
    

    resources\views に contact.blade.php ファイルが作られます。

    dashboard.blade.php をコピーして、以下の内容にしておきます。

    おおもとのタグ x-app-layout は、resources\views\layouts\app.blade.php をレイアウトファイルに指定するという意味です。

    このファイルは、ユーザーがログインしている状態を前提として書かれているので、app の部分を guest に変更しておきます。

    また、@vite の行があると npm というツールをインストールする必要があるので、この行は削除しておきます。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        {{ __("お問い合わせ内容を入力してください。") }}
                    </div>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    コントローラーを作成する

    Laravelではコントローラーに対応するクラスは App\Http\Controllers フォルダに作成されます。

    以下のコマンドで Contact に関連する制御をおこなう、ContactController を作成します。

    > php artisan make:controller ContactController
    

    ContactController.php の内容は以下のようにします。

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    
    class ContactController extends Controller
    {
        public function index()
        {
            return view('contact');
        }
    }
    

    resources\views\layouts\guest.blade.php は15行目の @vite の行を削除し、さらに、ロゴが記載されている div をまるごと削除しておきます。

    <!DOCTYPE html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <meta name="csrf-token" content="{{ csrf_token() }}">
    
            <title>{{ config('app.name', 'Laravel') }}</title>
    
            <!-- Fonts -->
            <link rel="preconnect" href="https://fonts.bunny.net">
            <link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
    
            <!-- Scripts -->
        </head>
        <body class="font-sans text-gray-900 antialiased">
            <div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
                <div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg">
                    {{ $slot }}
                </div>
            </div>
        </body>
    </html>
    

    ルーティングを定義する

    どのURLにアクセスが来たときに、どのコントローラーに制御を渡すのかをルーティングといいます。

    ルーティングを定義しているファイルは、routes/web.php です。

    こちらに、以下の内容を追加します。

    <?php
    
    use App\Http\Controllers\ContactController;
    use App\Http\Controllers\ProfileController;
    use Illuminate\Support\Facades\Route;
    
    Route::get('/', function () {
        return view('welcome');
    });
    
    Route::get('/contact', [ContactController::class, 'index']);
    
    Route::get('/dashboard', function () {
        return view('dashboard');
    })->middleware(['auth', 'verified'])->name('dashboard');
    
    Route::middleware('auth')->group(function () {
        Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
        Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
        Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
    });
    
    require __DIR__.'/auth.php';
    

    これで、http://localhost:8000/contactにアクセスすると、お問い合わせページが表示されます。

    お問い合わせページに、入力フォームを追加します。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        {{ __("お問い合わせ内容を入力してください。") }}
                    </div>
                    <div>
                        <form action="" method="post">
                            @csrf
                            お名前: <input type="text" name="name" /></br>
                            Email: <input type="text" name="email" /></br>
                            お問い合わせ内容:
                            <textarea name="body"></textarea></br>
                            <button>送信</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    ルーティングにPOST先を追加する

    お問い合わせ内容のデータの送信先となるルーティングを追加します。

    <?php
    
    use App\Http\Controllers\ContactController;
    use App\Http\Controllers\ProfileController;
    use Illuminate\Support\Facades\Route;
    
    Route::get('/', function () {
        return view('welcome');
    });
    
    Route::get('/contact', [ContactController::class, 'index']);
    Route::post('/post', [ContactController::class, 'post'])->name('contact.post');
    
    

    formのaction属性を変更する

    ルーティングでPOST先を追加したので、そのURLにデータを送信するように、formタグのaction属性を変更します。

    ルーティングに対してname(‘contact.post)として名前を付けておいたので、以下のように記述すれば、Laravelが自動的に’/post’に変換してくれます。

    @csrf の内容もinputタグに変換されているので、devtoolで確認しましょう。

                    <div>
                        <form action="{{ route('contact.post') }}" method="post">
                            @csrf
                            お名前: <input type="text" name="name" /></br>
                            Email: <input type="text" name="email" /></br>
                            お問い合わせ内容:
                            <textarea name="body"></textarea></br>
                            <button>送信</button>
                        </form>
                    </div>
    

    お問い合わせ内容のデータをコントローラーで受け取る

    お問い合わせ内容のデータをコントローラーで受け取って、データベースに保存するようにしましょう。

    <?php
    
    namespace App\Http\Controllers;
    
    use Illuminate\Http\Request;
    use App\Models\Contact;
    
    class ContactController extends Controller
    {
        public function index()
        {
            return view('contact');
        }
    
        public function post(Request $request)
        {
            Contact::create([
                'name' => $request->input('name'),
                'email' => $request->input('email'),
                'body' => $request->input('body'),
            ]);
            return view('posted');
        }
    }
    

    postメソッドの最後で posted ビューを表示しようとしていますので、作りましょう。

    > php artisan make:view posted
    

    以下の内容にします。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        {{ __("お問い合わせ内容を受け付けました。") }}
                    </div>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    お問い合わせ内容を送信してみる

    お問い合わせページで名前とメールアドレスとお問い合わせ内容を入力して送信してみましょう。

    データベースに、入力した内容が登録されていればOKです。

    以下のコマンドでも確認が可能です。

    > php artisan tinker
    Psy Shell v0.12.4 (PHP 8.2.12 — cli) by Justin Hileman
    > App\Models\Contact::all()                                                                                       
    = Illuminate\Database\Eloquent\Collection {#5980
        all: [
          App\Models\Contact {#5571
            id: 1,
            name: "asdf",
            email: "asdf@example.com",
            body: """
              お問い合わせ内容\r\n
              複数行\r\n
              ああああ
              """,
            created_at: "2024-10-18 06:19:42",
            updated_at: "2024-10-18 06:19:42",
          },
        ],
      }
    
    >
    

    お問い合わせ内容を確認するページを間に挟む

    お問い合わせ内容を入力したら、確認ボタンで確認画面に遷移して、確認後にデータを送信するように変更してみましょう。

    まず、contact.blade.php を少し変更します。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        {{ __("お問い合わせ内容を入力してください。") }}
                    </div>
                    <div>
                        <form action="{{ route('contact.confirm') }}" method="post">
                            @csrf
                            お名前: <input type="text" name="name" /></br>
                            Email: <input type="text" name="email" /></br>
                            お問い合わせ内容:
                            <textarea name="body"></textarea></br>
                            <button>確認</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    15行目を route(‘contact.confirm’) に変更したので、これをルーティングに追加します。

    Route::get('/contact', [ContactController::class, 'index']);
    Route::post('/confirm', [ContactController::class, 'confirm'])->name('contact.confirm');
    Route::post('/post', [ContactController::class, 'post'])->name('contact.post');
    

    ContactControllerにconfirmメソッドを追加します。

        public function confirm(Request $request)
        {
            $contact = new Contact;
            $contact->name = $request->input('name');
            $contact->email = $request->input('email');
            $contact->body = $request->input('body');
            return view('confirm', compact('contact'));
        }
    

    確認画面を作成する

    確認画面では、コントローラーから受け取ったデータを表示するとともに、
    フォーム内では input タグの type 属性を hidden にして送信用のデータを保持します。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        {{ __("お問い合わせ内容を確認してください。") }}
                    </div>
                    <div>
                        <div>お名前: {{ $contact->name }}</div>
                        <div>Email: {{ $contact->email }}</div>
                        <div>お問い合わせ内容:</div>
                        <div>{{ $contact->body }}</div>
                        <form action="{{ route('contact.post') }}" method="post">
                            @csrf
                            <input type="hidden" name="name" value="{{ $contact->name }}" /></br>
                            <input type="hidden" name="email" value="{{ $contact->email }}" /></br>
                            <input type="hidden" name="body" value="{{ $contact->body }}" />
                            <button>送信</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    これだと、確認画面ではお問い合わせ内容の改行がうまく表示されません。

    複数行を表示するために、nl2br() 関数を使って改行コードを br タグに変更するように修正します。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 text-gray-900">
                        {{ __("お問い合わせ内容を確認してください。") }}
                    </div>
                    <div>
                        <div>お名前: {{ $contact->name }}</div>
                        <div>Email: {{ $contact->email }}</div>
                        <div>お問い合わせ内容:</div>
                        <div>{!! nl2br($contact->body) !!}</div>
                        <form action="{{ route('contact.post') }}" method="post">
                            @csrf
                            <input type="hidden" name="name" value="{{ $contact->name }}" /></br>
                            <input type="hidden" name="email" value="{{ $contact->email }}" /></br>
                            <input type="hidden" name="body" value="{{ $contact->body }}" />
                            <button>送信</button>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    お問い合わせの一覧を表示するページを作成する

    投稿されたお問い合わせの一覧を表示するページを作成します。

    まずはお問い合わせ一覧を表示するためのURLを用意します。

    Route::get('/contact', [ContactController::class, 'index']);
    Route::post('/confirm', [ContactController::class, 'confirm'])->name('contact.confirm');
    Route::post('/post', [ContactController::class, 'post'])->name('contact.post');
    Route::get('/contact-list', [ContactController::class, 'list'])->name('contact.list');
    

    コントローラーにlist()メソッドを追加します。

        public function list()
        {
            $contacts = Contact::orderBy('created_at', 'desc')->get();
            return view('contacts', compact('contacts'));
        }
    

    ビューテンプレートを作成します。

    以下のコマンドで作成します。

    > php artisan make:view contacts
    

    ビューテンプレートの内容は以下のようにします。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ一覧') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <table>
                        <tr>
                            <th>日時</th>
                            <th>名前</th>
                        </tr>
                        @foreach($contacts as $contact)
                        <tr>
                            <td>{{ $contact->created_at }}</td>
                            <td>{{ $contact->name }}</td>
                        </tr>
                        @endforeach
                    </table>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    日時の時間帯が変なので、タイムゾーンの設定を変更します。
    .env ファイルの設定を変更します。

    APP_TIMEZONE=Asia/Tokyo
    

    お問い合わせ内容の詳細ページを作成する

    お問い合わせ一覧ページで、名前のところをクリックすると、お問い合わせの詳細を表示するページに遷移できるようにします。

    まずは詳細ページに対応するURLを作成します。

    Route::get('/contact', [ContactController::class, 'index']);
    Route::post('/confirm', [ContactController::class, 'confirm'])->name('contact.confirm');
    Route::post('/post', [ContactController::class, 'post'])->name('contact.post');
    Route::get('/contact-list', [ContactController::class, 'list'])->name('contact.list');
    Route::get('/contact-detail/{id}', [ContactController::class, 'contact'])->name('contact.detail');
    

    コントローラーにcontact()メソッドを追加します。

        public function contact($id)
        {
            $contact = Contact::find($id);
            return view('contact-detail', compact('contact'));
        }
    

    お問い合わせ詳細ページを作成します。

    > php artisan make:view contact-detail
    

    contact-detail.blade.php は、以下の内容にします。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div>
                        <div>日時: {{ $contact->created_at }}</div>
                        <div>お名前: {{ $contact->name }}</div>
                        <div>Email: {{ $contact->email }}</div>
                        <div>お問い合わせ内容:</div>
                        <div>{!! nl2br($contact->body) !!}</div>
                    </div>
                    <a href="{{ route('contact.list') }}">一覧に戻る</a>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

    一覧ページの名前の部分をリンクに修正します。

    <x-guest-layout>
        <x-slot name="header">
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                {{ __('お問い合わせ一覧') }}
            </h2>
        </x-slot>
    
        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <table>
                        <tr>
                            <th>日時</th>
                            <th>名前</th>
                        </tr>
                        @foreach($contacts as $contact)
                        <tr>
                            <td>{{ $contact->created_at }}</td>
                            <td><a href="{{ route('contact.detail', $contact->id) }}">{{ $contact->name }}</a></td>
                        </tr>
                        @endforeach
                    </table>
                </div>
            </div>
        </div>
    </x-guest-layout>
    

-基本

Copyright© LaravelでWebサイトを作ってみよう! , 2025 All Rights Reserved Powered by STINGER.