Laravel の基本的な概念
今回は、初めてフレームワークを学ぶにあたり、Laravelの基本的な概念から理解を深めていきます。Laravelは非常に多機能で、開発手法も人によって異なることがありますが、まずは多くの人が共通して使うであろう基礎的な部分をしっかり押さえていきたいと思います。
Laravelのフォルダ構成
| フォルダ名 | 説明 |
|---|---|
| app | アプリケーションのプログラム部分 |
| bootstrap | アプリケーション実行時に最初に行われる処理がまとめられている |
| config | 設定関係のファイルがまとめられている |
| database | データベース関連のファイル |
| public | 公開フォルダJavaScriptやスタイルシートなど外部にそのまま公開されるファイルがまとめられている |
| resources | リソース関連の配置場所 |
| routes | ルート情報の保存場所 |
| storage | ファイルの保存場所 |
| tests | ユニットテスト関係のファイル |
| vendor | フレームワーク本体のプログラムがまとめられている |
この3つのMVCモデルを完成させる手順は
ルーティング設定 → コントローラーの実装 → ビューの作成の順番で実装していきます。
MVCアーキテクチャ
MVCは、Model(モデル)、View(ビュー)、Controller(コントローラー)の3つに役割を分けた設計パターンです。
| Model | データベースとのやり取りを担当 |
|---|---|
| View | ユーザーに表示される画面(HTML など) |
| Controller | アプリのロジックを管理し、Model と View をつなげる役割 |
ルーティングとは
ルーティングは、URL とその処理内容を結びつける仕組みです。
MVCに入る前の旗振り役となり、コントローラーメソッドへ流します。
resource\web.phpに設定します。
# ルートの基本
// ビュールート:固定ページ
Route::view('url', コールバック);
// ルート定義メソッド:動的処理ページ
Route::get('url', コールバック);
// 名前付きルート:コントローラーでルートを呼び出すときに使う名前:動的処理ページ
// ->name() で名前をつけられる
Route::get(...)->name('名前');
ファサードとは?
クラスを簡単に呼び出すための「入口」となる仕組みです。
Laravel の機能を呼び出すためのファサード一覧
| ファサード | 役割 | 具体例 |
|---|---|---|
| DB | データベース操作・DBにアクセスする | DB::table('users')->get() |
| Route | ルート定義 | ※下記一覧記載 |
| Storage | ファイル保存・取得 | ファイル保存:Storage::put('file.texte', '内容') |
| Storage | ファイルの保存先を指定:Strage::disk('public')->put() | |
| Log | ログ出力 | ログを記録する:Log::info('処理が完了しました') |
| Cache | キャッシュ操作 | キャッシュに保存:Cache::put('key', 'value', 600) |
| メール送信 | メール送信:Mail::to('user@example.com')->send(new Mail()) |
Routeの主なHTTPメソッド
| メッソド | 役割 | 具体例 |
|---|---|---|
| Route::get() | データの取得、一覧表示、フォーム表示 | Route::get('/url', [ProductController::class, 'index']); |
| Route::post() | フォーム送信、新規レコード作成 | Route::post('/url', [ProductController::class, 'store']); |
| Route::put() | 既存レコードを丸ごと更新 | Route::put('/url/{id}', [ProductController::class, 'update']); |
| Route::patch() | レコードの特定のカラムだけ更新 | Route::patch('/url/{id}', [ProductController::class, 'updatePartial']); |
| Route::delete() | データの削除処理 | Route::delete('/url/{id}', [ProductController::class, 'destroy']); |
| Route::options() | ブラウザからのOPTIONSリクエストに応答 | Route::options('/url', function (){return response()->json(['status' => 'ok']);}); |
| Route::match() | GET と POST 両方でアクセス可能にする 複数メソッドOK | Route::match(['get', 'post'], '/url', [ProductController::class, 'search']); |
| Route::any() | 開発中やデバッグ用ですべてのHTTPメソッドを受け付ける複数メソッドOK | Route::any('/url', function () {return 'any method works';}); |
頻繁に使用するルーティング処理例:
Route::get('/hello/{id}', [HelloController::class, 'index'])->where('id', '[0-9]+');
//[0-9]+ : 1ケタ以上の数字のみ
コントローラー
アプリケーションの指示役となり、ルーティングで指定されたURLにアクセスされたとき、どの処理を行うかを決めて、モデルやビューと連携して処理の流れを整理する役割を担います。app\Http\Controllersフォルダ内に設定されます。
クラスとして作成され、↓の名前空間に配置されます。
namespace App\Http\Controllers;
また、useによって「どのクラスを使うのか」を宣言して、処理を記述します。
use Illuminate\Support\Facades\Route;
// アクションを追加してルートに割り当てる
Route::get('/contact', [ContactController::class, 'index']);
//複数アクションを割りあてる
Route::get('hello/other', [ContactController::class, 'other']);
// レコードの取得
$items = DB::select('select * from people');
// レコード追加
$items = DB::insert('insert into people (name, mail, age) value(:name, :email, :param)');
// レコードの更新
DB::update(クエリ一文,パラメーター配列);
// レコードの削除
DB::update(クエリ一文,パラメーター配列);
return redirect('hello');
コントローラーの作成
php artisan make:controller HelloController --resource
// --resource:テンプレートのコードを簡単に作成してくれる
Laravel のリソースコントローラが持つ典型的なメソッド
| メソッド | 役割 | ルーターメソッド | csrf保護 formを使う | 使用可能HTML |
|---|---|---|---|---|
| index() | 一覧表示 | GET | <a> | |
| create() | 新規作成フォームの表示 | GET | ||
| store() | 新規保存処理(DBに登録) | POST | @csrf + @method('PUT') | <form> |
| show() | 単一データの表示 | GET | ||
| edit() | 編集フォームの表示 | GET | ||
| update() | 更新処理(DBを更新) | PUT・PATCH | @csrf | <form> |
| destroy() | 削除処理 | DELITE | @csrf + @method('DELETE') | <form> |
コントロールで行うデータベース操作の例:
public function index()
{ //データベースから全レコードを取得
$data = DB::table('people')->get();
$msg = 'データベースにアクセスしました';
// ビューに渡して表示する
return view('hello.index', compact('data', 'msg'));
// →→→Blade側で@foreach($data as $item)・{{ $item->msg }}など指定する。
}
リクエストとレスポンス
リクエスト: ユーザーから送られてくる情報
レスポンス:サーバーからユーザーへ返す内容
// リクエスト:フォーム送信
$request->input();
// レスポンス:内容を取得する
$response->content();
リダイレクトとは?
ユーザーのアクセスを別のURLへ自動的に転送する処理のことです。
// リダイレクト後、戻り値からさらにrouteメソッドを呼び出して
// 'hello'のRedirectResponseインスタンスを返す
public function other()
{
return redirect()->route('hello');
}
マイグレーション
マイグレーションは、データベースの構造(テーブルの追加や変更)をバージョン管理するための仕組みです。チーム開発でも、データベースの変更を簡単に共有・適用できます。
マイグレーションの作成手順
1.マイグレーションのスクリプトファイルを作成する
dateabase\migrationsに作成される
php artisan make:migrate create_people_table
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{ // テーブルの用意・フィールドやインデックスの作成
public function up(): void
{
Schema::create('people', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
// upで実行した操作を元に戻す処理
public function down(): void
{
Schema::dropIfExists('people');
}
2.マイグレーションを実行する
php artisan migrate
3.出力されてることを確認する
INFO Running migrations.
2025_09_10_123456_create_people_table ..................................... DONE
クエリビルダー
複雑なSQL文を直接書かずに、PHPコードで構築できるツールのことです。
public function index()
{
// $blogs = Blog::all();を変更
// 表示件数を更新日は新しい順に10件表示する
$blogs = Blog::latest('updated_at')->limit(10)->get();
return view('admin.blogs.index',['blogs' => $blogs]);
}
public function index()
{
// $blogs = Blog::latest('updated_at')->limit(10)->get();を変更
// ページネーションで10以上の記事へは別ページを開く
$blogs = Blog::latest('updated_at')->paginate(10);
return view('admin.blogs.index',['blogs' => $blogs]);
}
ページネーション
レコードを一定数取り出していて表示する仕組み

- 「前へ」「次へ」だけのシンプルなページネーション
$blogs = Blog::latest('updated_at')->simplePaginate(10);
return view('admin.blogs.index',['blogs' => $blogs]);
// Blade側で {{ $blogs->links() }} ページネーションリンクを表示する
- ページ番号付きのページネーション
$blogs = Blog::latest('updated_at')->simplePaginate(10); 前後のページ
// Blade側で {{ $blogs->onEachSide(2)->links() }} :前後2ページ
クエリビルダの部分一致検索(LIKE句)と複数条件の組み合わせの例
# フィールド like '%テキスト%'
// 全ての条件に合致するものだけ検索
->where('name', 'like', '%', $name . '%')
->get();
// 条件に1つでも合致すればすべて検索
->where('name', 'like', '%' . $name . '%')
->orWhere('mail', 'like', '%' . $name . '%')
->get();
※参照:SQL文を簡単にクエリービルダーに変換してくれるサイト
Bladeテンプレート
// @ifディレクティブ
@if(条件)
--出力内容--
@elseif
--出力内容--
@else
--出力内容--
@endif
// 変数が空の時
@emoty(変数)
--表示内容--
@endemoty
フォームの表示と送信処理を実装する例:
// その変数が「存在していて、nullでない」場合にだけ処理を実行する条件分岐
@isset(変数)
--表示内容--
@endisset
<h1>ユーザー情報</h1>
@isset($user)
<p>名前: {{ $user->name }}</p>
<p>メール: {{ $user->email }}</p>
@endisset
<form action="/hello" method="POST">
@csrf
<input type="text" name="name" placeholder="名前">
<input type="email" name="email" placeholder="メール">
<button type="submit">送信</button>
</form>
<p>こちらは常に表示されます。</p>
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class HelloController extends Controller
{
// フォームを表示
public function index()
{
return view('hello'); // Blade を返す
}
// フォーム送信を処理
public function store(Request $request)
{
return view('hello', ['user' => (object) $request->only(['name', 'email'])]);
}
}
use App\Http\Controllers\HelloController;
use Illuminate\Support\Facades\Route;
//フォームのルート設定
Route::get('/hello', [HelloController::class, 'index']); // フォーム表示
Route::post('/hello', [HelloController::class, 'store']); // フォーム送信
レイアウト
HTMLやCSS/JavaScriptをレンダリングして、レスポンスを表示するのが役割です。
HTMLにPHPを埋め込めるテンプレートエンジンであり、拡張子は、 .blade.phpとなります。
各ページデォルトのビューをresources\views\layoutsの下に設定する。
<!DOCTYPE html>
<html lang="ja">
<head>
<title>@yield('title', 'ねこカフェららべる')</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link rel="stylesheet" href="/css/tailwind/tailwind.min.css">
</head>
<main>@yield('content')</main>
...
...
<div class="footer">@yield('footer')</div>
</html>
子ビュー:それぞれのページにデォルトを配置する
子ビューはresources\views\に設定する。
@extends('layouts.default')
@section('title', 'トップページ')
@section('content')
@endsection
Eloquent ORM
Eloquent ORM は、Laravel が提供するデータベース操作用のツールです。複雑な SQL を書かずに、オブジェクト指向の形式(=モデル)でデータベースのデータを操作できます。モデルのファイルは app\下で管理されます。
※データベース設定はconfig/database.phpに記載します。
例: User::find(1); で ID が1のユーザーを取得する。
モデル
データベースのテーブルと連携してデータを扱うためのPHPクラスのこと。
// モデルの新規作成
php artisan make:model (モデル名) -cr
// -cr:モデルとコントローラーを同時に作成する
// モデルを利用するコントローラーを作成する
php artisan make:controller PhotoController
<?php
namespace App\Http\Controllers;
use app\Models\Blog;
use Illuminate\Http\Request:
class BlogController extends Controller
{
public function index()
{ // データの取得 一覧表示
$items = Blog::all();
return view('blog.index', ['items' => $items]);
}
public function store(Request $request)
{ // データの作成 新規作成
Blog::create($request->only(['title', 'body']));
return to_route('blog.index');
}
public function update(Request $request, $id)
{ // データの更新処理
$blog = Blog::findOrFail($id);
$blog->update($request->only(['title', 'body']));
return to_route('blog.index');
}
public function destroy($id)
{ // データ削除処理
$blog = Blog::findOrFail($id);
$blog->delete();
return to_route('blog.index');
}
}
続いてview内にblogsという名前のindex.blade.phpを作成する
@extends('layouts.default')
@section('title', 'ブログ一覧')
@section('content')
<h1>ブログ一覧</h1>
<table border="1" cellpadding="8" cellspacing="0">
<tbody>
@foreach($items as $item)
<tr>
<td>{{ $item->title }}</td>
<td>{{ $item->body }}</td>
<td>
<a href="{{ route('blog.edit', $item->id) }}">編集</a>
<form action="{{ route('blog.destroy', $item->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" onclick="return confirm('削除してもよろしいですか?')">削除</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
@endsection
ルート情報を追加する
// use App\Http\Controllers\BlogController;を追記
Route::get('blog', [BlogControllser::class. 'index']);
Route::post('blog', [BlogController::class, 'store']);
Route::put('blog/{id}', [BlogController::class, 'update']);
Route::delete('blog/{id}', [BlogController::class, 'destroy']);
php artisan serverを実行し、/blog/indexにアクセスできることを確認する。
※今回データベースの一覧・カラム確認などはAdminerを利用しました。
http://localhost/adminer
バリデーション
Laravel では、FormRequest クラスで rules() メソッドを定義すると バリデーションルール を返すことが期待されています。
php artisan make:request ContactRequest
// バリデーションルール専用のContactRequestができる
FormRequest クラス
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ContactRequest extends FormRequest
{
public function authorize(): bool
{
return true; // 誰でも送信可能 :アクセス制御
}
public function rules(): array
{ // バリデーションの設定
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email'],
'body' => ['required', 'string', 'max:2000'],
];
}
}
namespace App\Http\Controllers;
use App\Http\Requests\ContactRequest;
class ContactController extends Controller
{
public function store(ContactRequest $request)
{
$data = $request->validated(); // バリデーション済みデータを取得
// DB保存やメール送信処理
return redirect()->back()->with('success', '送信しました!');
}
}
その他
サービスプロバイダ
アプリケーションの起動時に必要なサービスや機能をサービスコンテナに登録・初期化するための仕組みです
config/app.php内のproviders配列に設定
| register( ) | boot( ) | |
|---|---|---|
| 説明 | サービスコンテナにクラスやインターフェースをバインド(登録)する | アプリケーション起動後に実行される初期化処理を記述する |
| 具体的な場面例 | 外部APIクライアントの登録 | カスタムBladeディレクティブの追加 |
php artisan make:provider MyServiceprovider
public function register()
{
$this->app->singleton(WeatherClient::class, function ($app) {
return new WeatherClient(config('services.weather.api_key'));
});
}
// コントローラで WeatherClient を注入するとAPIが使用できる
public function boot()
{
Blade::directive('yen', function ($amount) {
return "<?php echo '¥' . number_format($amount); ?>";
});
}
// Blade側で @yen(1000) と書くだけで ¥1,000 と表示される
セッション
クライアントとサーバーの接続維持のための仕組み
ログイン状態やカートの中身など、状態を保持する必要がある場面で活躍します。
// msgという値を取り出す
$sesdata = $request->session()->get('msg', $msg);
// post送信したときの処理、セッションに保管する
$request->session()->put('msg');
| ドライバー | 特徴 |
|---|---|
| file | ローカルに保存 |
| cookie | クッキーに直接保存(暗号化) |
| database | DBに保存 |
| redis | 高速でスケーラブル |
| array | テスト用 |
ユーザー認証
Laravelにおけるユーザー認証は、ユーザー管理を支える重要な機能で、主に以下の3つの柱で構成されています。
- 認証(Authentication)
- 認可(Authorization)
- ユーザー登録
認証(Authentication)
// コントローラーの作成
php artisan make:controller Admin/AuthController
・ログイン処理の一例:
// ログインフォームの表示
public function showLoginForm()
{
return view('auth.login');
}
// ログイン処理
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
// ログイン中のユーザー情報を取得
if (Auth::attempt($credentials)) {
return redirect()->intended('/home');
}
return back()->withErrors([
'email' => '認証に失敗しました。',
]);
}
※よく使う検証メソッド
| 認証 | 機能説明 |
|---|---|
| Auth::routes( ) | 認証に必要なルートを一括定義 |
| Auth::user ( ) | 現在ログイン中のユーザー情報取得 |
| Auth::attempt( ) | ログイン認証を試みる |
| Auth::logout( ) | ログアウト処理 |
認可(Authorization)
ゲートの定義例:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
// 全認証/認可サービスの登録
public function boot(): void
{
Gate::define('isPremiumAuthor', function (User $user) {
// 両方がtrueの時だけ返す
return $user->is_premium && $user->is_author;
});
}
if (Gate::allows('isPremiumAuthor')) {
// 著者と一致する場合の処理
}
if (Gate::denies('isPremiumAuthor')) {
// 著者ではない場合の処理
}
※よく使う認可メソッド
| 認可 | 機能説明 |
|---|---|
Gate::define( ) |
ゲートを定義 |
$user->can('update', $post) |
認可チェック |
@can('update', $post) |
Bladeテンプレートでの認可 |
$this->authorize('update', $post) |
コントローラー内での認可 |
※Policyについては下記の記事が断然分かりやすいです。
ユーザー登録
1. 登録フォームを表示する
public function showRegistrationForm()
{
return view('auth.register');
}
2.登録処理のバリデーション、保存を行う
public function register(Request $request)
{ // 入力値のバリデーション
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8'],
]);
// ユーザー情報の保存
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
// 登録後に自動ログイン
Auth::login($user);
// リダイレクト処理
return return to_route('home');
}
3.ルーティングを設定する
Route::get('/register', [RegisterController::class, 'showRegistrationForm'])->name('register');
Route::post('/register', [RegisterController::class, 'register']);
※他参考資料
ユニットテスト
// テストの実行
php artisan test
コントローラーのテスト
ルートで設定したアドレスにアクセスして、期待度通りの結果が得られるかをテストする。
ダミーデータ生成など。
// 管理画面のブログ一覧にアクセス
$response = $this->get('/admin/blogs');
// ステータスコードが200(成功)であることを確認
$response->assertStatus(200);
// 表示された内容に「テストブログ」が含まれているか確認
$response->assertSee('テストブログ');
よく使うassertの一覧
| メソッド | 目的 |
|---|---|
| assertStatus(200) | 正常なHTTPレスポンスか確認 |
| assertRedirect() | 指定URLにリダイレクトされたか |
| assertViewls() | 指定ビューが表示されたか |
| assertStatus() | 存在しないページのチェック |
| assertSeeText() | コンテンツに含まれるテキスト |
※公式ドキュメント:詳しくは下記参照ください。
モデルのテストとシーティング
データの振る舞いを確認し、データの保存・取得・更新・削除を行う。
またリレーションの動作やバリデーションもテスト対象となる。
1.シーダーファイルを作成する
php artisan make:seeder SampleTableSeeder
2.作成されたdatabase/seeders/SampleTableSeeder.phpにデータを記述する
class SampleTableSeeder extends Seeder
{
public function run(): void
{
$samples = [
['title' => 'sample1'],
['title' => 'sample2'],
['title' => 'sample3'],
];
foreach ($samples as $sample) {
Sample::create($sample);
}
}
}
3.シーティングの実行対象として DatabaseSeederへ登録する
database/seeders/DatabaseSeeder.php
public function run(): void
{
$this->call(SampleTableSeeder::class);
}
4.シーティングを実行する
samples テーブルに sample1〜sample3 のデータが登録されます。
php artisan db:seed
まとめ
以上、Laravelを学ぶ中で、ビューの表示からコントローラーでの処理、ユーザー認証、さらにはテストに至るまで、非常に多くの機能が統合されていることに驚かされました。
特に、認証や認可の仕組みがフレームワークに自然に組み込まれており、セキュアなアプリケーションを効率的に構築できる点は大きな魅力です。
今後は、これらの機能を活かして、より実践的なWebアプリケーション開発に挑戦していきたいと思います。
※参考資料

