はじめに

Laravelで開発を始めようとしたとき、最初の壁になるのが開発環境づくりですよね。
PHPのバージョン、MySQLのインストール、メールの送信テスト……。
1つずつ自分のパソコンに入れていくと、それだけで1日が終わってしまいます。

この連載では、ポートフォリオとして作っている社内業務システム「office-hub」の開発工程を、フェーズごとに記録しています。
前回の#0 題材選びと設計書づくりで設計が終わったので、今回の#1からいよいよ手を動かします。

この記事では、Laravel Sailを使って、

  • Laravel+MySQL+メール確認ツールの環境をまとめて作る
  • 最初の起動の前に .env を設定する(ここが大事です)
  • React の画面からログインできるように、APIと認証の下準備をする

までを、実際につまずいたところも含めて紹介します。

コマンドは自分でターミナルに打っていますが、設定の意味や手順はAI(Claude)に相談しながら進めました。

Laravel Sailとは?

Laravel Sail は、Laravel公式のDocker開発環境です。
Dockerは、パソコンの中に「小さな専用のパソコン(コンテナ)」を作って、その中でアプリを動かす仕組みです。

Sailを使うと、PHP・MySQL・メール確認ツールなどが入ったコンテナがまとめて用意されます。
自分のパソコンにPHPやMySQLを直接インストールしなくていいのがうれしいところです。

今回Sailを選んだ理由は3つです。

  • 公式の環境なので、MySQLとメール確認ツール(Mailpit)が最初からそろう
  • 自分でDockerの設定ファイルを書くのは勉強になるけれど、それは仕上げの段階でやれば十分
  • あとから中身を取り出して、自分好みに変えることもできる

まずは「動く環境を早く作って、アプリづくりに集中する」ことを優先しました。

手順1:プロジェクトを作る

Docker Desktop を起動した状態で、ターミナルで次のコマンドを実行します。

curl -s "https://laravel.build/backend?with=mysql,mailpit" | bash
  • backend … 作られるフォルダの名前です
  • with=mysql,mailpit … 一緒に用意するもの。今回は MySQL と Mailpit(送ったメールをブラウザで確認できるツール)を指定しました

途中でMacのパスワードを聞かれます。
ファイルの権限を調整するためなので、入力して進めてOKです。最初はびっくりしますよね。

手順2:起動する前に .env を設定する

ここがこの記事でいちばん伝えたいポイントです。
プロジェクトができたら、すぐに起動せず、先に .env を設定します。

理由は、MySQLのコンテナは、最初に起動したときにしかデータベースを作らないからです。
先に起動してしまうと、あとから .env でデータベース名を変えても、そのデータベースは存在しないので接続エラーになります。

もしやってしまった場合は、コンテナをデータごと削除して作り直すことになります(中のデータは消えます)。
最初に決めておけば避けられるので、起動前に設定しておくのがおすすめです。

今回はこのように設定しました(関係するところだけ抜き出しています)。

APP_NAME="備品在庫管理システム"
APP_TIMEZONE=Asia/Tokyo
APP_URL=http://localhost
APP_LOCALE=ja
APP_FALLBACK_LOCALE=en

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=inventory
DB_USERNAME=sail
DB_PASSWORD=password

DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_ja_0900_as_cs

SESSION_DRIVER=database
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:5173
FRONTEND_URL=http://localhost:5173

タイムゾーンや言語のほかに、意味を知っておきたい設定が3つあります。

設定何のため?
DB_COLLATION=utf8mb4_ja_0900_as_cs文字の比べ方のルールです。最後の _cs は「大文字と小文字を区別する」という意味。備品コードの AB-01 と ab-01 を別のものとして扱いたかったので、こうしました
SESSION_DRIVER=databaseログイン状態(セッション)をデータベースに保存します。Laravel 11以降は最初からこの設定になっているので、そのまま使っています(Laravel 10まではファイルに保存するのが初期設定でした)。あとで出てくるエラーの原因になるので、覚えておいてください
SANCTUM_STATEFUL_DOMAINS=localhost:5173React(Vite)の開発用サーバーのアドレスです。ここからの通信を「自分の画面からの通信」として扱い、ログイン状態を引き継げるようにします

大文字と小文字を区別すると、メールアドレスで困る

大文字と小文字を区別する設定にはデメリットもあります。
User@example.com と user@example.com も別のものとして扱われるので、そのままだと同じ人が2回登録できてしまいます。

そこで、メールアドレスは保存する前に小文字にそろえることにしました。
1つの設定を決めると、別の場所に影響が出る。
設定の意味を知っておくと、こういうことに先に気づけます。

手順3:起動する

.env を保存したら、いよいよ起動です。

cd backend
./vendor/bin/sail up -d

-d は「裏側で動かし続ける」という意味です。
初回はコンテナの準備に5〜10分ほどかかりました。

💡 毎回 ./vendor/bin/sail と打つのは長いので、sail だけで動くように設定(エイリアス)する方法もあります。
ただ、私はLaravelの開発に慣れるまではあえて設定せず、毎回フルで打っています。
何を動かしているのかが見えるので、今はこのほうが分かりやすいです。

ハマったこと:sessionsテーブルが見つからない

起動できたので、ブラウザで http://localhost を開いてみると……500エラーになりました。

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'inventory.sessions' doesn't exist

「inventory データベースに sessions テーブルがない」というエラーです。

原因:テーブルを作るコマンドをまだ実行していなかった

手順2で、ログイン状態をデータベースに保存する設定(SESSION_DRIVER=database)にしました。
Laravelはトップページを表示するだけでもログイン状態の準備を始めるので、その保存先のテーブルが必要になります。

でも、テーブルを作るコマンド(マイグレーション)をまだ実行していませんでした。次のコマンドで解決です。

./vendor/bin/sail artisan migrate

sessionsテーブルはどこで作られる?

ここで1つ分かったことがあります。
最近のLaravel(11以降)では、sessions テーブルはユーザーのテーブルと同じファイルの中で作られます。

database/migrations/0001_01_01_000000_create_users_table.php
  ├─ users
  ├─ password_reset_tokens
  └─ sessions   ← ここ

「セッション用のマイグレーションファイルはどこ?」と探しても、ファイル名に sessions が入っていないので見つからないんです。

✅ ちなみに、このエラーはいい知らせでもありました。エラーに inventory というデータベース名が出ているということは、手順2で設定したデータベースにちゃんと接続できている証拠です。
エラーメッセージは、どこまでうまくいっているかの手がかりにもなります。

手順4:APIとSanctumを入れる

office-hubは、画面をReactで作り、Laravelはデータをやり取りするAPIの役割をします。そのための準備です。

./vendor/bin/sail artisan install:api
./vendor/bin/sail artisan config:publish cors
  • install:api … API用のルート(URLの割り当て)を書くファイル routes/api.php を作り、ログイン機能のライブラリ Laravel Sanctum を入れます
  • config:publish cors … 別のアドレスからの通信を許可する設定ファイル config/cors.php を取り出します

Laravel 11以降は、この2つのファイルは最初は存在しません。
必要な人だけコマンドで作る形になっています。

「マイグレーションを実行しますか?」には yes

install:api を実行すると、途中でこう聞かれます。

One new database migration has been published.
Would you like to run all pending database migrations? (yes/no) [yes]:

これは personal_access_tokens というテーブルを作るかどうかの質問です。
このテーブルは、スマホアプリなどで使うトークン方式のログインのためのもので、今回使う方式(次の手順で説明します)では実は使いません。

それでも yes にしました。

  • 実行していないマイグレーションを残したくない … noにしても、次にマイグレーションを実行したときに結局作られます。「わざと残しているのか、忘れているのか」が分からない状態になるのを避けたかったためです
  • あとで使うかもしれない … 将来、棚卸し用のタブレットなどからAPIを使いたくなったら、そのまま使えます。空のテーブルが1つ増えるだけなので、損はほとんどありません

手順5:React画面からログインできるようにする

ログインの方式は、SanctumのSPA認証を選びました。ログイン状態をCookieで管理する方式です。

方式ログイン情報の保存場所安全性
トークン方式ブラウザの localStorage画面に悪意のあるスクリプトを仕込まれると(XSS)、トークンごと盗まれる
SPA認証(採用)HttpOnly のCookieJavaScriptから読めないので、スクリプトに盗まれにくい

画面とAPIを同じドメインで動かす前提なので、Cookie方式の弱点(別のドメインをまたぐと設定が面倒)も問題になりません。

SPA認証を有効にするには、2つのファイルを編集します。

bootstrap/app.php

->withMiddleware(function (Middleware $middleware): void {
    $middleware->statefulApi();
})

この1行で、APIでもログイン状態(セッション)を使えるようになります。SPA認証のいちばん大事なところです。

config/cors.php

'paths' => ['api/*', 'sanctum/csrf-cookie'],

'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:5173')],

'supports_credentials' => true,
  • paths … 通信を許可するURL
  • allowed_origins … 通信を許可する相手。.env の FRONTEND_URL(Reactの開発サーバー)を読み込んでいます
  • supports_credentials … Cookieのやり取りを許可するかどうか

⚠️ 公式ドキュメントでは、SPA認証を使うときは supports_credentials を true にして、Access-Control-Allow-Credentials というヘッダーを返すように案内されています。
画面とAPIのアドレスが違う構成では、これを忘れるとCookieを使ったログインがうまくいきません。

ここまでで、開発環境の準備は完了です。実際にReactの画面からログインするところは、もう少し先の回で書きます。

この時点のコードは、GitHubの phase-1 タグで見られます。

まとめ

  • Laravel Sailを使うと、Laravel+MySQL+Mailpitの環境をコマンド1つで作れる
  • .env は最初の起動の前に設定する。MySQLのデータベースは最初の起動のときにしか作られない
  • 大文字と小文字を区別する設定にしたら、メールアドレスは小文字にそろえて保存する必要が出てきた
  • sessions テーブルがないエラーは migrate で解決。Laravel 11以降はユーザーのテーブルと同じファイルで作られる
  • React画面との認証はCookie方式のSPA認証。statefulApi() と supports_credentials => true を忘れない

次回の#2では、部署・カテゴリ・保管場所といったマスタのテーブルを作ります。
#0で予告した「UNIQUE制約がNULLのときに効かない」問題にも、ここで向き合います。

Laravelをはじめて触る方は、Laravel開発の始め方|初心者向けの初期設定まとめもあわせてどうぞ。

私はふだん製造業で働きながら、WordPressを中心にWebサイトの制作をしています。
これまでの制作実績はポートフォリオにまとめています。
office-hubのコードはGitHubで公開しています。