Laravelは、変化のめまぐるしいウェブ開発業界において、モダンかつダイナミックなウェブアプリケーションを構築するのに便利な人気のPHPフレームワークです。Laravel Eloquentオブジェクト関係マッピング(ORM)の一種であり、これを使うことでデータベースの作成、読み取り、更新、削除(CRUD)操作を効率的に行うことができます。

この記事では、LaravelのEloquent ORMを使用してLaravelアプリケーションでこの操作を実行する方法と、MyKinstaを使用してLaravel CRUDアプリケーションをデプロイする方法をご紹介します。

LaravelのCRUD機能

CRUD操作は、データベース駆動型アプリケーションに欠かせない概念です。レコードの作成、既存のレコードの読み取り、更新や削除など、基本的かつ不可欠なデータベースの操作を実行することができます。これらの操作は、データベースとやり取りするLaravelアプリケーションにとって非常に重要です。

Eloquentは、データベースとの直感的な対話を可能にするもので、データベース管理の複雑さを軽減しアプリケーション構築への専念を後押しします。組み込みのメソッドとクラスにより、データベースのレコードに対して簡単にCRUD操作を実行できます。

前提条件

この説明を読み進めるには、以下のものが必要です。

ステップ

  1. Laravelをインストールしアプリケーションを作成する
  2. データベースを作成する
  3. テーブルを作成する
  4. コントローラを作成する
  5. モデルを設定する
  6. ルートを追加する
  7. Bladeファイルを生成する
  8. CRUDアプリケーションのデプロイとテスト

今回の説明で使っているコードはこちらで公開しています。

Laravelをインストールしアプリケーションを作成する

Laravelアプリケーションを作成するには、まずターミナルを開き以下の手順に従ってください。

  1. Laravelをインストールするために、以下を実行します。
composer global require laravel/installer
  1. Laravelアプリケーションを作成するには、以下を実行します。
laravel new crudposts

データベースの作成

アプリケーションのデータベースを作成します。

  1. XAMPPコントロールパネルでApacheとMySQLサーバーを起動し、ブラウザでhttp://localhost/phpmyadminにアクセスします。
  1. 左サイドバーの「新規作成」をクリックしてください。以下のように表示されるはずです。
データベースの作成に使えるフォーム
データベースの作成フォーム
  1. データベース名を追加し、「作成」をクリックします。
  1. Laravelアプリケーションのルートにあるアプリケーションの.envファイルを編集します。このファイルには、アプリケーションで使用するすべての環境変数が含まれます。DB_というプレフィックスが付いた変数を探し、データベースの認証情報を入れて編集してください。
DB_CONNECTION=
DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=

テーブルの作成

アプリケーションのデータはテーブルに格納されます。このアプリケーションに必要なテーブルは1つだけで、Laravelのマイグレーションを使って作成します。

  1. Laravelのコマンドラインインターフェース、Artisanを使用してテーブル、マイグレーションファイルを生成するには、以下を実行します。
php artisan make:migration create_posts_table

上記のコマンドで新しいファイルとして…

yyyy_mm_dd_hhhmmss_create_posts_table.phpが database/migrationsに作成されます。

  1. yyyy_mm_dd_hhhmmss_create_posts_table.phpを開き、up関数でデータベーステーブル内に必要なカラムを定義します。
public function up()
{
  Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();
  });
}

このコードでpostsテーブルの内容を定義します。idtitlebodytimestampsの4つのカラムがあります。

  1. database/migrationsフォルダにあるmigrationsファイルを実行して、データベースにテーブルを作成します。
php artisan migrate

出力は次のようになります。

マイグレーション実行の結果
マイグレーションを実行する
  1. 先ほど作成したデータベースにアクセスし、テーブルが作成されていることを確認してみましょう。
テーブルを作成した結果
テーブルを作成

コントローラを作成する

コントローラには、データベースの投稿(posts)をCRUD操作する関数が含まれます。

Artisanを使用してLaravelアプリケーション内にコントローラファイルを生成しましょう。

php artisan make:controller PostController --api

このコマンドを実行すると、app/Http/ControllersPostController.phpファイルが作成され、ボイラープレートコードと空の関数宣言indexstoreshowupdatedestroyが用意できます。

関数の作成

次に、データの保存、インデックス化、更新、破棄、作成、表示、編集を行う関数を作成します。

これらの関数を以下にあるようにapp/Http/Controller/PostController.phpに追加します。

store関数

store関数は、投稿をデータベースに追加します。

store関数までスクロールし、空白の中括弧内に次のコードを追加します。

$request->validate([
  'title' => 'required|max:255',
  'body' => 'required',
]);
Post::create($request->all());
return redirect()->route('posts.index')
  ->with('success','Post created successfully.');

このコードは、投稿のタイトルと本文を含むオブジェクトを受け取り、データを検証し、データが有効であれば新しい投稿をデータベースに追加し、完了のメッセージとともにユーザーをホームページにリダイレクトします。

index関数

index関数はデータベースからすべての投稿を取得し、データをposts.indexページに送信するものです。

update関数

update関数には、更新する投稿のid、新しい投稿のtitle、そしてbodyが含まれます。 データを検証した後、同じidを持つ投稿を見つけます。見つかった場合、update関数によりデータベース内の投稿を新しいtitlebodyに変更します。そして、完了のメッセージとともにユーザーをホームページにリダイレクトします。

destroy関数

destroy関数は、指定されたidを持つ投稿を見つけてデータベースから削除し、完了のメッセージとともにユーザーをホームページにリダイレクトします。

ここまでで、データベースの投稿にCRUD操作を実行する関数をご紹介しました。resources/views/posts/にページをレンダリングするには、コントローラ内部でさらに関数を定義する必要があります。

create関数

create関数はresources/views/posts/create.blade.phpページ(投稿をデータベースに追加するフォームが含まれる)をレンダリングします。

show関数

show関数はデータベースで指定されたidを持つ投稿を見つけ、投稿を伴うかたちで resources/views/posts/show.blade.phpファイルをレンダリングします

edit関数

edit関数はデータベースにある指定されたidを持つ投稿を見つけ、投稿の詳細と共にresources/views/posts/edit.blade.phpファイルをレンダリングします。

モデルのセットアップ

Postモデルはデータベースのpostsテーブルとやりとりします。

  1. Artisanでモデルを作成するには、以下を実行します。
php artisan make:model Post

このコードはApp/Modelsフォルダ内にPost.phpファイルを作成します。

  1. fillable配列を作成します。Postクラスの中、use HasFactory;の下に以下のコードを追加します。
protected $fillable = [
  'title',
  'body',
];

このコードは、fillable配列を作成し、Laravelアプリケーションからデータベースに項目を追加できるようにします。

  1. PostモデルをPostController.phpファイルに接続します。PostController.phpを開き、use Illuminate\Http\Request;の下に行を追加します。以下のようになります。
use Illuminate\Http\Request;
use App\Models\Post;

PostController.phpファイルは次のようになります。

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    $posts = Post::all();
    return view('posts.index', compact('posts'));
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    $request->validate([
      'title' => 'required|max:255',
      'body' => 'required',
    ]);
    Post::create($request->all());
    return redirect()->route('posts.index')
      ->with('success', 'Post created successfully.');
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, $id)
  {
    $request->validate([
      'title' => 'required|max:255',
      'body' => 'required',
    ]);
    $post = Post::find($id);
    $post->update($request->all());
    return redirect()->route('posts.index')
      ->with('success', 'Post updated successfully.');
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function destroy($id)
  {
    $post = Post::find($id);
    $post->delete();
    return redirect()->route('posts.index')
      ->with('success', 'Post deleted successfully');
  }
  // routes functions
  /**
   * Show the form for creating a new post.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    return view('posts.create');
  }
  /**
   * Display the specified resource.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function show($id)
  {
    $post = Post::find($id);
    return view('posts.show', compact('post'));
  }
  /**
   * Show the form for editing the specified post.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function edit($id)
  {
    $post = Post::find($id);
    return view('posts.edit', compact('post'));
  }
}

ルートの追加

コントローラ関数とPostモデルを作成したら、 コントローラ関数用のルートを追加する必要があります

  1. routes/web.phpを開き、アプリケーションが生成したboilerplateルートを削除します。以下のコードに置き換えて、コントローラ関数をそれぞれのルートに接続します。
// returns the home page with all posts
Route::get('/', PostController::class .'@index')->name('posts.index');
// returns the form for adding a post
Route::get('/posts/create', PostController::class . '@create')->name('posts.create');
// adds a post to the database
Route::post('/posts', PostController::class .'@store')->name('posts.store');
// returns a page that shows a full post
Route::get('/posts/{post}', PostController::class .'@show')->name('posts.show');
// returns the form for editing a post
Route::get('/posts/{post}/edit', PostController::class .'@edit')->name('posts.edit');
// updates a post
Route::put('/posts/{post}', PostController::class .'@update')->name('posts.update');
// deletes a post
Route::delete('/posts/{post}', PostController::class .'@destroy')->name('posts.destroy');
  1. ルートを接続するには、app/Http/Controllers/PostController.phpを開き、以下のコードをuse Illuminate\Support\Facades\Route;の下に追加します。
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;

routes/web.phpファイルはこのようになります。

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
// returns the home page with all posts
Route::get('/', PostController::class .'@index')->name('posts.index');
// returns the form for adding a post
Route::get('/posts/create', PostController::class . '@create')->name('posts.create');
// adds a post to the database
Route::post('/posts', PostController::class .'@store')->name('posts.store');
// returns a page that shows a full post
Route::get('/posts/{post}', PostController::class .'@show')->name('posts.show');
// returns the form for editing a post
Route::get('/posts/{post}/edit', PostController::class .'@edit')->name('posts.edit');
// updates a post
Route::put('/posts/{post}', PostController::class .'@update')->name('posts.update');
// deletes a post
Route::delete('/posts/{post}', PostController::class .'@destroy')->name('posts.destroy');

Bladeファイルの生成

ルートができたので、Laravel Bladeファイルを作成します。Artisanを使用してBladeファイルを生成する前に、make:viewコマンドを実行します。これを使ってblade.phpファイルを生成することができます。

  1. CLIで以下のコードを実行し、app/Console/Commandsフォルダ内にMakeViewCommandコマンドファイルを作成します。
php artisan make:command MakeViewCommand
  1. MakeViewCommandファイルのコードを以下のように置き換えて、CLIから.blade.phpファイルを生成するコマンドを作成します。
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use File;
class MakeViewCommand extends Command
{
  /**
   * The name and signature of the console command.
   *
   * @var string
   */
  protected $signature = 'make:view {view}';
  /**
   * The console command description.
   *
   * @var string
   */
  protected $description = 'Create a new blade template.';
  /**
   * Execute the console command.
   *
   * @return mixed
   */
  public function handle()
  {
    $view = $this->argument('view');
    $path = $this->viewPath($view);
    $this->createDir($path);
    if (File::exists($path))
    {
        $this->error("File {$path} already exists!");
        return;
    }
    File::put($path, $path);
    $this->info("File {$path} created.");
  }
  /**
   * Get the view full path.
   *
   * @param string $view
   *
   * @return string
   */
  public function viewPath($view)
  {
    $view = str_replace('.', '/', $view) . '.blade.php';
    $path = "resources/views/{$view}";
    return $path;
  }
  /**
   * Create a view directory if it does not exist.
   *
   * @param $path
   */
  public function createDir($path)
  {
    $dir = dirname($path);
    if (!file_exists($dir))
    {
        mkdir($dir, 0777, true);
    }
  }
}

ホームページの作成

次に、ホームページを作成します。ホームページはindex.blade.phpファイルです。ここにすべての投稿を一覧表示します。

  1. ホームページを作成するには、以下を実行します。
php artisan make:view posts.index

これにより、/resources/viewsフォルダ内にpostsフォルダが、そしてその下にindex.blade.phpファイルが作成されます。結果のパスは/resources/views/posts/index.blade.phpになります。

  1. index.blade.phpファイル内に以下のコードを追加します。
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
  <title>Posts</title>
</head>
<body>
  <nav class="navbar navbar-expand-lg navbar-light bg-warning">
    <div class="container-fluid">
      <a class="navbar-brand h1" href={{ route('posts.index') }}>CRUDPosts</a>
      <div class="justify-end ">
        <div class="col ">
          <a class="btn btn-sm btn-success" href={{ route('posts.create') }}>Add Post</a>
        </div>
      </div>
    </div>
  </nav>
  <div class="container mt-5">
    <div class="row">
      @foreach ($posts as $post)
        <div class="col-sm">
          <div class="card">
            <div class="card-header">
              <h5 class="card-title">{{ $post->title }}</h5>
            </div>
            <div class="card-body">
              <p class="card-text">{{ $post->body }}</p>
            </div>
            <div class="card-footer">
              <div class="row">
                <div class="col-sm">
                  <a href="{{ route('posts.edit', $post->id) }}"
            class="btn btn-primary btn-sm">Edit</a>
                </div>
                <div class="col-sm">
                    <form action="{{ route('posts.destroy', $post->id) }}" method="post">
                      @csrf
                      @method('DELETE')
                      <button type="submit" class="btn btn-danger btn-sm">Delete</button>
                    </form>
                </div>
              </div>
            </div>
          </div>
        </div>
      @endforeach
    </div>
  </div>
</body>
</html>

上記のコードは、スタイリングにBootstrapを使用したシンプルなHTMLページを作成します。@foreach Bladeヘルパーを使用して、ナビゲーションバーと、データベース内のすべての投稿の詳細と2つの操作ボタン(編集と削除)を表示するグリッドテンプレートになります。

「Edit(編集)」ボタンは「Edit post(投稿の編集)」ページにリンクされ、そこで投稿を編集できます。「Delete(削除)」ボタンをクリックすると、DELETEメソッドで{{ route('posts.destroy', $post->id) }}を使用しデータベースから投稿を削除することができます。

)すべてのファイルのナビゲーションバーのコードは先のファイルと同じものを使用しています。

  1. create.blade.phpページを作成します。createというBladeファイルは、投稿をデータベースに追加するものです。以下のコマンドを使用してファイルを生成します。
php artisan make:view posts.create

これにより、 /resources/views/postsフォルダ内にcreate.blade.phpファイルが生成されます。

  1. 以下のコードをcreate.blade.phpファイルに追加します。
// same as the previous file. Add the following after the nav tag and before the closing body tag.
<div class="container h-100 mt-5">
  <div class="row h-100 justify-content-center align-items-center">
    <div class="col-10 col-md-8 col-lg-6">
      <h3>Add a Post</h3>
      <form action="{{ route('posts.store') }}" method="post">
        @csrf
        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" class="form-control" id="title" name="title" required>
        </div>
        <div class="form-group">
          <label for="body">Body</label>
          <textarea class="form-control" id="body" name="body" rows="3" required></textarea>
        </div>
        <br>
        <button type="submit" class="btn btn-primary">Create Post</button>
      </form>
    </div>
  </div>
</div>

上記のコードにより、titlebodyフィールドを持つフォームと、POSTメソッドの{{ route('posts.store') }}を通してデータベースに投稿を追加するsubmitボタンが作成されます。

  1. データベースの投稿を編集する「Edit post(投稿の編集)」ページを作ります。ファイルを生成するために次のコマンドを使います。
php artisan make:view posts.edit

これにより、/resources/views/postsフォルダ内にedit.blade.phpファイルが作成されます。

  1. edit.blade.phpファイルに以下のコードを追加します。
<div class="container h-100 mt-5">
  <div class="row h-100 justify-content-center align-items-center">
    <div class="col-10 col-md-8 col-lg-6">
      <h3>Update Post</h3>
      <form action="{{ route('posts.update', $post->id) }}" method="post">
        @csrf
        @method('PUT')
        <div class="form-group">
          <label for="title">Title</label>
          <input type="text" class="form-control" id="title" name="title"
            value="{{ $post->title }}" required>
        </div>
        <div class="form-group">
          <label for="body">Body</label>
          <textarea class="form-control" id="body" name="body" rows="3" required>{{ $post->body }}</textarea>
        </div>
        <button type="submit" class="btn mt-3 btn-primary">Update Post</button>
      </form>
    </div>
  </div>
</div>

上記のコードにより、titlebodyフィールドを持つフォームと、PUTメソッドの{{ route('posts.update') }}を通してデータベース内の指定されたidを持つ投稿を編集する投稿ボタンが作成されます。

  1. 次に、以下のコードを使ってアプリケーションサーバーを再起動します。
php artisan serve

ブラウザでhttp://127.0.0.1:8000を開きブログを表示してみましょう。記事を追加するには、「Add Post」ボタンをクリックします。

CRUDアプリケーションのデプロイとテスト

以下のように、アプリケーションをデプロイする準備をします。

  1. publicフォルダを宣言することで、デプロイがスムーズかつ簡単になります。アプリケーションフォルダのルートに.htaccessファイルを追加しましょう。
<IfModule mod_rewrite.c >
  RewriteEngine On
  RewriteRule ^(.*)$ public/$1 [L]
</IfModule >
  1. routes/web.phpファイル内のroutesの上に以下のコードを追加して、アプリでのHTTPS接続を強制します。
use Illuminate\Support\Facades\URL;
URL::forceScheme('https');
  1. コードをGitリポジトリにプッシュします。KinstaはGitHub、GitLab、Bitbucketからのデプロイをサポートしています。

MyKinstaでプロジェクトをセットアップする

  1. まだお持ちでない場合は、MyKinstaアカウントを作成してください。
  1. アカウントにログインし、ダッシュボードの「サービスを追加」ボタンをクリックして、アプリケーションを新規作成します。
  1. 初めてアプリを作成する場合は、GitHub、GitLab、または Bitbucket アカウントに接続し、特定のパーミッションを付与してください。
  1. フォームに必要事項を記入し、APP_KEYを追加してください。.envファイルで対応する値を確認することができます。
  1. ビルドリソースを選択し、アプリケーションのビルドパスを使用するか、Dockerfileを使用してアプリケーションをビルドするかを選択します。このデモでは、リポジトリに基づき自動でアプリのビルドを行います。
  1. デプロイ時に実行するさまざまなプロセスを指定します。この時点では空白のままで構いません。
  1. 最後に、お支払い方法を追加します。

お支払い方法の確認後、MyKinstaのシステムによりアプリケーションがデプロイされ、以下のようにURLが割り当てられます。

MyKinstaでのデプロイ完了の表示
デプロイ完了

リンクにアクセスすることはできますが、アプリが動作するためには有効なデータベース接続が必要なため、500 | Server Errorページが表示されます。次のセクションでこの問題を解決します。

MyKinsta経由でデータベースを作成する

  1. データベースを作成するには、MyKinstaダッシュボードに行き、「サービスを追加」をクリックします。
  1. データベース」を選択し、希望のデータベース名、タイプ、ユーザー名、パスワードをフォームに入力します。アプリケーションに合ったデータセンターの場所とデータベースサイズを追加します。
  1. 次のページでは、費用の概要とお支払い方法が表示されます。「データベースを作成する」をクリックしてプロセスを完了します。
  1. データベースを作成すると、MyKinstaのサービス一覧が表示されます。作成したデータベースをクリックし、「外部接続」までスクロールし、データベースの認証情報をコピーします。
  1. アプリケーションの「デプロイメント」ページに戻り、「設定」をクリックします。そして、「環境変数」までスクロールし、「環境変数を追加」をクリックします。以下の順序でデータベースの認証情報を環境変数として追加してください。
DB_CONNECTION=mysql
DB_HOST=External hostname
DB_PORT=External port
DB_DATABASE=Database name
DB_USERNAME=Username
DB_PASSWORD=Password

アプリケーションの環境変数一覧がこのようになるはずです。

.env環境変数一覧
.env変数
  1. アプリケーションの「デプロイメント」ページに行き、「デプロイする」ボタンをクリックして手動でアプリケーションをデプロイし、変更内容を適用します。これで、データベースの作成とアプリケーションへの接続ができました。
  1. 最後に、MyKinstaのデータベースでテーブルを作成するには、.envファイルを先ほどと同じ認証情報を使って編集し、次のコマンドを実行してデータベースをローカルアプリに接続します。
php artisan migrate

このコマンドですべてのマイグレーションファイルが実行されます。これは、MyKinstaアプリケーションで定義されたすべてのテーブルを作成するものです。

これで、最初のデプロイ後に割り当てられたURLでアプリケーションをテストすることができます。

まとめ

Laravelは、CRUD機能を必要とする堅牢でスケーラブルなウェブアプリケーションを作成するのに便利な包括的フレームワークです。直感的な構文と強力な機能により、LaravelではCRUD操作をアプリケーションに簡単に組み込むことができます。

この記事では、CRUD操作の基本的な概念と、Laravelの組み込み機能を使用した実装方法をご説明しました。また、以下も扱っています。

  • MyKinstaでデータベースを作成しアプリケーションに接続する方法
  • Laravelのマイグレーションを使ってデータベーステーブルを定義し、コントローラファイルとその関数を作成する方法
  • モデルの定義とコントローラの接続(LaravelのルーティングでBladeファイルを生成し、対応するページとフォームを作成し、MyKinstaを使用してアプリケーションをデプロイしてテスト)

LaravelでのCRUD操作がいかに簡単かお分かりいただけたと思います。ウェブアプリケーション開発とホスティング管理の手間をごっそり省くコントロールパネル「MyKinsta」を是非ともご確認ください。

Marcia Ramos Kinsta

Kinstaのエディトリアルチームリード。大のオープンソース&コーディング好き。IT業界向けのテクニカルライティングと編集に7年以上携わり、的確かつ簡潔なコンテンツを制作しながら、チームで協力し合い、ワークフローの改善を行っている。