当ブログ人気記事!
転職体験談
Laravelで学ぶWebアプリ開発
誰でも作れるチャットアプリ
未経験への勧め

【Laravel初心者向け講座】AjaxでのPOSTデータをバリデーション&サービスクラス作成で少し実践的なコードを書いてみる

プログラミング

バリデーションって何?必要?
サービスクラスって何?メリットは?
Laravelでの実装方が知りたい!

本記事はこんな悩みを解決します。


この記事を書いている私は、
2020年1月現在メガベンチャーの社内スタートアップの部署でエンジニア(1年目)をしてます。


プログラミング未経験からメガベンチャーへの転職を成功させた経験・ノウハウ
Webエンジニアになってから学んだこと

をブログにまとめています。


本記事では、「バリデーション」と「サービスクラス」をソースコード付きで解説します。


前回記事でAjaxでのポストを実装しましたが、

そこにバリデーションとロジック部分をサービスクラスに分離することで
少し実践的なソースコードに変えていきます。

Github: https://github.com/Shuto-san/laravel-vue-docker

スポンサーリンク

バリデーションとは?必須なの?

バリデーション(validation)を英訳すると、
「検証、実証、妥当性」
といった意味ですが、

プログラミングの世界では、

入力されたデータが正しいかどうか検証する

ことを意味します。

よくエンジニアとの会話では

「変数をバリデする」

という感じで登場します。

入力されたデータは正しいのかどうかは
どんなシステムでも必ず行われなければならない

バリデーションはまさにエンジニアにとっては必須の知識・スキルです。

本記事では、バックエンド側(PHP/Laravel)での実装例のみを紹介しますが、

当然バリデーションは
フロントエンド側(JS)、バックエンド側(PHP)の両方で行われるべきです。


「バリデーションは両側で必ずやって」
と入社当初口酸っぱく言われたものです。。。

バリデーション(Laravel)

Laravelの実装はとても簡単です。

まず、Httpリクエスト時に入力データに対するバリデーションルール
を設定できるクラスを以下のコマンドで自動生成します。

php artisan make:request TweetRequest


app/Http/Requests以下にTweetRequestクラスが自動生成されるので
バリデーションルールを実装します。

  • app/Http/Requests/TweetRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class TweetRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        // change false => true
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        // configure validation rules
        return [
            'tweet' => 'required|min:1|max:255',
        ];
    }
}


authorize()は、ユーザーのリクエスト権限を判定するメソッドですが、
今回は返り値をtrueにして全ユーザーに対してリクエストの権限を付与します。


rules()にバリデーションルールを記述します。

required=>必須項目、min:1=>最小1文字、 max:255=>最大255文字

としました。


あとはコントローラークラスで、設定したルールでバリデーションを行います。

  • app/Http/Controllers/TweetController.php
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Requests\TweetRequest  $request
     * @return \Illuminate\Http\Response
     */
    public function store(TweetRequest $request)
    {
        // validate posted tweet
        $validatedTweet = $request->validated();

        // ....
    }

TweetRequestvalidate()メソッドを用いることで、
先ほど設定したルールでバリデーションを行うことができます。

成功したらコードは通常通り続けて実行されます。
逆にバリデーションに失敗すると、例外が投げられ、
ユーザーに対し自動的に適切なJSONエラーレスポンスが返されます。

これでリクエスト毎にバリデーションが実行されるようになります!

サービスクラスとは?

サービスクラスとは、リクエストのビジネスロジックやDB処理をまとめて記述するためのクラスです。


Laravelではコマンドによるサービスクラス自動生成はサポートされておらず、
処理を実行する上で必須なクラスではありません。

特に一人で開発しているとサービスクラス必要性を感じにくいかもしれません。


Laravelでは、
リクエストに対する処理はコントローラークラスに記述することになっていますね。


ところが
システムの規模が大きくなったり
リクエストに対する処理ロジックが煩雑になってくるとと
当然ながらコントローラークラスのコード量がどんどん膨れていきます。


コントローラークラスが膨れ上がると
他の人はおろか自分でもどこに何が書いてあるか分かりにくい。。。
コードの変更箇所を発見するのに時間がかかるし、修正箇所が多くなる。。。

サービスクラスはそんな状況を助けます。


処理が煩雑なビジネスロジックやDB処理をサービスクラスに切り出してあげることで
可読性や保守性の向上や単体テスト実施など、
システム開発の効率化に多くのメリットがあります。


したがって筆者は、Laravelにも基本的にサービスクラスを導入することにしています。
(※システムの設計指針によります)


具体的な実装例を紹介します。

サービスクラス作成

artisanコマンドで自動生成は出来ないので、
まず、ディレクトリapp/Http/Servicesを作成します。

作成したディレクトリにサービスクラスを作成していきます。

  • app/Http/Services/TweetService.php
<?php

namespace app\Http\Services;

use App\Tweet;
use Illuminate\Support\Facades\Auth;

class TweetService {

    public function saveTweet($postedTweet)
    {
        $user = Auth::user();
        $tweet = new Tweet();
        $tweet->user_id = $user->id;
        $tweet->nickname = $user->name;
        $tweet->tweet = $postedTweet['tweet'];
        $tweet->save();

        return $tweet->tweet;
    }

}


前回TweetControllerstoreメソッド内に書いていたDB処理をサービスクラスに切り出しました。

今後、DBやRedisに接続しに行く処理はサービスクラスに記述していくことにしましょう。
そしてTweetControllerから呼び出します。

  • app/Http/Controllers/TweetController.php
<?php

namespace App\Http\Controllers;

use App\Http\Services\TweetService;
use Illuminate\Http\Request;
use App\Http\Requests\TweetRequest;

class TweetController extends Controller
{

    protected $tweetService;

    public function __construct(TweetService $tweet_service)
    {
        $this->middleware('auth')->only(['index']);
        $this->tweetService = $tweet_service;
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(TweetRequest $request)
    {
        // validate posted tweet
        $validatedTweet = $request->validated();

        // save tweet in DB
        $tweet = $this->tweetService->saveTweet($validatedTweet);

        return $tweet;
    }

サービスクラスをコントローラークラスに依存注入する場合

pretectedでサービスクラスの変数$tweetServiceを定義

Construct(TweetService $tweet_service)でコンストラクタの引数にサービスクラスのインスタンスを設定

コンストラクタ内で$tweetServiceにサービスクラスのインスタンスを代入


これでサービスクラスをコントローラークラス内で使えるようになります。

storeメソッド内は

ツイート内容をバリデーション

サービスクラスのメソッドにツイートを渡して呼び出し、
DB保存を実行

ツイート内容をレスポンス

という処理の流れになりました。

コントローラーの中身がスッキリしましたね!

まとめ:バックエンド側バリデーション&サービスクラス作成

以上、Laravelのバリデーション実装方法とサービスクラスの活用法でした。

これで前回のただのAjaxリクエストのコードが
少しだけ実践的なコードに生まれ変わりました。


趣味で書くプログラミングと世にリリースするプロダクトは
品質が全く違います


今後はより実践的なコードを
ブログやGithubに共有していきたいと考えています。

次回は、「バリデーション(Vue、ライブラリ不使用)」を解説します!
↓↓


それではまた!

プログラミング
スポンサーリンク
シェアする
SHOOTをフォローする
WebエンジニアSHOOTのブログ

コメント

タイトルとURLをコピーしました