Laravel 13でMySQLを使う方法|WSL2から接続してCRUDを作成

はじめに

Laravel 13でWebアプリケーションを開発する場合、データベースとしてMySQLを使用したいケースは多いと思います。

Laravel 13では新規プロジェクト作成時にSQLiteが標準で設定されていますが、.envを変更することでMySQLへ簡単に切り替えることができます。

今回は、

  • Windows 11
  • WSL2
  • Ubuntu
  • Laravel 13
  • MySQL

という環境でMySQLをインストールし、Laravel 13から接続します。

さらに、接続確認だけではなく、商品データを例にして、

登録(Create)・一覧表示(Read)・更新(Update)・削除(Delete)

までのCRUD処理を作成します。

Laravel 13でMySQLを使ったWebアプリケーションを開発したい方は参考にしてください。


今回作成するもの

今回は簡単な商品管理機能を作成します。

商品には以下の3項目を持たせます。

  • 商品名
  • 価格
  • 在庫数

最終的に次の操作ができるようにします。

  • 商品一覧を表示する
  • 商品を新規登録する
  • 商品を編集する
  • 商品を削除する

LaravelのModel、Migration、Controller、Blade、Routeを使用して実装します。


開発環境

今回の環境は以下を想定しています。

OS:Windows 11
Linux:WSL2 / Ubuntu
Framework:Laravel 13
Database:MySQL
PHP:Laravel 13が動作するPHP環境

すでにLaravel 13のプロジェクトが作成されている前提で進めます。

プロジェクト名は例として、

laravel-mysql-app

とします。

WSL2上でLaravel 13をまだインストールしていない場合は、先にLaravelの開発環境を構築してください。


1. WSL2にMySQLをインストールする

まずWSL2のUbuntuを起動します。

パッケージ情報を更新します。

sudo apt update

続いてMySQL Serverをインストールします。

sudo apt install mysql-server

途中で確認された場合は、

Y

を入力します。

インストールが完了したらMySQLのバージョンを確認します。

mysql --version

バージョン情報が表示されればMySQLのインストールは完了です。


2. MySQLが起動しているか確認する

次のコマンドを実行します。

sudo systemctl status mysql

正常に起動していれば、

active (running)

のように表示されます。

停止している場合は、次のコマンドで起動します。

sudo systemctl start mysql

再度、

sudo systemctl status mysql

を実行して確認します。

WSL2の環境によってはsystemdの設定が必要になる場合があります。


3. MySQLへログインする

UbuntuからMySQLへログインします。

sudo mysql

次のような表示になればログイン成功です。

mysql>

現在作成されているデータベースを確認してみます。

SHOW DATABASES;

4. Laravel用のデータベースを作成する

今回はLaravel用として、

laravel_crud

というデータベースを作成します。

MySQL上で次を実行します。

CREATE DATABASE laravel_crud
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

作成されたことを確認します。

SHOW DATABASES;

一覧に、

laravel_crud

が表示されれば成功です。


5. Laravel用MySQLユーザーを作成する

開発環境であっても、LaravelからMySQLへ接続するためのユーザーを作成しておくと管理しやすくなります。

今回は、

ユーザー名:laravel_user
パスワード:任意の強いパスワード

として作成します。

例えば次のように実行します。

CREATE USER 'laravel_user'@'localhost'
IDENTIFIED BY 'your_secure_password';

作成したユーザーへlaravel_crudデータベースの権限を付与します。

GRANT ALL PRIVILEGES
ON laravel_crud.*
TO 'laravel_user'@'localhost';

権限を反映します。

FLUSH PRIVILEGES;

MySQLから退出します。

EXIT;

6. Laravel 13の.envをMySQL用に変更する

Laravelプロジェクトへ移動します。

cd ~/laravel-mysql-app

Laravel 13の新規プロジェクトではSQLiteが設定されている場合があります。

.envを開き、データベース設定をMySQL用に変更します。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_crud
DB_USERNAME=laravel_user
DB_PASSWORD=your_secure_password

ここで重要なのが、

DB_CONNECTION=mysql

です。

これによってLaravelがMySQLを使用するようになります。


7. Laravelの設定キャッシュをクリアする

.envを変更したあと、設定キャッシュが残っている場合があります。

念のため次のコマンドを実行します。

php artisan config:clear

続いて、

php artisan cache:clear

も実行しておきます。


8. LaravelからMySQLへ接続できるか確認する

LaravelからMySQLへ正常に接続できるか確認します。

php artisan migrate

正常であればLaravel標準のMigrationが実行されます。

例えば、

INFO  Running migrations.

などと表示されます。

MySQL側から確認したい場合は、

mysql -u laravel_user -p

でログインします。

パスワードを入力後、

USE laravel_crud;

続いて、

SHOW TABLES;

を実行します。

Laravelによって作成されたテーブルが表示されれば、

Laravel 13 → MySQL

の接続は成功しています。


Laravel 13でCRUDを作成する

ここから実際にCRUDを作成します。

今回は、

products

テーブルを作成します。


9. ProductモデルとMigrationを作成する

次のArtisanコマンドを実行します。

php artisan make:model Product -m

これによって、

app/Models/Product.php

と、

database/migrations/

以下にMigrationファイルが作成されます。


10. productsテーブルを作成する

作成されたMigrationファイルを開きます。

ファイル名は実行日時によって異なります。

database/migrations/xxxx_xx_xx_xxxxxx_create_products_table.php

up()を次のようにします。

Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->unsignedInteger('price');
    $table->unsignedInteger('stock')->default(0);
    $table->timestamps();
});

今回作成する項目は、

id
name
price
stock
created_at
updated_at

です。

Migrationを実行します。

php artisan migrate

正常に実行されればproductsテーブルが作成されます。


11. Productモデルを設定する

app/Models/Product.phpを開きます。

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = [
        'name',
        'price',
        'stock',
    ];
}

$fillableには、一括代入を許可するカラムを指定しています。

今回は、

name
price
stock

を登録・更新できるようにします。


12. ProductControllerを作成する

CRUD処理を行うControllerを作成します。

php artisan make:controller ProductController --resource

これによって、

app/Http/Controllers/ProductController.php

が作成されます。

--resourceを付けることでCRUDで使用する基本的なメソッドが生成されます。


13. 商品一覧を取得する

ProductController.phpを編集します。

まずProductモデルを読み込みます。

use App\Models\Product;
use Illuminate\Http\Request;

index()を次のようにします。

public function index()
{
    $products = Product::orderBy('id', 'desc')->get();

    return view('products.index', compact('products'));
}

これでproductsテーブルの商品を取得できます。


14. 商品登録画面を作成する

create()を次のようにします。

public function create()
{
    return view('products.create');
}

続いてstore()を作成します。

public function store(Request $request)
{
    $validated = $request->validate([
        'name' => ['required', 'string', 'max:255'],
        'price' => ['required', 'integer', 'min:0'],
        'stock' => ['required', 'integer', 'min:0'],
    ]);

    Product::create($validated);

    return redirect()
        ->route('products.index')
        ->with('success', '商品を登録しました。');
}

ここではバリデーションも設定しています。

商品名は必須、価格と在庫数は0以上の整数としています。


15. 商品編集処理を作成する

edit()を作成します。

public function edit(Product $product)
{
    return view('products.edit', compact('product'));
}

Laravelのルートモデルバインディングを利用して、URLのIDに対応するProductを取得します。

続いてupdate()です。

public function update(Request $request, Product $product)
{
    $validated = $request->validate([
        'name' => ['required', 'string', 'max:255'],
        'price' => ['required', 'integer', 'min:0'],
        'stock' => ['required', 'integer', 'min:0'],
    ]);

    $product->update($validated);

    return redirect()
        ->route('products.index')
        ->with('success', '商品を更新しました。');
}

16. 商品削除処理を作成する

destroy()を作成します。

public function destroy(Product $product)
{
    $product->delete();

    return redirect()
        ->route('products.index')
        ->with('success', '商品を削除しました。');
}

これで削除処理も完成です。


ProductController全体

最終的なProductController.phpは次のようになります。

<?php

namespace App\Http\Controllers;

use App\Models\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::orderBy('id', 'desc')->get();

        return view('products.index', compact('products'));
    }

    public function create()
    {
        return view('products.create');
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'price' => ['required', 'integer', 'min:0'],
            'stock' => ['required', 'integer', 'min:0'],
        ]);

        Product::create($validated);

        return redirect()
            ->route('products.index')
            ->with('success', '商品を登録しました。');
    }

    public function edit(Product $product)
    {
        return view('products.edit', compact('product'));
    }

    public function update(Request $request, Product $product)
    {
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'price' => ['required', 'integer', 'min:0'],
            'stock' => ['required', 'integer', 'min:0'],
        ]);

        $product->update($validated);

        return redirect()
            ->route('products.index')
            ->with('success', '商品を更新しました。');
    }

    public function destroy(Product $product)
    {
        $product->delete();

        return redirect()
            ->route('products.index')
            ->with('success', '商品を削除しました。');
    }
}

17. Routeを設定する

routes/web.phpを開きます。

<?php

use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;

Route::resource('products', ProductController::class);

Route::resource()を使用することでCRUD用のRouteをまとめて登録できます。

登録されたRouteは次のコマンドで確認できます。

php artisan route:list

productsに関連するRouteが表示されれば正常です。


18. Bladeファイルを作成する

次のディレクトリを作成します。

resources/views/products

その中に、

index.blade.php
create.blade.php
edit.blade.php

を作成します。


19. 商品一覧画面を作成する

resources/views/products/index.blade.phpを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>商品一覧</title>
</head>

<body>

<h1>商品一覧</h1>

@if (session('success'))
    <p>{{ session('success') }}</p>
@endif

<p>
    <a href="{{ route('products.create') }}">
        商品を登録する
    </a>
</p>

<table border="1" cellpadding="10">
    <thead>
        <tr>
            <th>ID</th>
            <th>商品名</th>
            <th>価格</th>
            <th>在庫数</th>
            <th>操作</th>
        </tr>
    </thead>

    <tbody>

    @forelse ($products as $product)

        <tr>
            <td>{{ $product->id }}</td>

            <td>{{ $product->name }}</td>

            <td>
                {{ number_format($product->price) }}円
            </td>

            <td>
                {{ $product->stock }}
            </td>

            <td>

                <a href="{{ route('products.edit', $product) }}">
                    編集
                </a>

                <form
                    action="{{ route('products.destroy', $product) }}"
                    method="POST"
                    style="display:inline;"
                >

                    @csrf
                    @method('DELETE')

                    <button
                        type="submit"
                        onclick="return confirm('削除しますか?')"
                    >
                        削除
                    </button>

                </form>

            </td>
        </tr>

    @empty

        <tr>
            <td colspan="5">
                商品が登録されていません。
            </td>
        </tr>

    @endforelse

    </tbody>
</table>

</body>
</html>

20. 商品登録画面を作成する

resources/views/products/create.blade.phpを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>商品登録</title>
</head>

<body>

<h1>商品登録</h1>

@if ($errors->any())

    <ul>

        @foreach ($errors->all() as $error)

            <li>
                {{ $error }}
            </li>

        @endforeach

    </ul>

@endif

<form
    action="{{ route('products.store') }}"
    method="POST"
>

    @csrf

    <div>
        <label>商品名</label>

        <input
            type="text"
            name="name"
            value="{{ old('name') }}"
        >
    </div>

    <div>
        <label>価格</label>

        <input
            type="number"
            name="price"
            value="{{ old('price') }}"
            min="0"
        >
    </div>

    <div>
        <label>在庫数</label>

        <input
            type="number"
            name="stock"
            value="{{ old('stock', 0) }}"
            min="0"
        >
    </div>

    <button type="submit">
        登録
    </button>

</form>

<p>
    <a href="{{ route('products.index') }}">
        商品一覧へ戻る
    </a>
</p>

</body>
</html>

21. 商品編集画面を作成する

resources/views/products/edit.blade.phpを作成します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>商品編集</title>
</head>

<body>

<h1>商品編集</h1>

@if ($errors->any())

    <ul>

        @foreach ($errors->all() as $error)

            <li>
                {{ $error }}
            </li>

        @endforeach

    </ul>

@endif

<form
    action="{{ route('products.update', $product) }}"
    method="POST"
>

    @csrf
    @method('PUT')

    <div>
        <label>商品名</label>

        <input
            type="text"
            name="name"
            value="{{ old('name', $product->name) }}"
        >
    </div>

    <div>
        <label>価格</label>

        <input
            type="number"
            name="price"
            value="{{ old('price', $product->price) }}"
            min="0"
        >
    </div>

    <div>
        <label>在庫数</label>

        <input
            type="number"
            name="stock"
            value="{{ old('stock', $product->stock) }}"
            min="0"
        >
    </div>

    <button type="submit">
        更新
    </button>

</form>

<p>
    <a href="{{ route('products.index') }}">
        商品一覧へ戻る
    </a>
</p>

</body>
</html>

22. Laravelを起動する

Laravelの開発サーバーを起動します。

php artisan serve

ブラウザから、

http://127.0.0.1:8000/products

へアクセスします。

商品一覧画面が表示されれば成功です。

「商品を登録する」をクリックして、

商品名:ノートパソコン
価格:120000
在庫数:5

などを登録してみます。

商品一覧に表示されればMySQLへの保存も正常に行われています。


23. MySQLに本当に登録されているか確認する

MySQLへ直接ログインして確認することもできます。

mysql -u laravel_user -p

ログイン後、

USE laravel_crud;

続いて、

SELECT * FROM products;

を実行します。

Laravelから登録した商品が表示されれば正常です。


LaravelからMySQLへ接続できない場合

Laravel 13からMySQLへ接続する際、いくつかのエラーが発生する場合があります。

代表的なものを紹介します。


SQLSTATE[HY000] [2002] Connection refused

例えば、

SQLSTATE[HY000] [2002] Connection refused

が発生した場合、まずMySQLが起動しているか確認します。

sudo systemctl status mysql

停止している場合は、

sudo systemctl start mysql

で起動します。

.envの設定も確認します。

DB_HOST=127.0.0.1
DB_PORT=3306

Access denied for userが発生する場合

例えば、

Access denied for user 'laravel_user'@'localhost'

が表示された場合は、

  • ユーザー名
  • パスワード
  • MySQLユーザーの権限

を確認します。

Laravelの.envとMySQLで作成したユーザー情報が一致している必要があります。

設定変更後は、

php artisan config:clear

を実行してください。


Unknown databaseが発生する場合

例えば、

Unknown database 'laravel_crud'

と表示された場合、指定したデータベースが存在していない可能性があります。

MySQLへログインして、

SHOW DATABASES;

を実行します。

存在しなければ、

CREATE DATABASE laravel_crud
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

で作成します。


could not find driverが発生する場合

環境によっては、

could not find driver

と表示されることがあります。

この場合はPHPのMySQL拡張が利用できるか確認します。

php -m | grep -i mysql

例えば、

mysqli
pdo_mysql

などが表示されるか確認してください。

pdo_mysqlが存在しない場合は、使用しているPHPバージョンに対応したMySQL拡張をインストールする必要があります。


migrateをやり直したい場合

開発中にMigrationをすべて削除して作り直したい場合は、

php artisan migrate:fresh

を使用できます。

ただし、このコマンドは既存テーブルを削除して作り直すため、

登録済みデータも削除されます。

本番環境では不用意に実行しないよう注意してください。


Laravel 13 + MySQLでCRUDを作る基本的な流れ

今回行った処理をまとめると次のようになります。

WSL2
 ↓
Ubuntu
 ↓
MySQLインストール
 ↓
データベース作成
 ↓
MySQLユーザー作成
 ↓
Laravel .env設定
 ↓
php artisan migrate
 ↓
Model作成
 ↓
Migration作成
 ↓
Controller作成
 ↓
Route設定
 ↓
Blade作成
 ↓
CRUD完成

LaravelではModelとEloquent ORMを使用することで、SQLを直接記述しなくてもデータベースを操作できます。

例えば一覧取得は、

Product::all();

登録は、

Product::create($validated);

更新は、

$product->update($validated);

削除は、

$product->delete();

のように記述できます。

Laravelを使う大きなメリットの一つです。


実際の業務システムではここから機能を追加する

今回作った商品CRUDは非常にシンプルですが、基本的な構造は在庫管理システムや顧客管理システムなどでも同じです。

例えば商品管理であれば、ここから、

  • 商品コード
  • 商品カテゴリー
  • 仕入価格
  • 販売価格
  • 入庫数
  • 出庫数
  • 現在庫
  • 発注点
  • 仕入先

などを追加できます。

さらに、

商品マスタ
    ↓
入庫データ
    ↓
出庫データ
    ↓
在庫数計算

と発展させれば、Laravelを利用した在庫管理システムを構築できます。

Excelで管理していた在庫表をLaravelとMySQLによるWebシステムへ移行する場合にも、今回紹介したCRUDが基本となります。


まとめ

今回は、Laravel 13でMySQLを使用する方法について、WSL2へのMySQLインストールからCRUD作成まで紹介しました。

基本的な手順は、

1. WSL2へMySQLをインストール
2. Laravel用データベースを作成
3. Laravel用MySQLユーザーを作成
4. .envをMySQL用に変更
5. php artisan migrateを実行
6. ModelとMigrationを作成
7. Controllerを作成
8. Routeを設定
9. Bladeを作成
10. CRUDを実装

となります。

LaravelとMySQLを接続できるようになると、

  • 在庫管理システム
  • 顧客管理システム
  • 見積管理システム
  • 予約管理システム
  • 案件管理システム
  • 営業管理システム

など、さまざまな業務システムへ発展させることができます。

Laravelを学習する場合も、データベース接続だけで終わらせず、今回のようにCRUDを一度作成してみることで、Model・Migration・Controller・Route・Viewの関係を理解しやすくなります。