Laravel Sail + Vite + Tailwind CSS + Laravel Breeze(認証機能)を使った開発環境の構築
はじめに
今回はLaravel Sailを使用して、Dockerを使った開発環境を構築を行います。
Laravelとは
PHPで開発されたオープンソースのWebアプリケーションフレームワークです。
Laravelは、ルーティング、MVCアーキテクチャ、認証、データベースマイグレーション、テンプレートエンジン、セッション管理などの多くの機能を提供しています。
MVCとは
下記の頭文字を取ったものです。
モデル(Model)はデータを管理する部分、ビュー(View)はユーザーに表示されるインターフェース部分、コントローラー(Controller)はユーザーからの要求を受け取り、モデルとビューの間で情報をやり取りする役割を担います。
Laravel Sailとは
Laravel SailはCLIを通じてLaravelの開発環境を構築するためのDockerコンテナを提供するツールです。
Sailには、Laravelアプリケーションに必要なPHP、MySQL、Node.jsなどのコンテナが含まれており、簡単な設定とコマンド一つで環境をセットアップできます。
Sailコマンド
Laravel Sailは、./vendor/bin/sail
スクリプトを通じてコンテナ内部のコマンドを呼び出す仕組みを提供しています。これにより、直接コンテナ内に入ることなくコマンドを実行できます。
sail
コマンドはdocker-compose exec
コマンドを使用してDockerコンテナ内でArtisan
コマンドを実行します。このため、sailはdocker-compose
のラッパーとして機能し、Docker Composeで定義されたサービスに対してコマンドを実行します。
この仕組みにより、ユーザーは複雑なDocker
コマンドを覚える必要がなく、簡単にLaravelのArtisan
コマンドを実行することが可能です。
エイリアス作成
Laravelでは、通常コマンドを入力する場合にはphp artisan
を使用します。
しかし、Laravel Sailを使用する場合は、./vendor/bin/sail
と入力する必要があります。毎回./vendor/bin/sail
と入力するのは面倒なのでエイリアスを設定します。
zsh
シェルを使用している場合はホームディレクトリにある.zshrc
ファイルを編集してエイリアスを設定することができます。もし、.zshrc
ファイルが存在しない場合は新規に作成してください。
touch .zshrc
.zshrc
ファイルを開き、以下のコードを追加してください。
sail
と入力するだけで./vendor/bin/sail
を実行できるようにするエイリアスを定義しています。
alias sail="./vendor/bin/sail"
設定を有効にするために、以下のコマンドを実行して設定変更を反映させてください。
これにより、Laravel Sail コマンドを sail という短縮形で簡単に使用できるようになります
source ~/.zshrc
Laravelプロジェクトの作成
Dockerを用いた開発環境を含んだLaravelプロジェクトの作成してください。
curl -s https://laravel.build/<プロジェクト名> | bash
利用するサービスをオプションの追加することで指定することもできます。URLクエリパラメータを使用して、with
の後に使用したいDockerサービスのリストをカンマ区切りで指定してください。
指定しない場合は、mysql、redis、meilisearch、mailhog、selenium
が設定されます。
curl -s "https://laravel.build/<プロジェクト名> ?with=mysql,redis,meilisearch" | bash
最後にパスワードの入力が求められます。
無事にプロジェクトが作成できると下記のコマンドが表示されますので、表示通りに実行してコンテナを起動してください。
cd <作成されたプロジェクト名> && ./vendor/bin/sail up
sail up
のあとに-d
をつけると、バックグラウンドでコンテナを立ち上げることができます。
ブラウザに http://localhost/ と入力すると、下記のいずれか表示されます。
下記の場合は、RUN MIGRATIONS
を選択してください。
下記の場合は、sail artisan migrate
でマイギュレーションを実行してください。
データベースのマイグレーションを実行してLaravelアプリケーションで定義されたすべてのマイグレーションがデータベースに適用されます。
Refresh now
を選択してください。
http://localhost/ にアクセスすると、デフォルトのトップページ(welcome.blade.php
)が表示されることを確認してください。
認証機能の追加
認証機能の追加することによって、ログインした人のみが観覧できるようにすることができます。
今回はLaravel Breezeを使用して認証機能の追加します。
これは必須ではないのでプロジェクトに応じて追加してください。
また後からaravel Breezeを使用して認証機能を追加する場合は、既存のものが上書きされるなどして組み込みが大変なので最初に追加しておくことをおすすめします。
Laravel Breezeとは
Laravelアプリケーションに認証機能を追加するための軽量なパッケージです。
Laravel Breezeのインストール
composer require laravel/breeze --dev
認証機能の作成
下記を実行すると、認証機能に必要なコントローラー、モデル、ビューが自動生成されます。
sail artisan breeze:install
Blade with Alpine
を選択してください。
┌ Which Breeze stack would you like to install? ───────────────┐
│ › ● Blade with Alpine │
│ ○ Livewire (Volt Class API) with Alpine │
│ ○ Livewire (Volt Functional API) with Alpine │
│ ○ React with Inertia │
│ ○ Vue with Inertia │
│ ○ API only │
└──────────────────────────────────────────────────────────────┘
または核を実行すると、オプションの中でBlade with Alpine
を選択していることになります。
sail artisan breeze:install blade
生成が完了したら、http://localhost/ にアクセスして右上にLog in Register
が追加されているか確認してください。
認証機能を確認するために、登録してください。
登録/ログインが完了すると、右上に名前が表示されると思います。
パスワードリセットの設定
現在のままでは下記のように表示はされますが、実際にパスワードリセットを行うことができません。
mailpit
サービスを使用して、実際のメールサーバーではなく、ローカルの開発環境内でメールを受信できるようにします。
Notificationクラスの作成
php artisan make:notification ResetPasswordNotification
Notification
モデルの修正
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Notifications\ResetPasswordNotification;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
// 追記
public function sendPasswordResetNotification($token): void
{
$url = route('password.reset', ['token' => $token]); // 名前付きルートを利用
$this->notify(new ResetPasswordNotification($url));
}
}
http://localhost:8025/ にアクセスしてメールが受信できているか確認してください。
ResetPasswordNotification.php
の内容を変更すると、届くメールの内容も変更することができます。
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class ResetPasswordNotification extends Notification
{
use Queueable;
protected $url; // プロパティの宣言を追加
/**
* Create a new notification instance.
*/
public function __construct($url)
{
$this->url = $url;
}
/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject(config('app.name') . ' パスワードリセットURLの送付')
->greeting('いつもご利用頂きありがとうございます。')
->action('パスワードリセット', $this->url)
->line('こちらからパスワードリセットを行ってください。');
}
/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
//
];
}
}
次のように変更されます。
リンクからパスワードリセットの画面が表示されるか確認してください。
Tailwind CSSの導入
Laravel Breezeのインストールしている場合はTailwind CSSがすでに含まれているため、追加の手順や初期設定は不要です。
Tailwindで機能するパッケージをインストール
npm install -D tailwindcss postcss autoprefixer
Tailwind CSSの初期設定を行います。
tailwind.config.js
とpostcss.config.js
の2つのファイルがプロジェクトのルートに作成されているか確認してください。
npx tailwindcss init -p
テンプレートパスの設定
以下を記述してください。
LaravelはデフォルトでpublicディレクトリにあるCSSファイルを探します。テンプレートパスは、アプリケーションのCSSファイルがどこにあるかをLaravelに伝えるものです。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
],
theme: {
extend: {},
},
plugins: [],
}
@tailwindディレクティブの追加
Tailwind CSSを利用してプロジェクトにスタイルを追加するために@tailwind
ディレクティブの記述を追加してください。
@tailwind base;
@tailwind components;
@tailwind utilities;
スタイルの適用
スタイルを適用するには、以下を適用したいbladeファイル(レイアウトを共通化するためのファイル)に記述してください。
@vite('resources/css/app.css')
今回は試しに以下のように変更して、確認してみます。
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1 class="text-3xl bg-orange-300 font-bold ">
Hello world!
</h1>
</body>
</html>
スタイルが適用されているか確認するために、コンテナは起動したままViteを使用してフロントエンドの開発サーバーを起動します。
npm run dev
既にデフォルトページが表示されているにも関わらず、Viteを使用してフロントエンドの開発サーバーを起動する理由
Laravelプロジェクトには、通常、フロントエンドのJavaScriptやCSSなどが含まれています。
これらのファイルを編集した場合にnpm run dev
を実行し、Viteを起動していると、Viteが変更を検知し、自動的にビルドを実行してブラウザをリロードしてくれるので、変更を即座に反映させる(ホットリロード)ことができます。
下記が表示され、Tailwind CSSが効いていないことがわかると思います。
次に@vite('resources/css/app.css')
を追記してください。
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@vite('resources/css/app.css')
</head>
<body>
<h1 class="text-3xl bg-orange-300 font-bold ">
Hello world!
</h1>
</body>
</html>
Tailwind CSSが効いていることがわかると思います。
Viteを起動している時の違いがわかるように、h1のユーザー一覧
をユーザー
に変更して比較しました。
Viteの起動なし(手動更新&tailwind cssが効いていません)
Viteの起動あり(手動更新不要&tailwind cssが効いています)
Viteとは
Vue.jsのための新しいビルドツールおよび開発サーバーです。
Laravelのデフォルトビルドツールがバージョン9.18以降はLaravel MixからViteに変わっています。
Viteを使用してフロントエンドの開発サーバーを起動することができます。
npm run dev
ホットリロード機能
Viteのデフォルト設定にはホットリロード機能が含まれており、これによりコードの変更が即座に適用されるため、ページをリフレッシュする必要がありません。デフォルトで、localhost
が指定されています。
記述されていませんが、コメントアウト部分の記述が適用されています。
import laravel from "laravel-vite-plugin";
import { defineConfig } from "vite";
export default defineConfig({
// server: {
// hmr: {
// host: "localhost",
// },
// },
plugins: [
laravel({
input: ["resources/css/app.css", "resources/js/app.js"],
refresh: true,
}),
],
});
言語とタイムゾーンの変更
timezone、localeの項目を以下のように変更します。
'timezone' => 'Asia/Tokyo'
'locale' => 'ja',
データベースのGUIツール
phpMyAdminのインストール方法などを記述しております!
本番環境用
本番環境用にビルドする場合は下記を実行してください。
sail npm run build
これにより、public
ディレクトリにファイルが出力され、本番環境で参照するjs、cssファイルなどが生成され、デプロイできる状態になります。
Laravel SailのDockerfileを表示する
下記コマンドでDocker関連のファイルをルートディレクトリにコピーすることで確認できます。
また、コピーしたファイルはGit管理の対象となります。
sail artisan sail:publish
docker
以下にvendor
内にあるファイルがコピー表示されます。
また、docker-compose.yml
の context:
の内容も自動でコピーして作成されたDockerfile
に変更になっています。
laravel.test
のデフォルトのコンテナ名を変更する
.env
> $APP_SERVICE
は、Laravelアプリケーションを実行しているコンテナ名を指定しています。
デフォルトのlaravel.test
から、`docker-compose.yml`でコンテナ名を変更する場合は必ず、.env
でAPP_SERVICE
を定義してください。
APP_SERVICE="app"
artisanコマンドの実行について
ローカルでartisan
コマンドを使う場合は
php artisan
で実行していましたが、Sail上でartisanコマンドを使う場合には
sail artisan
で実行します。
アプリケーションが表示されない場合
デベロッパーツールのConsoleで以下のような表示がされている場合には、フロントエンドの開発サーバー(Vite)が立ち上がっていません。
開発中は、両方のサーバーを起動しておいてください。
両方のサーバーを起動していることで、バックエンドのサーバーはフロントエンドからのリクエストの処理などを行ったりすることができます。
サーバー | コマンド | 説明 |
---|---|---|
Laravelのバックエンドサーバー(コンテナ) | ./vendor/bin/sail up |
API の提供やデータベースとのやり取りなど、アプリケーションのバックエンド処理を担当します。 |
Viteを使用したフロントエンドの開発サーバー | npm run dev |
フロントエンドの開発に特化した機能を提供し、ビルドやモジュールのホットリロードを可能にします。 |
エラーログの確認
Laravelは詳細なエラーログをstorage/logs/laravel.log
に保存します。
このログファイルを確認して、具体的なエラーメッセージを確認してください。
また、下記を記述することでデバックできます。
use Illuminate\Support\Facades\Log;
Log::info('ユーザーID: ' . user()->id);
ポート番号を変更する
"${APP_PORT:-80}:80"
を"8080:80"
に変更してコンテナを再起動してください。
services:
laravel.test:
build:
context: ./docker/8.3
dockerfile: Dockerfile
args:
WWWGROUP: "${WWWGROUP}"
image: sail-8.3/app
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- "8080:80"
# - "${APP_PORT:-80}:80"
- "${VITE_PORT:-5173}:${VITE_PORT:-5173}"
http://localhost/ ではなく、http://localhost:8080/ で画面が表示されるように変更になっているのがわかると思います。
ビュー(Bladeテンプレート内)でデバッグする
dd関数
dd(Dump and Die)関数はデバッグヘルパー関数の1つで、変数や式の値を出力してから、その後の処理が停止します。
{{ dd(session('message')) }}
SQLSTATE[42S02]: Base table or view not found: 1146 Table '<データベース名>.<テーブル名>' doesn't exist (Connection: mysql, SQL: select * from <テーブル名> where id = <ID> limit 1)
マイグレーションを実行してテーブルの作成/変更を行うと解決するか確認してください。
sail artisan migrate
file_put_contents(/.../storage/framework/views/<>.php): Failed to open stream: No such file or directory
Laravelがビューのキャッシュファイルを作成しようとした際にディレクトリが存在しないか、書き込み権限がないためにファイルを作成できないことを示しています。
ディレクトリが存在しない場合は作成してください。
/.../
は省略して表示しています。
mkdir -p /.../storage/framework/views
ストレージディレクトリに対して適切なパーミッションを設定してください。
今回はmacOSを使用しているので_www
としています。
chmod -R 775 /.../storage
sudo chown -R $USER:_www /.../storage
設定を変更した後、Laravelのキャッシュをクリアして設定を反映させます。
php artisan cache:clear
php artisan view:clear
php artisan config:clear
終わりに
何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉
Discussion