
バリデーションって何?必要?
サービスクラスって何?メリットは?
Laravelでの実装方が知りたい!
本記事はこんな悩みを解決します。
この記事を書いている私は、
2020年1月現在メガベンチャーの社内スタートアップの部署でエンジニア(1年目)をしてます。
プログラミング未経験からメガベンチャーへの転職を成功させた経験・ノウハウ
Webエンジニアになってから学んだこと
をブログにまとめています。
本記事では、「バリデーション」と「サービスクラス」をソースコード付きで解説します。
前回記事でAjaxでのポストを実装しましたが、
そこにバリデーションとロジック部分をサービスクラスに分離することで
少し実践的なソースコードに変えていきます。
目次
バリデーションとは?必須なの?
バリデーション(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();
// ....
}
TweetRequestのvalidate()メソッドを用いることで、
先ほど設定したルールでバリデーションを行うことができます。
成功したらコードは通常通り続けて実行されます。
逆にバリデーションに失敗すると、例外が投げられ、
ユーザーに対し自動的に適切な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;
}
}
前回TweetControllerのstoreメソッド内に書いていた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リクエストのコードが
少しだけ実践的なコードに生まれ変わりました。
趣味で書くプログラミングと世にリリースするプロダクトは
品質が全く違います。
今後はより実践的なコードを
ブログに共有していきたいと考えています。
次回は、「バリデーション(Vue、ライブラリ不使用)」を解説します!
↓↓
それではまた!




