{"id":2605,"date":"2025-03-24T08:46:57","date_gmt":"2025-03-23T23:46:57","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=2605"},"modified":"2025-03-24T08:47:26","modified_gmt":"2025-03-23T23:47:26","slug":"%e3%80%90%e4%bf%9d%e5%ad%98%e7%89%88%e3%80%91laravel-formrequest%e3%81%a7%e5%ae%9f%e7%8f%be%e3%81%99%e3%82%8b%e5%a0%85%e5%ae%9f%e3%81%aa%e3%83%90%e3%83%aa%e3%83%87%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=2605","title":{"rendered":"\u3010\u4fdd\u5b58\u7248\u3011Laravel FormRequest\u3067\u5b9f\u73fe\u3059\u308b\u5805\u5b9f\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406\u306e\u5b9f\u88c5\u65b9\u6cd5 &#8211; \u5b9f\u8df5\u7684\u306a11\u306e\u6d3b\u7528\u30c6\u30af\u30cb\u30c3\u30af"},"content":{"rendered":"\n<div class=\"toc\"><br \/>\n<b>Warning<\/b>:  Undefined array key \"is_admin\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>116<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_category_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>121<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>128<\/b><br \/>\n    <div id=\"toc_container\" class=\"sgb-toc--bullets js-smooth-scroll\" data-dialog-title=\"\u76ee\u6b21\">\n      <p class=\"toc_title\">\u76ee\u6b21 <\/p>\n      <ul class=\"toc_list\">  <li class=\"first\">    <a href=\"#i-0\">FormRequest\u306e\u57fa\u790e\u77e5\u8b58\u3068\u5c0e\u5165\u30e1\u30ea\u30c3\u30c8<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">FormRequest\u3068\u306f\uff1f \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u3092\u30b9\u30ea\u30e0\u5316\u3059\u308b\u9b54\u6cd5\u306e\u30af\u30e9\u30b9<\/a>      <\/li>      <li>        <a href=\"#i-2\">\u5f93\u6765\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406\u3068\u306e\u6bd4\u8f03\u30e1\u30ea\u30c3\u30c8<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-3\">FormRequest\u3092\u4f7f\u3046\u3079\u304d3\u3064\u306e\u30b1\u30fc\u30b9<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-4\">FormRequest\u306e\u57fa\u672c\u7684\u306a\u624b\u9806<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-5\">artisan\u30b3\u30de\u30f3\u30c9\u3067FormRequest\u3092\u751f\u6210\u3059\u308b<\/a>      <\/li>      <li>        <a href=\"#i-6\">rules\u30e1\u30bd\u30c3\u30c9\u3067\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u5b9a\u7fa9\u3059\u308b<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-7\">authorize\u30e1\u30bd\u30c3\u30c9\u3067\u51e6\u7406\u3092\u5b9f\u88c5\u3059\u308b<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-8\">\u5b9f\u8df5\u7684\u306aFormRequest\u306e\u6d3b\u7528\u30c6\u30af\u30cb\u30c3\u30af<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-9\">\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u8ffd\u52a0\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-10\">\u6761\u4ef6\u4ed8\u304d\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u88c5\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-11\">\u914d\u5217\u30c7\u30fc\u30bf\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-12\">\u30d5\u30a1\u30a4\u30eb\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u8a2d\u5b9a<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-13\">FormRequest\u306e\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-14\">\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-15\">\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u6642\u306e\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u5236\u5fa1<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-16\">API\u30ea\u30af\u30a8\u30b9\u30c8\u30a8\u30e9\u30fc\u5fdc\u7b54\u8a2d\u5b9a<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-17\">FormRequest\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-18\">FormRequest\u5c02\u7528\u306e\u30e6\u30cb\u30c3\u30c8\u30c6\u30b9\u30c8\u306e\u66f8\u304d\u65b9<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-19\">\u30c6\u30b9\u30c8\u6642\u306b\u3088\u304f\u767a\u751f\u3059\u308b\u30a8\u30e9\u30fc\u3068\u305d\u306e\u89e3\u6c7a\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-20\">FormRequest\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3068\u30d2\u30f3\u30c8<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-21\">FormRequest\u306e\u5171\u901a\u51e6\u7406\u3092\u89aa\u30af\u30e9\u30b9\u306b\u5b9f\u88c5\u3059\u308b<\/a>      <\/li>      <li>        <a href=\"#i-22\">\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u518d\u5229\u7528\u3068DRY\u539f\u5247\u306e\u5b9f\u8df5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-23\">\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306eFormRequest\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3<\/a>      <\/li>    <\/ul>  <\/li><\/ul>\n      <a href=\"#\" class=\"sgb-toc-button js-toc-button\" rel=\"nofollow\" data-open-dialog=\"true\"><i class=\"fa fa-list\"><\/i><span class=\"sgb-toc-button__text\">\u76ee\u6b21\u3078<\/span><\/a>\n    <\/div><\/div><h2 class=\"wp-block-heading\" id=\"i-0\">FormRequest\u306e\u57fa\u790e\u77e5\u8b58\u3068\u5c0e\u5165\u30e1\u30ea\u30c3\u30c8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">FormRequest\u3068\u306f\uff1f \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u3092\u30b9\u30ea\u30e0\u5316\u3059\u308b\u9b54\u6cd5\u306e\u30af\u30e9\u30b9<\/h3>\n\n\n\n<p>FormRequest\u306f\u3001Laravel\u304c\u63d0\u4f9b\u3059\u308b\u5f37\u529b\u306a\u30d5\u30a9\u30fc\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u6a5f\u80fd\u3067\u3059\u3002\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u691c\u8a3c\u30ed\u30b8\u30c3\u30af\u3092\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u304b\u3089\u5206\u96e2\u3057\u3001\u5c02\u7528\u306e\u30af\u30e9\u30b9\u3067\u7ba1\u7406\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b3\u30fc\u30c9\u306f\u3088\u308a\u6574\u7406\u3055\u308c\u3001\u4fdd\u5b88\u6027\u304c\u5411\u4e0a\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u5f93\u6765\u306e\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u3067\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\npublic function store(Request $request)\n{\n    $validated = $request-&gt;validate([\n        'title' =&gt; 'required|max:255',\n        'body' =&gt; 'required',\n        'published_at' =&gt; 'nullable|date',\n    ]);\n\n    \/\/ \u4ee5\u964d\u306e\u51e6\u7406...\n}\n\n\/\/ FormRequest\u3092\u4f7f\u7528\u3057\u305f\u5834\u5408\npublic function store(PostStoreRequest $request)\n{\n    \/\/ \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306f\u81ea\u52d5\u7684\u306b\u5b9f\u884c\u3055\u308c\u308b\n    $post = Post::create($request-&gt;validated());\n\n    return redirect()-&gt;route('posts.show', $post);\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">\u5f93\u6765\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406\u3068\u306e\u6bd4\u8f03\u30e1\u30ea\u30c3\u30c8<\/h3>\n\n\n\n<p>FormRequest\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u660e\u78ba\u306a\u30e1\u30ea\u30c3\u30c8\u304c\u5f97\u3089\u308c\u307e\u3059\uff1a<\/p>\n\n\n<div id=\"id-a8131b41-a2a3-4837-bfcc-0579f0235020\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u89b3\u70b9<\/th><th>\u5f93\u6765\u306e\u65b9\u6cd5<\/th><th>FormRequest<\/th><\/tr><\/thead><tbody><tr><td>\u30b3\u30fc\u30c9\u306e\u8cac\u52d9<\/td><td>\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u306b\u96c6\u4e2d<\/td><td>\u9069\u5207\u306b\u5206\u96e2<\/td><\/tr><tr><td>\u518d\u5229\u7528\u6027<\/td><td>\u4f4e\u3044\uff08\u30b3\u30d4\u30fc&amp;\u30da\u30fc\u30b9\u30c8\u304c\u5fc5\u8981\uff09<\/td><td>\u9ad8\u3044\uff08\u30af\u30e9\u30b9\u3068\u3057\u3066\u518d\u5229\u7528\u53ef\u80fd\uff09<\/td><\/tr><tr><td>\u30c6\u30b9\u30bf\u30d3\u30ea\u30c6\u30a3<\/td><td>\u3084\u3084\u96e3\u3057\u3044<\/td><td>\u5bb9\u6613\uff08\u72ec\u7acb\u3057\u305f\u30c6\u30b9\u30c8\u304c\u53ef\u80fd\uff09<\/td><\/tr><tr><td>\u30b3\u30fc\u30c9\u306e\u898b\u901a\u3057<\/td><td>\u8907\u96d1\u306b\u306a\u308a\u3084\u3059\u3044<\/td><td>\u30af\u30ea\u30fc\u30f3\u3067\u7406\u89e3\u3057\u3084\u3059\u3044<\/td><\/tr><tr><td>\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u6027<\/td><td>\u5909\u66f4\u304c\u5f71\u97ff\u3092\u53ca\u307c\u3057\u3084\u3059\u3044<\/td><td>\u5f71\u97ff\u7bc4\u56f2\u304c\u9650\u5b9a\u7684<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"i-3\">FormRequest\u3092\u4f7f\u3046\u3079\u304d3\u3064\u306e\u30b1\u30fc\u30b9<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u8907\u96d1\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u304c\u5fc5\u8981\u306a\u5834\u5408<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6761\u4ef6\u4ed8\u304d\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3<\/li>\n\n\n\n<li>\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb<\/li>\n\n\n\n<li>\u8907\u6570\u30d5\u30a3\u30fc\u30eb\u30c9\u306e\u76f8\u95a2\u30c1\u30a7\u30c3\u30af<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ComplexFormRequest extends FormRequest\n{\n    public function rules()\n    {\n        return [\n            'email' =&gt; 'required|email|unique:users',\n            'age' =&gt; 'required|integer|min:18',\n            'plan' =&gt; 'required|in:basic,premium',\n            'card_number' =&gt; Rule::requiredIf(fn() =&gt; $this-&gt;plan === 'premium'),\n        ];\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u540c\u3058\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u8907\u6570\u306e\u5834\u6240\u3067\u4f7f\u7528\u3059\u308b\u5834\u5408<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5171\u901a\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af<\/li>\n\n\n\n<li>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5168\u4f53\u3067\u306e\u4e00\u8cab\u6027\u78ba\u4fdd<\/li>\n\n\n\n<li>DRY\u306e\u539f\u5247\u306e\u5b9f\u8df5<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class BaseUserRequest extends FormRequest\n{\n    public function rules()\n    {\n        return [\n            'name' =&gt; 'required|string|max:255',\n            'email' =&gt; 'required|email|unique:users',\n        ];\n    }\n}\n\nclass CreateUserRequest extends BaseUserRequest\n{\n    public function rules()\n    {\n        return array_merge(parent::rules(), [\n            'password' =&gt; 'required|min:8|confirmed',\n        ]);\n    }\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u8a8d\u53ef\uff08Authorization\uff09\u3068\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u5834\u5408<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30e6\u30fc\u30b6\u30fc\u6a29\u9650\u306e\u30c1\u30a7\u30c3\u30af<\/li>\n\n\n\n<li>\u30ea\u30bd\u30fc\u30b9\u3078\u306e\u30a2\u30af\u30bb\u30b9\u5236\u5fa1<\/li>\n\n\n\n<li>\u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u306e\u9069\u7528<\/li>\n<\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UpdatePostRequest extends FormRequest\n{\n    public function authorize()\n    {\n        $post = Post::find($this-&gt;route('post'));\n        return $post &amp;&amp; $this-&gt;user()-&gt;can('update', $post);\n    }\n\n    public function rules()\n    {\n        return [\n            'title' =&gt; 'required|max:255',\n            'content' =&gt; 'required',\n            'category_id' =&gt; 'exists:categories,id',\n        ];\n    }\n}<\/pre>\n\n\n\n<p>FormRequest\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b3\u30fc\u30c9\u306f\u3088\u308a\u69cb\u9020\u5316\u3055\u308c\u3001\u4fdd\u5b88\u6027\u304c\u5411\u4e0a\u3057\u307e\u3059\u3002\u7279\u306b\u5927\u898f\u6a21\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3084\u3001\u8907\u96d1\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\u3092\u6301\u3064\u30b1\u30fc\u30b9\u3067\u306f\u3001FormRequest\u306e\u5c0e\u5165\u3092\u7a4d\u6975\u7684\u306b\u691c\u8a0e\u3059\u3079\u304d\u3067\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001FormRequest\u306e\u5177\u4f53\u7684\u306a\u5b9f\u88c5\u624b\u9806\u306b\u3064\u3044\u3066\u8a73\u3057\u304f\u8aac\u660e\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-4\">FormRequest\u306e\u57fa\u672c\u7684\u306a\u624b\u9806<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">artisan\u30b3\u30de\u30f3\u30c9\u3067FormRequest\u3092\u751f\u6210\u3059\u308b<\/h3>\n\n\n\n<p>FormRequest\u30af\u30e9\u30b9\u306e\u4f5c\u6210\u306f\u3001Laravel\u306eartisan\u30b3\u30de\u30f3\u30c9\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u7c21\u5358\u306b\u884c\u3048\u307e\u3059\u3002\u4ee5\u4e0b\u306e\u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u884c\u3059\u308b\u3053\u3068\u3067\u3001\u5fc5\u8981\u306a\u30dc\u30a4\u30e9\u30fc\u30d7\u30ec\u30fc\u30c8\u30b3\u30fc\u30c9\u304c\u81ea\u52d5\u751f\u6210\u3055\u308c\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u57fa\u672c\u7684\u306a\u751f\u6210\u30b3\u30de\u30f3\u30c9\nphp artisan make:request StorePostRequest\n\n# \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5185\u306e\u751f\u6210\u5834\u6240\n# app\/Http\/Requests\/StorePostRequest.php<\/pre>\n\n\n\n<p>\u751f\u6210\u3055\u308c\u308b\u30d5\u30a1\u30a4\u30eb\u306e\u57fa\u672c\u69cb\u9020\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">namespace App\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nclass StorePostRequest extends FormRequest\n{\n    \/**\n     * \u30ea\u30af\u30a8\u30b9\u30c8\u306e\u8a8d\u53ef\u3092\u5224\u5b9a\n     *\/\n    public function authorize()\n    {\n        return false;  \/\/ \u30c7\u30d5\u30a9\u30eb\u30c8\u306ffalse\n    }\n\n    \/**\n     * \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u5b9a\u7fa9\n     *\/\n    public function rules()\n    {\n        return [\n            \/\/\n        ];\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">rules\u30e1\u30bd\u30c3\u30c9\u3067\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u5b9a\u7fa9\u3059\u308b<\/h3>\n\n\n\n<p><code>rules<\/code>\u30e1\u30bd\u30c3\u30c9\u3067\u306f\u3001\u30d5\u30a9\u30fc\u30e0\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u5bfe\u3059\u308b\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u914d\u5217\u5f62\u5f0f\u3067\u5b9a\u7fa9\u3057\u307e\u3059\u3002Laravel\u304c\u63d0\u4f9b\u3059\u308b\u8c4a\u5bcc\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u6d3b\u7528\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function rules()\n{\n    return [\n        \/\/ \u57fa\u672c\u7684\u306a\u30eb\u30fc\u30eb\n        'title' =&gt; 'required|string|max:255',\n        'content' =&gt; 'required|string|min:10',\n\n        \/\/ \u8907\u6570\u306e\u30eb\u30fc\u30eb\u3092\u914d\u5217\u3067\u6307\u5b9a\n        'email' =&gt; [\n            'required',\n            'email',\n            'unique:users,email',\n        ],\n\n        \/\/ \u30af\u30ed\u30fc\u30b8\u30e3\u30fc\u3092\u4f7f\u7528\u3057\u305f\u52d5\u7684\u306a\u30eb\u30fc\u30eb\n        'category_id' =&gt; [\n            'required',\n            'integer',\n            function ($attribute, $value, $fail) {\n                if (!Category::where('id', $value)-&gt;exists()) {\n                    $fail('\u9078\u629e\u3055\u308c\u305f\u30ab\u30c6\u30b4\u30ea\u30fc\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002');\n                }\n            },\n        ],\n\n        \/\/ \u6761\u4ef6\u4ed8\u304d\u30eb\u30fc\u30eb\n        'phone' =&gt; Rule::when($this-&gt;contact_method === 'phone', [\n            'required',\n            'string',\n            'regex:\/^[0-9-]+$\/',\n        ]),\n    ];\n}\n\n\/\/ \u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\npublic function messages()\n{\n    return [\n        'title.required' =&gt; '\u30bf\u30a4\u30c8\u30eb\u306f\u5fc5\u9808\u3067\u3059\u3002',\n        'content.min' =&gt; '\u5185\u5bb9\u306f:min\u6587\u5b57\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n    ];\n}\n\n\/\/ \u5c5e\u6027\u540d\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\npublic function attributes()\n{\n    return [\n        'title' =&gt; '\u8a18\u4e8b\u30bf\u30a4\u30c8\u30eb',\n        'content' =&gt; '\u8a18\u4e8b\u5185\u5bb9',\n    ];\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-7\">authorize\u30e1\u30bd\u30c3\u30c9\u3067\u51e6\u7406\u3092\u5b9f\u88c5\u3059\u308b<\/h3>\n\n\n\n<p><code>authorize<\/code>\u30e1\u30bd\u30c3\u30c9\u3067\u306f\u3001\u73fe\u5728\u306e\u30e6\u30fc\u30b6\u30fc\u304c\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u5b9f\u884c\u3059\u308b\u6a29\u9650\u3092\u6301\u3063\u3066\u3044\u308b\u304b\u3069\u3046\u304b\u3092\u5224\u5b9a\u3057\u307e\u3059\u3002\u3053\u3053\u3067Laravel\u306e\u30dd\u30ea\u30b7\u30fc\u3084\u30b2\u30fc\u30c8\u3068\u9023\u643a\u3059\u308b\u3053\u3068\u3067\u3001\u304d\u3081\u7d30\u304b\u306a\u30a2\u30af\u30bb\u30b9\u5236\u5fa1\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public function authorize()\n{\n    \/\/ \u57fa\u672c\u7684\u306a\u8a8d\u53ef\u30c1\u30a7\u30c3\u30af\n    return true;  \/\/ \u3059\u3079\u3066\u306e\u30e6\u30fc\u30b6\u30fc\u306b\u8a31\u53ef\n\n    \/\/ \u30e6\u30fc\u30b6\u30fc\u306e\u6a29\u9650\u30c1\u30a7\u30c3\u30af\n    return $this-&gt;user()-&gt;can('create', Post::class);\n\n    \/\/ \u7279\u5b9a\u306e\u30ed\u30fc\u30eb\u30c1\u30a7\u30c3\u30af\n    return $this-&gt;user()-&gt;hasRole('editor');\n\n    \/\/ \u8907\u96d1\u306a\u6761\u4ef6\u30c1\u30a7\u30c3\u30af\n    $post = Post::find($this-&gt;route('post'));\n    return $post &amp;&amp; $this-&gt;user()-&gt;id === $post-&gt;user_id;\n}<\/pre>\n\n\n\n<p>\u5b9f\u88c5\u306e\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u9069\u5207\u306a\u540d\u524d\u4ed8\u3051<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30ea\u30af\u30a8\u30b9\u30c8\u30af\u30e9\u30b9\u306e\u540d\u524d\u306f\u7528\u9014\u3092\u660e\u78ba\u306b\u8868\u73fe\u3059\u308b<\/li>\n\n\n\n<li>\u4f8b\uff1a<code>StorePostRequest<\/code>, <code>UpdateUserRequest<\/code><\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u6574\u7406<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u95a2\u9023\u3059\u308b\u30eb\u30fc\u30eb\u3092\u307e\u3068\u3081\u3066\u8a18\u8ff0<\/li>\n\n\n\n<li>\u8907\u96d1\u306a\u30eb\u30fc\u30eb\u306f\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u30e1\u30bd\u30c3\u30c9\u306b\u5206\u5272<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30e6\u30fc\u30b6\u30fc\u30d5\u30ec\u30f3\u30c9\u30ea\u30fc\u306a\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u591a\u8a00\u8a9e\u5bfe\u5fdc\u3092\u8003\u616e<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u8a8d\u53ef\u30ed\u30b8\u30c3\u30af\u306e\u9069\u5207\u306a\u5b9f\u88c5<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3092\u8003\u616e\u3057\u305f\u9069\u5207\u306a\u6a29\u9650\u30c1\u30a7\u30c3\u30af<\/li>\n\n\n\n<li>\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u3068\u306e\u6574\u5408\u6027\u78ba\u4fdd<\/li>\n<\/ul>\n\n\n\n<p>FormRequest\u306e\u57fa\u672c\u7684\u306a\u5b9f\u88c5\u624b\u9806\u3092\u7406\u89e3\u3059\u308b\u3053\u3068\u3067\u3001\u30af\u30ea\u30fc\u30f3\u3067\u4fdd\u5b88\u6027\u306e\u9ad8\u3044\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3088\u308a\u5b9f\u8df5\u7684\u306aFormRequest\u306e\u6d3b\u7528\u30c6\u30af\u30cb\u30c3\u30af\u306b\u3064\u3044\u3066\u8aac\u660e\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-8\">\u5b9f\u8df5\u7684\u306aFormRequest\u306e\u6d3b\u7528\u30c6\u30af\u30cb\u30c3\u30af<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u8ffd\u52a0\u65b9\u6cd5<\/h3>\n\n\n\n<p>FormRequest\u3067\u306f\u3001Laravel\u306e\u6a19\u6e96\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306b\u52a0\u3048\u3066\u3001\u72ec\u81ea\u306e\u30ab\u30b9\u30bf\u30e0\u30eb\u30fc\u30eb\u3092\u5b9f\u88c5\u3067\u304d\u307e\u3059\u3002\u4ee5\u4e0b\u306b\u3001\u3088\u304f\u4f7f\u7528\u3055\u308c\u308b\u30d1\u30bf\u30fc\u30f3\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ProductRequest extends FormRequest\n{\n    \/**\n     * \u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30bf\u306e\u5b9a\u7fa9\n     *\/\n    public function withValidator($validator)\n    {\n        $validator-&gt;addRule('price_range', function ($attribute, $value, $parameters) {\n            return $value &gt;= $parameters[0] &amp;&amp; $value &lt;= $parameters[1];\n        });\n\n        \/\/ \u30af\u30ed\u30fc\u30b8\u30e3\u30fc\u306b\u3088\u308b\u8907\u96d1\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        $validator-&gt;after(function ($validator) {\n            if ($this-&gt;stock &lt; $this-&gt;minimum_stock) {\n                $validator-&gt;errors()-&gt;add('stock', '\u5728\u5eab\u6570\u306f\u6700\u5c0f\u5728\u5eab\u6570\u3088\u308a\u5927\u304d\u3044\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002');\n            }\n        });\n    }\n\n    public function rules()\n    {\n        return [\n            'price' =&gt; ['required', 'numeric', 'price_range:1000,100000'],\n            'stock' =&gt; 'required|integer|min:0',\n            'minimum_stock' =&gt; 'required|integer|min:0',\n        ];\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">\u6761\u4ef6\u4ed8\u304d\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u88c5\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u7279\u5b9a\u306e\u6761\u4ef6\u306b\u57fa\u3065\u3044\u3066\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u52d5\u7684\u306b\u5909\u66f4\u3059\u308b\u65b9\u6cd5\u3092\u8aac\u660e\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UpdateUserRequest extends FormRequest\n{\n    public function rules()\n    {\n        $rules = [\n            'name' =&gt; 'required|string|max:255',\n            'email' =&gt; [\n                'required',\n                'email',\n                Rule::unique('users')-&gt;ignore($this-&gt;user-&gt;id),\n            ],\n        ];\n\n        \/\/ \u30e6\u30fc\u30b6\u30fc\u30bf\u30a4\u30d7\u306b\u5fdc\u3058\u305f\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        if ($this-&gt;input('type') === 'business') {\n            $rules = array_merge($rules, [\n                'company_name' =&gt; 'required|string|max:255',\n                'tax_number' =&gt; 'required|string|size:13',\n            ]);\n        }\n\n        \/\/ \u30d1\u30b9\u30ef\u30fc\u30c9\u5909\u66f4\u6642\u306e\u307f\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        if ($this-&gt;filled('password')) {\n            $rules['password'] = ['required', 'min:8', 'confirmed'];\n            $rules['current_password'] = ['required', function ($attribute, $value, $fail) {\n                if (!Hash::check($value, $this-&gt;user-&gt;password)) {\n                    $fail('\u73fe\u5728\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002');\n                }\n            }];\n        }\n\n        return $rules;\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-11\">\u914d\u5217\u30c7\u30fc\u30bf\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406<\/h3>\n\n\n\n<p>\u8907\u6570\u306e\u8981\u7d20\u3092\u542b\u3080\u914d\u5217\u30c7\u30fc\u30bf\u306b\u5bfe\u3059\u308b\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u65b9\u6cd5\u3092\u793a\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class CreateOrderRequest extends FormRequest\n{\n    public function rules()\n    {\n        return [\n            \/\/ \u914d\u5217\u81ea\u4f53\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n            'items' =&gt; 'required|array|min:1',\n\n            \/\/ \u914d\u5217\u306e\u5404\u8981\u7d20\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n            'items.*.product_id' =&gt; 'required|exists:products,id',\n            'items.*.quantity' =&gt; 'required|integer|min:1',\n\n            \/\/ \u30cd\u30b9\u30c8\u3055\u308c\u305f\u914d\u5217\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n            'shipping_addresses' =&gt; 'required|array|min:1',\n            'shipping_addresses.*.postal_code' =&gt; 'required|string|size:7',\n            'shipping_addresses.*.address' =&gt; 'required|string|max:255',\n            'shipping_addresses.*.phone' =&gt; 'required|string|regex:\/^[0-9-]+$\/',\n        ];\n    }\n\n    \/**\n     * \u914d\u5217\u5168\u4f53\u306b\u5bfe\u3059\u308b\u8ffd\u52a0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n     *\/\n    public function withValidator($validator)\n    {\n        $validator-&gt;after(function ($validator) {\n            $totalQuantity = collect($this-&gt;items)-&gt;sum('quantity');\n            if ($totalQuantity &gt; 100) {\n                $validator-&gt;errors()-&gt;add('items', '\u6ce8\u6587\u6570\u91cf\u306e\u5408\u8a08\u306f100\u3092\u8d85\u3048\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002');\n            }\n        });\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-12\">\u30d5\u30a1\u30a4\u30eb\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u8a2d\u5b9a<\/h3>\n\n\n\n<p>\u30d5\u30a1\u30a4\u30eb\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u306b\u7279\u5316\u3057\u305f\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u5b9f\u88c5\u4f8b\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class DocumentUploadRequest extends FormRequest\n{\n    public function rules()\n    {\n        return [\n            \/\/ \u5358\u4e00\u30d5\u30a1\u30a4\u30eb\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n            'document' =&gt; [\n                'required',\n                'file',\n                'mimes:pdf,doc,docx',\n                'max:10240', \/\/ 10MB\n            ],\n\n            \/\/ \u8907\u6570\u30d5\u30a1\u30a4\u30eb\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n            'attachments' =&gt; 'required|array|min:1|max:5',\n            'attachments.*' =&gt; [\n                'required',\n                'file',\n                'mimes:jpg,jpeg,png,pdf',\n                'max:5120', \/\/ 5MB\n            ],\n        ];\n    }\n\n    \/**\n     * \u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0\u30c1\u30a7\u30c3\u30af\n     *\/\n    public function withValidator($validator)\n    {\n        $validator-&gt;after(function ($validator) {\n            if ($this-&gt;hasFile('attachments')) {\n                $totalSize = collect($this-&gt;file('attachments'))\n                    -&gt;sum(function ($file) {\n                        return $file-&gt;getSize();\n                    });\n\n                \/\/ \u5408\u8a08\u30b5\u30a4\u30ba\u30c1\u30a7\u30c3\u30af\uff0820MB\u4ee5\u4e0b\uff09\n                if ($totalSize &gt; 20 * 1024 * 1024) {\n                    $validator-&gt;errors()-&gt;add(\n                        'attachments',\n                        '\u6dfb\u4ed8\u30d5\u30a1\u30a4\u30eb\u306e\u5408\u8a08\u30b5\u30a4\u30ba\u306f20MB\u4ee5\u4e0b\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002'\n                    );\n                }\n            }\n        });\n    }\n\n    \/**\n     * \u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u524d\u306e\u524d\u51e6\u7406\n     *\/\n    protected function prepareForValidation()\n    {\n        if ($this-&gt;hasFile('document')) {\n            \/\/ \u30d5\u30a1\u30a4\u30eb\u540d\u306e\u30b5\u30cb\u30bf\u30a4\u30ba\n            $this-&gt;merge([\n                'original_filename' =&gt; $this-&gt;file('document')-&gt;getClientOriginalName()\n            ]);\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u8df5\u7684\u306a\u30c6\u30af\u30cb\u30c3\u30af\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u3088\u308a\u5805\u7262\u3067\u67d4\u8edf\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u51e6\u7406\u3092\u5b9f\u88c5\u3067\u304d\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001FormRequest\u306e\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u306b\u3064\u3044\u3066\u8a73\u3057\u304f\u8aac\u660e\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-13\">FormRequest\u306e\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-14\">\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u65b9\u6cd5<\/h3>\n\n\n\n<p>FormRequest\u3067\u306f\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u7d30\u304b\u304f\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u30e6\u30fc\u30b6\u30fc\u30d5\u30ec\u30f3\u30c9\u30ea\u30fc\u3067\u5206\u304b\u308a\u3084\u3059\u3044\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5b9f\u88c5\u3059\u308b\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserRegistrationRequest extends FormRequest\n{\n    \/**\n     * \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u5b9a\u7fa9\n     *\/\n    public function rules()\n    {\n        return [\n            'username' =&gt; 'required|string|max:30|unique:users',\n            'email' =&gt; 'required|email|unique:users',\n            'password' =&gt; 'required|min:8|confirmed',\n            'terms' =&gt; 'accepted',\n        ];\n    }\n\n    \/**\n     * \u30ab\u30b9\u30bf\u30e0\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u5b9a\u7fa9\n     *\/\n    public function messages()\n    {\n        return [\n            'username.required' =&gt; '\u30e6\u30fc\u30b6\u30fc\u540d\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n            'username.unique' =&gt; '\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u540d\u306f\u65e2\u306b\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002',\n            'email.email' =&gt; '\u6709\u52b9\u306a\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n            'password.min' =&gt; '\u30d1\u30b9\u30ef\u30fc\u30c9\u306f:min\u6587\u5b57\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n            'terms.accepted' =&gt; '\u5229\u7528\u898f\u7d04\u306b\u540c\u610f\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002',\n        ];\n    }\n\n    \/**\n     * \u5c5e\u6027\u540d\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\n     *\/\n    public function attributes()\n    {\n        return [\n            'username' =&gt; '\u30e6\u30fc\u30b6\u30fc\u540d',\n            'email' =&gt; '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9',\n            'password' =&gt; '\u30d1\u30b9\u30ef\u30fc\u30c9',\n            'terms' =&gt; '\u5229\u7528\u898f\u7d04',\n        ];\n    }\n\n    \/**\n     * \u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\u51e6\u7406\n     *\/\n    protected function formatErrors($validator)\n    {\n        return [\n            'status' =&gt; 'error',\n            'message' =&gt; '\u5165\u529b\u5185\u5bb9\u306b\u8aa4\u308a\u304c\u3042\u308a\u307e\u3059\u3002',\n            'errors' =&gt; $validator-&gt;errors()-&gt;toArray(),\n        ];\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-15\">\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u6642\u306e\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u5236\u5fa1<\/h3>\n\n\n\n<p>\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u767a\u751f\u6642\u306e\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u52d5\u4f5c\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b\u65b9\u6cd5\u3092\u8aac\u660e\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ProductUpdateRequest extends FormRequest\n{\n    \/**\n     * \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u6642\u306e\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u5148\u306e\u6307\u5b9a\n     *\/\n    protected $redirectRoute = 'products.edit';\n\n    \/**\n     * \u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u6642\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u8a2d\u5b9a\n     *\/\n    public function withValidator($validator)\n    {\n        if ($validator-&gt;fails()) {\n            \/\/ \u30bb\u30c3\u30b7\u30e7\u30f3\u306b\u30a8\u30e9\u30fc\u60c5\u5831\u3092\u4fdd\u5b58\n            session()-&gt;flash('error_type', 'validation');\n            session()-&gt;flash('target_section', 'product_details');\n        }\n    }\n\n    \/**\n     * \u30ab\u30b9\u30bf\u30e0\u30ea\u30c0\u30a4\u30ec\u30af\u30bf\u306e\u5b9f\u88c5\n     *\/\n    protected function getRedirectUrl()\n    {\n        \/\/ \u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u5148\u3092\u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\n        $url = $this-&gt;redirector-&gt;getUrlGenerator();\n\n        return $url-&gt;route('products.edit', [\n            'product' =&gt; $this-&gt;route('product'),\n            'section' =&gt; 'details',\n        ]);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">API\u30ea\u30af\u30a8\u30b9\u30c8\u30a8\u30e9\u30fc\u5fdc\u7b54\u8a2d\u5b9a<\/h3>\n\n\n\n<p>API\u7528\u306e\u30a8\u30e9\u30fc\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b\u65b9\u6cd5\u3092\u793a\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ApiProductRequest extends FormRequest\n{\n    \/**\n     * \u30ea\u30af\u30a8\u30b9\u30c8\u304cAPI\u3067\u3042\u308b\u3053\u3068\u3092\u793a\u3059\n     *\/\n    public function wantsJson()\n    {\n        return true;\n    }\n\n    \/**\n     * \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u6642\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\n     *\/\n    protected function failedValidation(Validator $validator)\n    {\n        $response = new JsonResponse([\n            'status' =&gt; 'error',\n            'message' =&gt; '\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002',\n            'errors' =&gt; $validator-&gt;errors(),\n            'error_code' =&gt; 'VALIDATION_ERROR',\n        ], 422);\n\n        throw new ValidationException($validator, $response);\n    }\n\n    \/**\n     * \u8a8d\u53ef\u30a8\u30e9\u30fc\u6642\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\n     *\/\n    protected function failedAuthorization()\n    {\n        throw new HttpResponseException(\n            response()-&gt;json([\n                'status' =&gt; 'error',\n                'message' =&gt; '\u3053\u306e\u64cd\u4f5c\u3092\u5b9f\u884c\u3059\u308b\u6a29\u9650\u304c\u3042\u308a\u307e\u305b\u3093\u3002',\n                'error_code' =&gt; 'UNAUTHORIZED',\n            ], 403)\n        );\n    }\n\n    \/**\n     * \u30b0\u30ed\u30fc\u30d0\u30eb\u306a\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\n     *\/\n    public function withValidator($validator)\n    {\n        $validator-&gt;after(function ($validator) {\n            try {\n                \/\/ \u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n                $this-&gt;validateBusinessRules();\n            } catch (BusinessRuleException $e) {\n                $validator-&gt;errors()-&gt;add('business_rule', $e-&gt;getMessage());\n            }\n        });\n    }\n\n    \/**\n     * \u30a8\u30e9\u30fc\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u30d5\u30a9\u30fc\u30de\u30c3\u30c8\n     *\/\n    public function formatErrors(Validator $validator)\n    {\n        return [\n            'status' =&gt; 'error',\n            'errors' =&gt; $validator-&gt;errors()-&gt;toArray(),\n            'debug_id' =&gt; uniqid('val_'),\n            'timestamp' =&gt; now()-&gt;toIso8601String(),\n        ];\n    }\n}\n\n\/\/ API\u30a8\u30e9\u30fc\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u4f7f\u7528\u4f8b\nclass ApiErrorHandler extends Handler\n{\n    protected function invalidJson($request, ValidationException $exception)\n    {\n        return response()-&gt;json([\n            'message' =&gt; $exception-&gt;getMessage(),\n            'errors' =&gt; $this-&gt;transformErrors($exception),\n        ], $exception-&gt;status);\n    }\n\n    private function transformErrors(ValidationException $exception)\n    {\n        $errors = [];\n\n        foreach ($exception-&gt;errors() as $field =&gt; $message) {\n            $errors[] = [\n                'field' =&gt; $field,\n                'message' =&gt; $message[0],\n                'code' =&gt; 'INVALID_' . strtoupper($field),\n            ];\n        }\n\n        return $errors;\n    }\n}<\/pre>\n\n\n\n<p>FormRequest\u306e\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u3092\u9069\u5207\u306b\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001\u30e6\u30fc\u30b6\u30fc\u30d5\u30ec\u30f3\u30c9\u30ea\u30fc\u306a\u30a8\u30e9\u30fc\u901a\u77e5\u3068API\u5fdc\u7b54\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u591a\u8a00\u8a9e\u5316\u3084\u3001\u30a8\u30e9\u30fc\u30ed\u30b0\u306e\u8a18\u9332\u306a\u3069\u3082\u8003\u616e\u306b\u5165\u308c\u308b\u3053\u3068\u3067\u3001\u3088\u308a\u5805\u7262\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001FormRequest\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5\u306b\u3064\u3044\u3066\u8aac\u660e\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-17\">FormRequest\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">FormRequest\u5c02\u7528\u306e\u30e6\u30cb\u30c3\u30c8\u30c6\u30b9\u30c8\u306e\u66f8\u304d\u65b9<\/h3>\n\n\n\n<p>FormRequest\u306e\u30c6\u30b9\u30c8\u306f\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3068\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u304c\u6b63\u3057\u304f\u6a5f\u80fd\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\u91cd\u8981\u306a\u5de5\u7a0b\u3067\u3059\u3002\u4ee5\u4e0b\u306b\u3001\u52b9\u679c\u7684\u306a\u30c6\u30b9\u30c8\u5b9f\u88c5\u306e\u65b9\u6cd5\u3092\u793a\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">namespace Tests\\Unit\\Http\\Requests;\n\nuse Tests\\TestCase;\nuse App\\Http\\Requests\\CreateProductRequest;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Illuminate\\Validation\\ValidationException;\n\nclass CreateProductRequestTest extends TestCase\n{\n    private CreateProductRequest $request;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n        $this-&gt;request = new CreateProductRequest();\n    }\n\n    \/**\n     * \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u30c6\u30b9\u30c8\n     *\/\n    public function test_validation_rules()\n    {\n        \/\/ \u671f\u5f85\u3055\u308c\u308b\u30eb\u30fc\u30eb\u306e\u5b9a\u7fa9\u3092\u78ba\u8a8d\n        $rules = $this-&gt;request-&gt;rules();\n\n        $this-&gt;assertEquals([\n            'name' =&gt; ['required', 'string', 'max:255'],\n            'price' =&gt; ['required', 'numeric', 'min:0'],\n            'description' =&gt; ['nullable', 'string'],\n        ], $rules);\n    }\n\n    \/**\n     * \u6b63\u5e38\u7cfb\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30c6\u30b9\u30c8\n     *\/\n    public function test_passes_valid_data()\n    {\n        $validator = Validator::make([\n            'name' =&gt; '\u5546\u54c1\u540d',\n            'price' =&gt; 1000,\n            'description' =&gt; '\u5546\u54c1\u306e\u8aac\u660e',\n        ], $this-&gt;request-&gt;rules());\n\n        $this-&gt;assertFalse($validator-&gt;fails());\n    }\n\n    \/**\n     * \u7570\u5e38\u7cfb\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30c6\u30b9\u30c8\n     *\/\n    public function test_fails_invalid_data()\n    {\n        $validator = Validator::make([\n            'name' =&gt; '',  \/\/ required\u9055\u53cd\n            'price' =&gt; -100,  \/\/ min:0\u9055\u53cd\n        ], $this-&gt;request-&gt;rules());\n\n        $this-&gt;assertTrue($validator-&gt;fails());\n        $this-&gt;assertArrayHasKey('name', $validator-&gt;errors()-&gt;toArray());\n        $this-&gt;assertArrayHasKey('price', $validator-&gt;errors()-&gt;toArray());\n    }\n\n    \/**\n     * \u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u30c6\u30b9\u30c8\n     *\/\n    public function test_custom_validation_rules()\n    {\n        $request = $this-&gt;createRequest([\n            'name' =&gt; '\u5546\u54c1\u540d',\n            'price' =&gt; 1000,\n            'stock' =&gt; 5,\n            'minimum_stock' =&gt; 10,\n        ]);\n\n        $validator = Validator::make(\n            $request-&gt;all(),\n            $request-&gt;rules()\n        );\n\n        $validator-&gt;after($request-&gt;withValidator($validator));\n\n        $this-&gt;assertTrue($validator-&gt;fails());\n        $this-&gt;assertArrayHasKey('stock', $validator-&gt;errors()-&gt;toArray());\n    }\n\n    \/**\n     * \u8a8d\u53ef\u30ed\u30b8\u30c3\u30af\u306e\u30c6\u30b9\u30c8\n     *\/\n    public function test_authorization()\n    {\n        $user = $this-&gt;createUser(['role' =&gt; 'admin']);\n        $this-&gt;actingAs($user);\n\n        $this-&gt;assertTrue($this-&gt;request-&gt;authorize());\n\n        $user = $this-&gt;createUser(['role' =&gt; 'guest']);\n        $this-&gt;actingAs($user);\n\n        $this-&gt;assertFalse($this-&gt;request-&gt;authorize());\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-19\">\u30c6\u30b9\u30c8\u6642\u306b\u3088\u304f\u767a\u751f\u3059\u308b\u30a8\u30e9\u30fc\u3068\u305d\u306e\u89e3\u6c7a\u65b9\u6cd5<\/h3>\n\n\n\n<p>FormRequest\u306e\u30c6\u30b9\u30c8\u5b9f\u88c5\u6642\u306b\u3088\u304f\u906d\u9047\u3059\u308b\u554f\u984c\u3068\u305d\u306e\u89e3\u6c7a\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30e2\u30c3\u30af\u306e\u6d3b\u7528<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ProductRequestTest extends TestCase\n{\n    public function test_unique_validation_with_mock()\n    {\n        \/\/ DB\u30a2\u30af\u30bb\u30b9\u3092\u30e2\u30c3\u30af\u5316\n        $this-&gt;mock(ProductRepository::class, function ($mock) {\n            $mock-&gt;shouldReceive('findByName')\n                 -&gt;with('\u65e2\u5b58\u5546\u54c1')\n                 -&gt;andReturn(true);\n        });\n\n        $validator = Validator::make([\n            'name' =&gt; '\u65e2\u5b58\u5546\u54c1'\n        ], $this-&gt;request-&gt;rules());\n\n        $this-&gt;assertTrue($validator-&gt;fails());\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30c6\u30b9\u30c8\u30d8\u30eb\u30d1\u30fc\u306e\u4f5c\u6210<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">trait FormRequestTestHelper\n{\n    protected function assertRequestValidationFails($requestClass, $data)\n    {\n        $request = new $requestClass();\n        $validator = Validator::make($data, $request-&gt;rules());\n\n        $this-&gt;assertTrue($validator-&gt;fails());\n        return $validator-&gt;errors();\n    }\n\n    protected function assertRequestValidationPasses($requestClass, $data)\n    {\n        $request = new $requestClass();\n        $validator = Validator::make($data, $request-&gt;rules());\n\n        $this-&gt;assertFalse($validator-&gt;fails());\n    }\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u8a8d\u8a3c\u30fb\u8a8d\u53ef\u306e\u30c6\u30b9\u30c8<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UpdateProductRequestTest extends TestCase\n{\n    public function test_authorization_with_different_roles()\n    {\n        $testCases = [\n            'admin' =&gt; true,\n            'manager' =&gt; true,\n            'user' =&gt; false,\n        ];\n\n        foreach ($testCases as $role =&gt; $expectedResult) {\n            $user = User::factory()-&gt;create(['role' =&gt; $role]);\n            $this-&gt;actingAs($user);\n\n            $request = new UpdateProductRequest();\n            $this-&gt;assertEquals($expectedResult, $request-&gt;authorize());\n        }\n    }\n}<\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u30c6\u30b9\u30c8<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserRequestTest extends TestCase\n{\n    public function test_custom_error_messages()\n    {\n        $request = new CreateUserRequest();\n\n        $validator = Validator::make([\n            'email' =&gt; 'invalid-email',\n        ], $request-&gt;rules(), $request-&gt;messages());\n\n        $errors = $validator-&gt;errors();\n\n        $this-&gt;assertEquals(\n            '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306e\u5f62\u5f0f\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002',\n            $errors-&gt;first('email')\n        );\n    }\n}<\/pre>\n\n\n\n<p>FormRequest\u306e\u30c6\u30b9\u30c8\u3092\u9069\u5207\u306b\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30ed\u30b8\u30c3\u30af\u306e\u4fe1\u983c\u6027\u3092\u78ba\u4fdd\u3057\u3001\u4e88\u671f\u305b\u306c\u30d0\u30b0\u306e\u65e9\u671f\u767a\u898b\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001FormRequest\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3068\u30d2\u30f3\u30c8\u306b\u3064\u3044\u3066\u8aac\u660e\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-20\">FormRequest\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3068\u30d2\u30f3\u30c8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-21\">FormRequest\u306e\u5171\u901a\u51e6\u7406\u3092\u89aa\u30af\u30e9\u30b9\u306b\u5b9f\u88c5\u3059\u308b<\/h3>\n\n\n\n<p>\u5927\u898f\u6a21\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u3001FormRequest\u9593\u3067\u5171\u901a\u3059\u308b\u51e6\u7406\u3092\u89aa\u30af\u30e9\u30b9\u306b\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001\u30b3\u30fc\u30c9\u306e\u91cd\u8907\u3092\u907f\u3051\u3001\u4fdd\u5b88\u6027\u3092\u5411\u4e0a\u3055\u305b\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">abstract class BaseFormRequest extends FormRequest\n{\n    \/**\n     * \u5171\u901a\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\n     *\/\n    protected function baseRules(): array\n    {\n        return [\n            'created_by' =&gt; 'exists:users,id',\n            'updated_by' =&gt; 'exists:users,id',\n        ];\n    }\n\n    \/**\n     * \u5171\u901a\u306e\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\n     *\/\n    protected function baseMessages(): array\n    {\n        return [\n            'required' =&gt; ':attribute\u306f\u5fc5\u9808\u9805\u76ee\u3067\u3059\u3002',\n            'string' =&gt; ':attribute\u306f\u6587\u5b57\u5217\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n            'max' =&gt; ':attribute\u306f:max\u6587\u5b57\u4ee5\u5185\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n        ];\n    }\n\n    \/**\n     * \u5171\u901a\u306e\u8a8d\u53ef\u30ed\u30b8\u30c3\u30af\n     *\/\n    public function authorize(): bool\n    {\n        return $this-&gt;user() !== null;\n    }\n\n    \/**\n     * \u30b0\u30ed\u30fc\u30d0\u30eb\u306a\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u524d\u51e6\u7406\n     *\/\n    protected function prepareForValidation()\n    {\n        $this-&gt;merge([\n            'updated_by' =&gt; $this-&gt;user()-&gt;id,\n        ]);\n    }\n\n    \/**\n     * \u5171\u901a\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\n     *\/\n    protected function failedValidation(Validator $validator)\n    {\n        \/\/ \u30ed\u30b0\u51fa\u529b\n        Log::warning('Validation failed', [\n            'request' =&gt; $this-&gt;route()-&gt;getName(),\n            'errors' =&gt; $validator-&gt;errors()-&gt;toArray(),\n            'input' =&gt; $this-&gt;except(['password']),\n        ]);\n\n        parent::failedValidation($validator);\n    }\n}\n\n\/\/ \u5177\u4f53\u7684\u306a\u5b9f\u88c5\u4f8b\nclass CreateProductRequest extends BaseFormRequest\n{\n    public function rules(): array\n    {\n        return array_merge($this-&gt;baseRules(), [\n            'name' =&gt; 'required|string|max:255',\n            'price' =&gt; 'required|numeric|min:0',\n        ]);\n    }\n\n    public function messages(): array\n    {\n        return array_merge($this-&gt;baseMessages(), [\n            'price.min' =&gt; '\u4fa1\u683c\u306f0\u4ee5\u4e0a\u3067\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002',\n        ]);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-22\">\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u518d\u5229\u7528\u3068DRY\u539f\u5247\u306e\u5b9f\u8df5<\/h3>\n\n\n\n<p>\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u3092\u518d\u5229\u7528\u53ef\u80fd\u306a\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3068\u3057\u3066\u8a2d\u8a08\u3059\u308b\u3053\u3068\u3067\u3001\u4fdd\u5b88\u6027\u3068\u4e00\u8cab\u6027\u3092\u5411\u4e0a\u3055\u305b\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30eb\u30fc\u30eb\u306e\u30c8\u30ec\u30a4\u30c8\ntrait HasAddressValidation\n{\n    protected function addressRules(): array\n    {\n        return [\n            'postal_code' =&gt; ['required', 'string', 'size:7'],\n            'prefecture' =&gt; ['required', 'string', Rule::in(config('prefectures'))],\n            'city' =&gt; ['required', 'string', 'max:255'],\n            'street' =&gt; ['required', 'string', 'max:255'],\n            'building' =&gt; ['nullable', 'string', 'max:255'],\n        ];\n    }\n}\n\ntrait HasContactValidation\n{\n    protected function contactRules(): array\n    {\n        return [\n            'email' =&gt; ['required', 'email', 'max:255'],\n            'phone' =&gt; ['required', 'string', 'regex:\/^[0-9-]{10,11}$\/'],\n        ];\n    }\n}\n\n\/\/ \u30eb\u30fc\u30eb\u30bb\u30c3\u30c8\u306e\u4f5c\u6210\nclass ValidationRuleSets\n{\n    public static function passwordRules(): array\n    {\n        return [\n            'required',\n            'string',\n            'min:8',\n            'regex:\/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$\/',\n        ];\n    }\n\n    public static function imageRules(int $maxSize = 5120): array\n    {\n        return [\n            'required',\n            'image',\n            'mimes:jpeg,png,jpg',\n            \"max:{$maxSize}\",\n        ];\n    }\n}\n\n\/\/ \u5b9f\u969b\u306eFormRequest\u3067\u306e\u4f7f\u7528\nclass CustomerRegistrationRequest extends BaseFormRequest\n{\n    use HasAddressValidation, HasContactValidation;\n\n    public function rules(): array\n    {\n        return array_merge(\n            $this-&gt;addressRules(),\n            $this-&gt;contactRules(),\n            [\n                'name' =&gt; ['required', 'string', 'max:255'],\n                'password' =&gt; ValidationRuleSets::passwordRules(),\n                'avatar' =&gt; ValidationRuleSets::imageRules(),\n            ]\n        );\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-23\">\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306eFormRequest\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3<\/h3>\n\n\n\n<p>\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u3001FormRequest\u3092\u52b9\u7387\u7684\u306b\u7ba1\u7406\u3059\u308b\u305f\u3081\u306e\u8a2d\u8a08\u30d1\u30bf\u30fc\u30f3\u304c\u91cd\u8981\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/\/ \u30c9\u30e1\u30a4\u30f3\u5225\u306eFormRequest\u306e\u57fa\u5e95\u30af\u30e9\u30b9\nnamespace App\\Http\\Requests\\User;\n\nabstract class UserBaseRequest extends BaseFormRequest\n{\n    protected function userRules(): array\n    {\n        return [\n            'name' =&gt; ['required', 'string', 'max:255'],\n            'email' =&gt; ['required', 'email', Rule::unique('users')-&gt;ignore($this-&gt;user)],\n        ];\n    }\n}\n\n\/\/ \u30d5\u30a9\u30fc\u30e0\u30ea\u30af\u30a8\u30b9\u30c8\u30d5\u30a1\u30af\u30c8\u30ea\u30fc\nclass FormRequestFactory\n{\n    public static function create(string $type, array $data = []): FormRequest\n    {\n        return match ($type) {\n            'user.create' =&gt; new CreateUserRequest($data),\n            'user.update' =&gt; new UpdateUserRequest($data),\n            'product.create' =&gt; new CreateProductRequest($data),\n            default =&gt; throw new InvalidArgumentException('Unknown request type'),\n        };\n    }\n}\n\n\/\/ \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u30b5\u30fc\u30d3\u30b9\nclass ValidationService\n{\n    public function validateWithRules(array $data, array $rules): array\n    {\n        return Validator::make($data, $rules)-&gt;validate();\n    }\n\n    public function validateWithRequest(string $requestType, array $data): array\n    {\n        $request = FormRequestFactory::create($requestType, $data);\n        return $this-&gt;validateWithRules($data, $request-&gt;rules());\n    }\n}\n\n\/\/ \u30d3\u30b8\u30cd\u30b9\u30eb\u30fc\u30eb\u306e\u30d0\u30ea\u30c7\u30fc\u30bf\nclass BusinessRuleValidator\n{\n    public function validateInventory(Product $product, int $quantity): bool\n    {\n        return $product-&gt;stock &gt;= $quantity;\n    }\n\n    public function validateUserSubscription(User $user, string $feature): bool\n    {\n        return $user-&gt;subscription-&gt;hasFeature($feature);\n    }\n}\n\n\/\/ FormRequest\u3067\u306e\u4f7f\u7528\u4f8b\nclass CreateOrderRequest extends BaseFormRequest\n{\n    private BusinessRuleValidator $validator;\n\n    public function __construct(BusinessRuleValidator $validator)\n    {\n        $this-&gt;validator = $validator;\n    }\n\n    public function withValidator($validator)\n    {\n        $validator-&gt;after(function ($validator) {\n            $product = Product::find($this-&gt;input('product_id'));\n\n            if (!$this-&gt;validator-&gt;validateInventory($product, $this-&gt;input('quantity'))) {\n                $validator-&gt;errors()-&gt;add('quantity', '\u5728\u5eab\u304c\u4e0d\u8db3\u3057\u3066\u3044\u307e\u3059\u3002');\n            }\n\n            if (!$this-&gt;validator-&gt;validateUserSubscription($this-&gt;user(), 'create_order')) {\n                $validator-&gt;errors()-&gt;add('subscription', '\u3053\u306e\u6a5f\u80fd\u3092\u5229\u7528\u3059\u308b\u306b\u306f\u3001\u30b5\u30d6\u30b9\u30af\u30ea\u30d7\u30b7\u30e7\u30f3\u306e\u30a2\u30c3\u30d7\u30b0\u30ec\u30fc\u30c9\u304c\u5fc5\u8981\u3067\u3059\u3002');\n            }\n        });\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u4fdd\u5b88\u6027\u304c\u9ad8\u304f\u3001\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb\u306aFormRequest\u306e\u5b9f\u88c5\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002\u7279\u306b\u5927\u898f\u6a21\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306f\u3001\u3053\u308c\u3089\u306e\u30d1\u30bf\u30fc\u30f3\u3092\u9069\u5207\u306b\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u52b9\u7387\u7684\u306a\u30b3\u30fc\u30c9\u7ba1\u7406\u3068\u958b\u767a\u304c\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warning: Undefined array key &#8220;is_admin&#8221; in \/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/ &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":{"0":"post-2605","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-php","7":"nothumb"},"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2605"}],"version-history":[{"count":2,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2605\/revisions"}],"predecessor-version":[{"id":2607,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2605\/revisions\/2607"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}