{"id":2476,"date":"2025-03-24T08:47:12","date_gmt":"2025-03-23T23:47:12","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=2476"},"modified":"2025-03-24T08:47:42","modified_gmt":"2025-03-23T23:47:42","slug":"php-slim%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9a%e8%bb%bd%e9%87%8f%e7%b4%9a%e3%83%95%e3%83%ac%e3%83%bc%e3%83%a0%e3%83%af%e3%83%bc%e3%82%af%e3%81%a7%e4%bd%9c%e3%82%8b%e9%ab%98%e9%80%9f","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=2476","title":{"rendered":"PHP Slim\u5b8c\u5168\u30ac\u30a4\u30c9\uff1a\u8efd\u91cf\u7d1a\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u4f5c\u308b\u9ad8\u901f\u306aWeb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3"},"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\">Slim Framework\u3068\u306f\uff1a\u7279\u5fb4\u3068\u5f37\u307f<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">\u30de\u30a4\u30af\u30ed\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u306e\u738b\u9053\uff1a\u8efd\u91cf\u3067\u9ad8\u901f\u306a\u958b\u767a\u304c\u53ef\u80fd<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-2\">Laravel\u30fbSymfony\u3068\u306e\u9055\u3044\uff1aSlim\u3092\u9078\u3076\u3079\u304d\u30b7\u30fc\u30f3<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-3\">Slim Framework \u5c0e\u5165\u304b\u3089Hello World\u307e\u3067<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-4\">Composer\u3092\u4f7f\u3063\u305f\u6700\u65b0\u7248\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-5\">\u57fa\u672c\u7684\u306a\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u306e\u8a2d\u5b9a\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-6\">\u30b7\u30f3\u30d7\u30eb\u306aAPI\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u4f5c\u6210<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-7\">\u5b9f\u8df5\u7684\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u958b\u767a\u624b\u6cd5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-8\">\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u3092\u6d3b\u7528\u3057\u305f\u30ea\u30af\u30a8\u30b9\u30c8\u51e6\u7406\u306e\u5b9f\u88c5<\/a>      <\/li>      <li>        <a href=\"#i-9\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u9023\u643a\uff1aPDO\u3068Eloquent\u306e\u6d3b\u7528<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-10\">DI\u30b3\u30f3\u30c6\u30ca\u3092\u4f7f\u3063\u305f\u4f9d\u5b58\u6027\u306e\u7ba1\u7406<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-11\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-12\">\u30ad\u30e3\u30c3\u30b7\u30e5\u6226\u7565\uff1a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u9ad8\u901f\u5316\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-13\">\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-14\">\u672c\u756a\u74b0\u5883\u3067\u306e\u5b9f\u8df5\u7684\u306a\u30c7\u30d7\u30ed\u30a4\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-15\">\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56\u3068\u904b\u7528\u306e\u30dd\u30a4\u30f3\u30c8<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-16\">\u4e00\u822c\u7684\u306a\u8106\u5f31\u6027\u5bfe\u7b56\u3068\u30b9\u30ea\u30e0\u56fa\u6709\u306e\u6ce8\u610f\u70b9<\/a>      <\/li>      <li>        <a href=\"#i-17\">\u30ed\u30b0\u7ba1\u7406\u3068\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-18\">\u30e6\u30cb\u30c3\u30c8\u30c6\u30b9\u30c8\u3068CI\u306e\u5c0e\u5165\u65b9\u6cd5<\/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\">Slim Framework\u3068\u306f\uff1a\u7279\u5fb4\u3068\u5f37\u307f<\/h2>\n\n\n\n<p>Slim Framework\u306f\u3001PHP\u958b\u767a\u8005\u306e\u9593\u3067\u9ad8\u3044\u8a55\u4fa1\u3092\u53d7\u3051\u3066\u3044\u308b\u30de\u30a4\u30af\u30ed\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3067\u3059\u3002\u300c\u5fc5\u8981\u6700\u5c0f\u9650\u306e\u6a5f\u80fd\u300d\u3068\u300c\u9ad8\u3044\u62e1\u5f35\u6027\u300d\u3092\u517c\u306d\u5099\u3048\u3001REST API\u3084\u30b7\u30f3\u30d7\u30eb\u306aWeb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u958b\u767a\u306b\u6700\u9069\u306a\u30c4\u30fc\u30eb\u3068\u3057\u3066\u77e5\u3089\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">\u30de\u30a4\u30af\u30ed\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u306e\u738b\u9053\uff1a\u8efd\u91cf\u3067\u9ad8\u901f\u306a\u958b\u767a\u304c\u53ef\u80fd<\/h3>\n\n\n\n<p>Slim Framework\u306e\u6700\u5927\u306e\u7279\u5fb4\u306f\u3001\u305d\u306e\u540d\u306e\u901a\u308a\u300c\u30b9\u30ea\u30e0\u300d\u3067\u3042\u308b\u3053\u3068\u3067\u3059\u3002\u57fa\u672c\u6a5f\u80fd\u306b\u7d5e\u3089\u308c\u305f\u30b3\u30a2\u30d1\u30c3\u30b1\u30fc\u30b8\u306f\u3001\u308f\u305a\u304b\u6570\u767eKB\u306e\u30b5\u30a4\u30ba\u306b\u53ce\u307e\u3063\u3066\u3044\u307e\u3059\u3002\u3053\u306e\u8efd\u91cf\u3055\u304c\u3082\u305f\u3089\u3059\u5229\u70b9\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u512a\u308c\u305f\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6700\u5c0f\u9650\u306e\u30aa\u30fc\u30d0\u30fc\u30d8\u30c3\u30c9<\/li>\n\n\n\n<li>\u30ea\u30af\u30a8\u30b9\u30c8\u51e6\u7406\u306e\u9ad8\u901f\u5316<\/li>\n\n\n\n<li>\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u6700\u9069\u5316<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u77ed\u3044\u5b66\u7fd2\u66f2\u7dda<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30b7\u30f3\u30d7\u30eb\u306a\u8a2d\u8a08\u601d\u60f3<\/li>\n\n\n\n<li>\u76f4\u611f\u7684\u306a\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0API<\/li>\n\n\n\n<li>\u660e\u78ba\u306a\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u67d4\u8edf\u306a\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u6027<\/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=\"\">   \/\/ \u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u8ffd\u52a0\u304c\u7c21\u5358\n   $app-&gt;add(new \\Slim\\Middleware\\Session());\n\n   \/\/ PSR-7\u6e96\u62e0\u306e\u30ea\u30af\u30a8\u30b9\u30c8\/\u30ec\u30b9\u30dd\u30f3\u30b9\u51e6\u7406\n   $app-&gt;get('\/api\/users', function (Request $request, Response $response) {\n       return $response-&gt;withJson(['status' =&gt; 'success']);\n   });<\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>\u30e2\u30c0\u30f3\u306aPHP\u6a5f\u80fd\u306e\u30b5\u30dd\u30fc\u30c8<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PSR-7, PSR-11, PSR-15\u5bfe\u5fdc<\/li>\n\n\n\n<li>Composer\u5bfe\u5fdc<\/li>\n\n\n\n<li>PHP 7.4\u4ee5\u4e0a\u306e\u65b0\u6a5f\u80fd\u6d3b\u7528<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">Laravel\u30fbSymfony\u3068\u306e\u9055\u3044\uff1aSlim\u3092\u9078\u3076\u3079\u304d\u30b7\u30fc\u30f3<\/h3>\n\n\n\n<p>Slim Framework\u3068PHP\u306e\u4e3b\u8981\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u3092\u6bd4\u8f03\u3059\u308b\u3053\u3068\u3067\u3001\u305d\u306e\u72ec\u81ea\u306e\u4f4d\u7f6e\u3065\u3051\u304c\u660e\u78ba\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n<div id=\"id-ae810509-d50d-4852-937c-11443f2c4e0b\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6a5f\u80fd\u6bd4\u8f03<\/th><th>Slim<\/th><th>Laravel<\/th><th>Symfony<\/th><\/tr><\/thead><tbody><tr><td>\u521d\u671f\u30b5\u30a4\u30ba<\/td><td>~300KB<\/td><td>~10MB<\/td><td>~8MB<\/td><\/tr><tr><td>\u5b66\u7fd2\u30b3\u30b9\u30c8<\/td><td>\u4f4e<\/td><td>\u4e2d\u301c\u9ad8<\/td><td>\u9ad8<\/td><\/tr><tr><td>\u6a5f\u80fd\u306e\u8c4a\u5bcc\u3055<\/td><td>\u6700\u5c0f\u9650<\/td><td>\u8c4a\u5bcc<\/td><td>\u975e\u5e38\u306b\u8c4a\u5bcc<\/td><\/tr><tr><td>\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u6027<\/td><td>\u9ad8<\/td><td>\u4e2d<\/td><td>\u9ad8<\/td><\/tr><tr><td>\u958b\u767a\u901f\u5ea6<\/td><td>\u901f\u3044<\/td><td>\u666e\u901a<\/td><td>\u666e\u901a<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p><strong>Slim\u304c\u6700\u9069\u306a\u30b7\u30fc\u30f3\uff1a<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30de\u30a4\u30af\u30ed\u30b5\u30fc\u30d3\u30b9\u306e\u958b\u767a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u8efd\u91cf\u306aAPI\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8<\/li>\n\n\n\n<li>\u7279\u5b9a\u306e\u6a5f\u80fd\u306b\u7279\u5316\u3057\u305f\u30b5\u30fc\u30d3\u30b9<\/li>\n\n\n\n<li>\u30b3\u30f3\u30c6\u30ca\u5316\u3055\u308c\u305f\u74b0\u5883\u3067\u306e\u904b\u7528<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d7\u30ed\u30c8\u30bf\u30a4\u30d7\u306e\u8fc5\u901f\u306a\u958b\u767a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>MVP\uff08\u6700\u5c0f\u5b9f\u884c\u88fd\u54c1\uff09\u306e\u4f5c\u6210<\/li>\n\n\n\n<li>\u30d7\u30eb\u30fc\u30d5\u30aa\u30d6\u30b3\u30f3\u30bb\u30d7\u30c8<\/li>\n\n\n\n<li>\u5b9f\u9a13\u7684\u306a\u6a5f\u80fd\u306e\u5b9f\u88c5<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30ea\u30bd\u30fc\u30b9\u304c\u9650\u3089\u308c\u305f\u74b0\u5883\u3067\u306e\u904b\u7528<\/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=\"\">   \/\/ \u6700\u5c0f\u9650\u306e\u8a2d\u5b9a\u3067\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u8d77\u52d5\n   $app = AppFactory::create();\n   $app-&gt;get('\/', function (Request $request, Response $response) {\n       $response-&gt;getBody()-&gt;write('Hello, World!');\n       return $response;\n   });\n   $app-&gt;run();<\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>\u30ec\u30ac\u30b7\u30fc\u30b7\u30b9\u30c6\u30e0\u306e\u30e2\u30c0\u30f3\u5316<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6bb5\u968e\u7684\u306a\u30ea\u30d7\u30ec\u30fc\u30b9<\/li>\n\n\n\n<li>API\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u3068\u3057\u3066\u306e\u6d3b\u7528<\/li>\n\n\n\n<li>\u65e2\u5b58\u30b7\u30b9\u30c6\u30e0\u3068\u306e\u7d71\u5408<\/li>\n<\/ul>\n\n\n\n<p>\u9078\u629e\u306e\u969b\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\u306f\u3001<strong>\u5fc5\u8981\u306a\u6a5f\u80fd\u304c\u660e\u78ba\u306b\u306a\u3063\u3066\u3044\u308b\u3053\u3068<\/strong>\u3067\u3059\u3002\u30d5\u30eb\u30b9\u30bf\u30c3\u30af\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u304c\u63d0\u4f9b\u3059\u308b\u591a\u304f\u306e\u6a5f\u80fd\u304c\u4e0d\u8981\u306a\u5834\u5408\u3001Slim\u306f\u7406\u60f3\u7684\u306a\u9078\u629e\u80a2\u3068\u306a\u308a\u307e\u3059\u3002\u7279\u306b\u3001\u30de\u30a4\u30af\u30ed\u30b5\u30fc\u30d3\u30b9\u30a2\u30fc\u30ad\u30c6\u30af\u30c1\u30e3\u306e\u63a1\u7528\u3084API\u306e\u958b\u767a\u306b\u304a\u3044\u3066\u3001\u305d\u306e\u771f\u4fa1\u3092\u767a\u63ee\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-3\">Slim Framework \u5c0e\u5165\u304b\u3089Hello World\u307e\u3067<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-4\">Composer\u3092\u4f7f\u3063\u305f\u6700\u65b0\u7248\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u65b9\u6cd5<\/h3>\n\n\n\n<p>Slim Framework 4.x\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306f\u3001Composer\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u7c21\u5358\u306b\u884c\u3048\u307e\u3059\u3002\u4ee5\u4e0b\u306e\u30b9\u30c6\u30c3\u30d7\u306b\u5f93\u3063\u3066\u74b0\u5883\u3092\u69cb\u7bc9\u3057\u3066\u3044\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\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=\"\">   mkdir my-slim-app\n   cd my-slim-app<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Composer\u306e\u521d\u671f\u5316<\/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=\"\">   composer init --no-interaction \\\n       --name=myapp\/slim-project \\\n       --description=\"My First Slim Framework Project\" \\\n       --author=\"Your Name &lt;you@example.com&gt;\" \\\n       --require=\"slim\/slim:^4.12\" \\\n       --require-dev=\"phpunit\/phpunit:^10.0\"<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u5fc5\u8981\u306a\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb<\/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=\"\">   # PSR-7\u5b9f\u88c5\u3068\u30d5\u30a1\u30af\u30c8\u30ea\u30fc\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n   composer require slim\/psr7\n\n   # PHP-DI\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\uff08\u4f9d\u5b58\u6027\u6ce8\u5165\u30b3\u30f3\u30c6\u30ca\uff09\n   composer require php-di\/php-di<\/pre>\n\n\n\n<p>\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\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=\"\">my-slim-app\/\n\u251c\u2500\u2500 composer.json\n\u251c\u2500\u2500 composer.lock\n\u251c\u2500\u2500 public\/\n\u2502   \u2514\u2500\u2500 index.php\n\u251c\u2500\u2500 src\/\n\u2502   \u2514\u2500\u2500 Controllers\/\n\u2514\u2500\u2500 vendor\/<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">\u57fa\u672c\u7684\u306a\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u306e\u8a2d\u5b9a\u65b9\u6cd5<\/h3>\n\n\n\n<p>Slim Framework\u306e\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u306f\u3001\u76f4\u611f\u7684\u3067\u67d4\u8edf\u306a\u8a2d\u8a08\u304c\u7279\u5fb4\u3067\u3059\u3002\u57fa\u672c\u7684\u306a\u8a2d\u5b9a\u65b9\u6cd5\u3092\u898b\u3066\u3044\u304d\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30a8\u30f3\u30c8\u30ea\u30fc\u30dd\u30a4\u30f3\u30c8\u306e\u4f5c\u6210<\/strong> (<code>public\/index.php<\/code>)<\/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=\"\">   &lt;?php\n   use Psr\\Http\\Message\\ResponseInterface as Response;\n   use Psr\\Http\\Message\\ServerRequestInterface as Request;\n   use Slim\\Factory\\AppFactory;\n\n   require __DIR__ . '\/..\/vendor\/autoload.php';\n\n   \/\/ \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u521d\u671f\u5316\n   $app = AppFactory::create();\n\n   \/\/ \u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u8ffd\u52a0\n   $app-&gt;addErrorMiddleware(true, true, true);\n\n   \/\/ \u30d9\u30fc\u30b7\u30c3\u30af\u306a\u30eb\u30fc\u30c8\n   $app-&gt;get('\/', function (Request $request, Response $response) {\n       $response-&gt;getBody()-&gt;write('Hello World!');\n       return $response;\n   });\n\n   \/\/ \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u5b9f\u884c\n   $app-&gt;run();<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u69d8\u3005\u306aHTTP\u30e1\u30bd\u30c3\u30c9\u306e\u5229\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=\"\">   \/\/ GET\u30ea\u30af\u30a8\u30b9\u30c8\n   $app-&gt;get('\/users', function (Request $request, Response $response) {\n       \/\/ \u30e6\u30fc\u30b6\u30fc\u4e00\u89a7\u306e\u53d6\u5f97\n       return $response-&gt;withJson(['users' =&gt; ['John', 'Jane']]);\n   });\n\n   \/\/ POST\u30ea\u30af\u30a8\u30b9\u30c8\n   $app-&gt;post('\/users', function (Request $request, Response $response) {\n       \/\/ \u65b0\u898f\u30e6\u30fc\u30b6\u30fc\u306e\u4f5c\u6210\n       $data = $request-&gt;getParsedBody();\n       return $response-&gt;withJson(['status' =&gt; 'created']);\n   });\n\n   \/\/ \u30d7\u30ec\u30fc\u30b9\u30db\u30eb\u30c0\u30fc\u306e\u4f7f\u7528\n   $app-&gt;get('\/users\/{id}', function (Request $request, Response $response, array $args) {\n       $userId = $args['id'];\n       return $response-&gt;withJson(['user_id' =&gt; $userId]);\n   });<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">\u30b7\u30f3\u30d7\u30eb\u306aAPI\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u4f5c\u6210<\/h3>\n\n\n\n<p>\u5b9f\u8df5\u7684\u306aAPI\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u4f5c\u6210\u4f8b\u3092\u898b\u3066\u3044\u304d\u307e\u3057\u3087\u3046\u3002\u4ee5\u4e0b\u306f\u3001\u57fa\u672c\u7684\u306aCRUD\u64cd\u4f5c\u3092\u5b9f\u88c5\u3057\u305f\u4f8b\u3067\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=\"\">&lt;?php\n\/\/ src\/Controllers\/UserController.php\n\nnamespace App\\Controllers;\n\nuse Psr\\Http\\Message\\ResponseInterface as Response;\nuse Psr\\Http\\Message\\ServerRequestInterface as Request;\n\nclass UserController\n{\n    private $users = [\n        ['id' =&gt; 1, 'name' =&gt; '\u5c71\u7530\u592a\u90ce', 'email' =&gt; 'yamada@example.com'],\n        ['id' =&gt; 2, 'name' =&gt; '\u9234\u6728\u82b1\u5b50', 'email' =&gt; 'suzuki@example.com']\n    ];\n\n    public function getUsers(Request $request, Response $response): Response\n    {\n        $response-&gt;getBody()-&gt;write(json_encode([\n            'status' =&gt; 'success',\n            'data' =&gt; $this-&gt;users\n        ]));\n\n        return $response\n            -&gt;withHeader('Content-Type', 'application\/json')\n            -&gt;withStatus(200);\n    }\n\n    public function getUserById(Request $request, Response $response, array $args): Response\n    {\n        $userId = (int) $args['id'];\n        $user = array_filter($this-&gt;users, fn($u) =&gt; $u['id'] === $userId);\n\n        if (empty($user)) {\n            return $response\n                -&gt;withHeader('Content-Type', 'application\/json')\n                -&gt;withStatus(404);\n        }\n\n        $response-&gt;getBody()-&gt;write(json_encode([\n            'status' =&gt; 'success',\n            'data' =&gt; reset($user)\n        ]));\n\n        return $response\n            -&gt;withHeader('Content-Type', 'application\/json')\n            -&gt;withStatus(200);\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u3092<code>index.php<\/code>\u3067\u767b\u9332\u3057\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=\"\">\/\/ \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u306e\u30eb\u30fc\u30c8\u767b\u9332\n$app-&gt;get('\/api\/users', [UserController::class, 'getUsers']);\n$app-&gt;get('\/api\/users\/{id}', [UserController::class, 'getUserById']);<\/pre>\n\n\n\n<p>\u3053\u306eAPI\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u5f62\u5f0f\u3067\u30c6\u30b9\u30c8\u3067\u304d\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=\"\"># \u30e6\u30fc\u30b6\u30fc\u4e00\u89a7\u306e\u53d6\u5f97\ncurl http:\/\/localhost:8080\/api\/users\n\n# \u7279\u5b9a\u306e\u30e6\u30fc\u30b6\u30fc\u306e\u53d6\u5f97\ncurl http:\/\/localhost:8080\/api\/users\/1<\/pre>\n\n\n\n<p>\u958b\u767a\u30b5\u30fc\u30d0\u30fc\u306e\u8d77\u52d5\u306f\u4ee5\u4e0b\u306e\u30b3\u30de\u30f3\u30c9\u3067\u884c\u3044\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=\"\"># PHP\u306e\u5185\u8535\u30b5\u30fc\u30d0\u30fc\u3092\u4f7f\u7528\nphp -S localhost:8080 -t public<\/pre>\n\n\n\n<p>\u3053\u308c\u3067\u57fa\u672c\u7684\u306aSlim Framework\u306e\u74b0\u5883\u69cb\u7bc9\u3068API\u306e\u5b9f\u88c5\u304c\u5b8c\u4e86\u3057\u307e\u3057\u305f\u3002\u6b21\u306e\u30b9\u30c6\u30c3\u30d7\u3067\u306f\u3001\u3088\u308a\u5b9f\u8df5\u7684\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u958b\u767a\u624b\u6cd5\u306b\u3064\u3044\u3066\u898b\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-7\">\u5b9f\u8df5\u7684\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u958b\u767a\u624b\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u3092\u6d3b\u7528\u3057\u305f\u30ea\u30af\u30a8\u30b9\u30c8\u51e6\u7406\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<p>\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306f\u3001HTTP\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u51e6\u7406\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u3092\u67d4\u8edf\u306b\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3067\u304d\u308b\u5f37\u529b\u306a\u6a5f\u80fd\u3067\u3059\u3002\u8a8d\u8a3c\u3001\u30ed\u30ae\u30f3\u30b0\u3001CORS\u306a\u3069\u3001\u69d8\u3005\u306a\u6a2a\u65ad\u7684\u95a2\u5fc3\u4e8b\u3092\u52b9\u7387\u7684\u306b\u51e6\u7406\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u57fa\u672c\u7684\u306a\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Middleware\/JsonResponseMiddleware.php\nnamespace App\\Middleware;\n\nuse Psr\\Http\\Message\\ResponseInterface as Response;\nuse Psr\\Http\\Message\\ServerRequestInterface as Request;\nuse Psr\\Http\\Server\\MiddlewareInterface;\nuse Psr\\Http\\Server\\RequestHandlerInterface as RequestHandler;\n\nclass JsonResponseMiddleware implements MiddlewareInterface\n{\n    public function process(Request $request, RequestHandler $handler): Response\n    {\n        $response = $handler-&gt;handle($request);\n        return $response-&gt;withHeader('Content-Type', 'application\/json');\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u8a8d\u8a3c\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u4f8b<\/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=\"\">&lt;?php\n\/\/ src\/Middleware\/AuthMiddleware.php\nnamespace App\\Middleware;\n\nclass AuthMiddleware implements MiddlewareInterface\n{\n    public function process(Request $request, RequestHandler $handler): Response\n    {\n        $token = $request-&gt;getHeaderLine('Authorization');\n\n        if (empty($token)) {\n            $response = new Response();\n            return $response\n                -&gt;withStatus(401)\n                -&gt;withJson(['error' =&gt; '\u8a8d\u8a3c\u304c\u5fc5\u8981\u3067\u3059']);\n        }\n\n        \/\/ \u30c8\u30fc\u30af\u30f3\u306e\u691c\u8a3c\u30ed\u30b8\u30c3\u30af\n        if (!$this-&gt;validateToken($token)) {\n            $response = new Response();\n            return $response\n                -&gt;withStatus(403)\n                -&gt;withJson(['error' =&gt; '\u7121\u52b9\u306a\u30c8\u30fc\u30af\u30f3\u3067\u3059']);\n        }\n\n        return $handler-&gt;handle($request);\n    }\n\n    private function validateToken(string $token): bool\n    {\n        \/\/ \u30c8\u30fc\u30af\u30f3\u691c\u8a3c\u306e\u5b9f\u88c5\n        return true; \/\/ \u5b9f\u969b\u306e\u691c\u8a3c\u30ed\u30b8\u30c3\u30af\u3092\u5b9f\u88c5\n    }\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u767b\u9332<\/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=\"\">\/\/ \u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u30b0\u30ed\u30fc\u30d0\u30eb\u9069\u7528\n$app-&gt;add(new JsonResponseMiddleware());\n\n\/\/ \u7279\u5b9a\u306e\u30eb\u30fc\u30c8\u30b0\u30eb\u30fc\u30d7\u306b\u306e\u307f\u9069\u7528\n$app-&gt;group('\/api', function (Group $group) {\n    $group-&gt;get('\/users', [UserController::class, 'getUsers']);\n})-&gt;add(new AuthMiddleware());<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u9023\u643a\uff1aPDO\u3068Eloquent\u306e\u6d3b\u7528<\/h3>\n\n\n\n<p>Slim Framework\u3067\u306fPDO\u3092\u76f4\u63a5\u4f7f\u7528\u3059\u308b\u304b\u3001Eloquent\u306a\u3069\u306eORM\u3092\u7d71\u5408\u3059\u308b\u3053\u3068\u3067\u3001\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u64cd\u4f5c\u3092\u52b9\u7387\u7684\u306b\u884c\u3048\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>PDO\u3092\u4f7f\u7528\u3057\u305f\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Database\/Database.php\nnamespace App\\Database;\n\nclass Database\n{\n    private static $instance = null;\n    private $pdo;\n\n    private function __construct()\n    {\n        $host = $_ENV['DB_HOST'] ?? 'localhost';\n        $dbname = $_ENV['DB_NAME'] ?? 'slim_app';\n        $user = $_ENV['DB_USER'] ?? 'root';\n        $pass = $_ENV['DB_PASS'] ?? '';\n\n        $dsn = \"mysql:host=$host;dbname=$dbname;charset=utf8mb4\";\n        $this-&gt;pdo = new \\PDO($dsn, $user, $pass, [\n            \\PDO::ATTR_ERRMODE =&gt; \\PDO::ERRMODE_EXCEPTION,\n            \\PDO::ATTR_DEFAULT_FETCH_MODE =&gt; \\PDO::FETCH_ASSOC,\n            \\PDO::ATTR_EMULATE_PREPARES =&gt; false,\n        ]);\n    }\n\n    public static function getInstance(): self\n    {\n        if (self::$instance === null) {\n            self::$instance = new self();\n        }\n        return self::$instance;\n    }\n\n    public function getConnection(): \\PDO\n    {\n        return $this-&gt;pdo;\n    }\n}\n\n\/\/ \u4f7f\u7528\u4f8b\nclass UserRepository\n{\n    private $db;\n\n    public function __construct()\n    {\n        $this-&gt;db = Database::getInstance()-&gt;getConnection();\n    }\n\n    public function findById(int $id): ?array\n    {\n        $stmt = $this-&gt;db-&gt;prepare('SELECT * FROM users WHERE id = ?');\n        $stmt-&gt;execute([$id]);\n        return $stmt-&gt;fetch() ?: null;\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Eloquent\u306e\u7d71\u5408<\/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=\"\">&lt;?php\n\/\/ config\/database.php\nuse Illuminate\\Database\\Capsule\\Manager as Capsule;\n\n$capsule = new Capsule;\n$capsule-&gt;addConnection([\n    'driver'    =&gt; 'mysql',\n    'host'      =&gt; $_ENV['DB_HOST'],\n    'database'  =&gt; $_ENV['DB_NAME'],\n    'username'  =&gt; $_ENV['DB_USER'],\n    'password'  =&gt; $_ENV['DB_PASS'],\n    'charset'   =&gt; 'utf8mb4',\n    'collation' =&gt; 'utf8mb4_unicode_ci',\n    'prefix'    =&gt; '',\n]);\n\n$capsule-&gt;setAsGlobal();\n$capsule-&gt;bootEloquent();\n\n\/\/ src\/Models\/User.php\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass User extends Model\n{\n    protected $fillable = ['name', 'email'];\n\n    public function posts()\n    {\n        return $this-&gt;hasMany(Post::class);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">DI\u30b3\u30f3\u30c6\u30ca\u3092\u4f7f\u3063\u305f\u4f9d\u5b58\u6027\u306e\u7ba1\u7406<\/h3>\n\n\n\n<p>\u4f9d\u5b58\u6027\u6ce8\u5165\uff08DI\uff09\u30b3\u30f3\u30c6\u30ca\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30af\u30e9\u30b9\u306e\u4f9d\u5b58\u95a2\u4fc2\u3092\u52b9\u7387\u7684\u306b\u7ba1\u7406\u3057\u3001\u30c6\u30b9\u30bf\u30d3\u30ea\u30c6\u30a3\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=\"\">&lt;?php\n\/\/ config\/container.php\nuse DI\\ContainerBuilder;\nuse Psr\\Container\\ContainerInterface;\nuse App\\Services\\UserService;\nuse App\\Repositories\\UserRepository;\n\n$containerBuilder = new ContainerBuilder();\n$containerBuilder-&gt;addDefinitions([\n    UserService::class =&gt; function (ContainerInterface $c) {\n        return new UserService($c-&gt;get(UserRepository::class));\n    },\n\n    UserRepository::class =&gt; function (ContainerInterface $c) {\n        return new UserRepository($c-&gt;get(\\PDO::class));\n    },\n\n    \\PDO::class =&gt; function (ContainerInterface $c) {\n        return Database::getInstance()-&gt;getConnection();\n    }\n]);\n\n$container = $containerBuilder-&gt;build();\nAppFactory::setContainer($container);\n\n\/\/ \u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u306e\u4f8b\nclass UserService\n{\n    private $repository;\n\n    public function __construct(UserRepository $repository)\n    {\n        $this-&gt;repository = $repository;\n    }\n\n    public function createUser(array $data): User\n    {\n        \/\/ \u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        $this-&gt;validateUserData($data);\n\n        \/\/ \u30e6\u30fc\u30b6\u30fc\u4f5c\u6210\n        return $this-&gt;repository-&gt;create($data);\n    }\n\n    private function validateUserData(array $data): void\n    {\n        if (empty($data['email']) || !filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {\n            throw new \\InvalidArgumentException('\u6709\u52b9\u306a\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u304c\u5fc5\u8981\u3067\u3059');\n        }\n\n        if (empty($data['name']) || strlen($data['name']) &lt; 2) {\n            throw new \\InvalidArgumentException('\u540d\u524d\u306f2\u6587\u5b57\u4ee5\u4e0a\u5fc5\u8981\u3067\u3059');\n        }\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u30d1\u30bf\u30fc\u30f3\u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u4fdd\u5b88\u6027\u304c\u9ad8\u304f\u3001\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb\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\u3001\u3053\u308c\u3089\u306e\u5b9f\u88c5\u3092\u30d9\u30fc\u30b9\u306b\u3057\u305f\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0\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-11\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30c1\u30e5\u30fc\u30cb\u30f3\u30b0\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-12\">\u30ad\u30e3\u30c3\u30b7\u30e5\u6226\u7565\uff1a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u9ad8\u901f\u5316\u65b9\u6cd5<\/h3>\n\n\n\n<p>Slim Framework\u3067\u306f\u3001\u69d8\u3005\u306a\u30ec\u30d9\u30eb\u3067\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u5b9f\u88c5\u3067\u304d\u307e\u3059\u3002\u9069\u5207\u306a\u30ad\u30e3\u30c3\u30b7\u30e5\u6226\u7565\u3092\u63a1\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\u6642\u9593\u3092\u5927\u5e45\u306b\u6539\u5584\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30eb\u30fc\u30c8\u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Cache\/RouteCache.php\nnamespace App\\Cache;\n\nuse Psr\\SimpleCache\\CacheInterface;\nuse Slim\\Interfaces\\RouteCollectorProxyInterface;\n\nclass RouteCache\n{\n    private $cache;\n    private $ttl;\n\n    public function __construct(CacheInterface $cache, int $ttl = 3600)\n    {\n        $this-&gt;cache = $cache;\n        $this-&gt;ttl = $ttl;\n    }\n\n    public function cacheRoute($route, callable $handler)\n    {\n        return function ($request, $response, $args) use ($handler, $route) {\n            $cacheKey = \"route_\" . md5($route . json_encode($args));\n\n            \/\/ \u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u78ba\u8a8d\n            if ($cachedResponse = $this-&gt;cache-&gt;get($cacheKey)) {\n                return $response-&gt;withJson($cachedResponse);\n            }\n\n            \/\/ \u5b9f\u969b\u306e\u51e6\u7406\u3092\u5b9f\u884c\n            $result = $handler($request, $response, $args);\n\n            \/\/ \u7d50\u679c\u3092\u30ad\u30e3\u30c3\u30b7\u30e5\n            $this-&gt;cache-&gt;set($cacheKey, $result, $this-&gt;ttl);\n\n            return $response-&gt;withJson($result);\n        };\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Redis\u3092\u4f7f\u7528\u3057\u305f\u30ad\u30e3\u30c3\u30b7\u30e5\u30b7\u30b9\u30c6\u30e0<\/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=\"\">&lt;?php\n\/\/ config\/cache.php\nuse Redis;\n\n$redis = new Redis();\n$redis-&gt;connect('127.0.0.1', 6379);\n\n\/\/ \u30ad\u30e3\u30c3\u30b7\u30e5\u30af\u30e9\u30b9\u306e\u5b9f\u88c5\nclass RedisCache implements CacheInterface\n{\n    private $redis;\n\n    public function __construct(Redis $redis)\n    {\n        $this-&gt;redis = $redis;\n    }\n\n    public function get($key, $default = null)\n    {\n        $result = $this-&gt;redis-&gt;get($key);\n        return $result !== false ? json_decode($result, true) : $default;\n    }\n\n    public function set($key, $value, $ttl = null)\n    {\n        $this-&gt;redis-&gt;set($key, json_encode($value));\n        if ($ttl) {\n            $this-&gt;redis-&gt;expire($key, $ttl);\n        }\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u306e\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af<\/h3>\n\n\n\n<p>\u30e1\u30e2\u30ea\u306e\u52b9\u7387\u7684\u306a\u4f7f\u7528\u306f\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3\u306b\u76f4\u63a5\u5f71\u97ff\u3057\u307e\u3059\u3002\u4ee5\u4e0b\u306e\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af\u3092\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001\u30e1\u30e2\u30ea\u4f7f\u7528\u91cf\u3092\u524a\u6e1b\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30b8\u30a7\u30cd\u30ec\u30fc\u30bf\u3092\u4f7f\u7528\u3057\u305f\u5927\u91cf\u30c7\u30fc\u30bf\u306e\u51e6\u7406<\/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=\"\">&lt;?php\nclass UserExporter\n{\n    private $pdo;\n\n    public function exportUsers(): \\Generator\n    {\n        $stmt = $this-&gt;pdo-&gt;prepare('SELECT * FROM users');\n        $stmt-&gt;execute();\n\n        while ($row = $stmt-&gt;fetch()) {\n            yield $row;\n        }\n    }\n}\n\n\/\/ API\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u3067\u306e\u4f7f\u7528\u4f8b\n$app-&gt;get('\/api\/users\/export', function (Request $request, Response $response) {\n    $exporter = new UserExporter($this-&gt;get('pdo'));\n\n    $response = $response-&gt;withHeader('Content-Type', 'application\/json');\n    $stream = $response-&gt;getBody();\n\n    $stream-&gt;write('[');\n    $first = true;\n\n    foreach ($exporter-&gt;exportUsers() as $user) {\n        if (!$first) {\n            $stream-&gt;write(',');\n        }\n        $stream-&gt;write(json_encode($user));\n        $first = false;\n    }\n\n    $stream-&gt;write(']');\n    return $response;\n});<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30e1\u30e2\u30ea\u30ea\u30fc\u30af\u9632\u6b62\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/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=\"\">&lt;?php\nclass ResourceManager\n{\n    private $resources = [];\n\n    public function __destruct()\n    {\n        \/\/ \u30ea\u30bd\u30fc\u30b9\u306e\u660e\u793a\u7684\u306a\u89e3\u653e\n        foreach ($this-&gt;resources as $resource) {\n            if ($resource instanceof \\PDOStatement) {\n                $resource-&gt;closeCursor();\n            }\n        }\n        $this-&gt;resources = [];\n    }\n\n    public function addResource($resource)\n    {\n        $this-&gt;resources[] = $resource;\n    }\n}\n\n\/\/ \u5927\u304d\u306a\u914d\u5217\u306e\u51e6\u7406\nfunction processLargeArray(array $data)\n{\n    $chunk_size = 1000;\n    $chunks = array_chunk($data, $chunk_size);\n\n    foreach ($chunks as $chunk) {\n        \/\/ \u30c1\u30e3\u30f3\u30af\u5358\u4f4d\u3067\u51e6\u7406\n        processChunk($chunk);\n        \/\/ \u30e1\u30e2\u30ea\u306e\u89e3\u653e\n        unset($chunk);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-14\">\u672c\u756a\u74b0\u5883\u3067\u306e\u5b9f\u8df5\u7684\u306a\u30c7\u30d7\u30ed\u30a4\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u672c\u756a\u74b0\u5883\u3067\u306e\u30c7\u30d7\u30ed\u30a4\u306b\u306f\u3001\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3068\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306e\u4e21\u9762\u3067\u6ce8\u610f\u304c\u5fc5\u8981\u3067\u3059\u3002\u4ee5\u4e0b\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u3092\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3092\u304a\u52e7\u3081\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u672c\u756a\u74b0\u5883\u8a2d\u5b9a\u306e\u6700\u9069\u5316<\/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=\"\">&lt;?php\n\/\/ config\/production.php\nreturn [\n    'displayErrorDetails' =&gt; false,\n    'logErrors' =&gt; true,\n    'logErrorDetails' =&gt; true,\n    'logger' =&gt; [\n        'name' =&gt; 'slim-app',\n        'path' =&gt; __DIR__ . '\/..\/logs\/app.log',\n        'level' =&gt; \\Monolog\\Logger::WARNING,\n    ],\n    'db' =&gt; [\n        'connection_limit' =&gt; 100,\n        'timeout' =&gt; 5,\n        'persistent' =&gt; true,\n    ],\n    'cache' =&gt; [\n        'enabled' =&gt; true,\n        'ttl' =&gt; 3600,\n    ],\n];\n\n\/\/ \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u8a2d\u5b9a\u306e\u9069\u7528\n$settings = require __DIR__ . '\/config\/production.php';\n$app = AppFactory::create();\n$app-&gt;addRoutingMiddleware();\n$errorMiddleware = $app-&gt;addErrorMiddleware(\n    $settings['displayErrorDetails'],\n    $settings['logErrors'],\n    $settings['logErrorDetails']\n);<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>OPcache\u306e\u6700\u9069\u5316\u8a2d\u5b9a<\/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=\"\">; php.ini \u306e\u8a2d\u5b9a\u4f8b\nopcache.enable=1\nopcache.memory_consumption=128\nopcache.interned_strings_buffer=8\nopcache.max_accelerated_files=4000\nopcache.revalidate_freq=60\nopcache.fast_shutdown=1\nopcache.enable_cli=1<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30c7\u30d7\u30ed\u30a4\u30b9\u30af\u30ea\u30d7\u30c8\u306e\u4f8b<\/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=\"\">#!\/bin\/bash\n# deploy.sh\n\n# \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\nAPP_DIR=\"\/var\/www\/slim-app\"\n\n# \u4f9d\u5b58\u95a2\u4fc2\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\ncomposer install --no-dev --optimize-autoloader\n\n# \u30ad\u30e3\u30c3\u30b7\u30e5\u306e\u30af\u30ea\u30a2\nphp artisan cache:clear\nphp artisan config:cache\nphp artisan route:cache\n\n# OPcache\u306e\u30ea\u30bb\u30c3\u30c8\ncurl -X GET http:\/\/localhost\/opcache-reset.php\n\n# \u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3\u306e\u8a2d\u5b9a\nchown -R www-data:www-data $APP_DIR\/storage\nchmod -R 755 $APP_DIR\/storage\n\n# Nginx\u306e\u8a2d\u5b9a\u4f8b\nserver {\n    listen 80;\n    server_name example.com;\n    root \/var\/www\/slim-app\/public;\n\n    location \/ {\n        try_files $uri \/index.php$is_args$args;\n    }\n\n    location ~ \\.php$ {\n        fastcgi_pass unix:\/var\/run\/php\/php8.1-fpm.sock;\n        fastcgi_split_path_info ^(.+\\.php)(\/.*)$;\n        include fastcgi_params;\n        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;\n        fastcgi_param DOCUMENT_ROOT $realpath_root;\n        internal;\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af\u3092\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u9ad8\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3067\u5b89\u5b9a\u3057\u305f\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002\u6b21\u306e\u30bb\u30af\u30b7\u30e7\u30f3\u3067\u306f\u3001\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56\u3068\u904b\u7528\u306e\u30dd\u30a4\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-15\">\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56\u3068\u904b\u7528\u306e\u30dd\u30a4\u30f3\u30c8<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">\u4e00\u822c\u7684\u306a\u8106\u5f31\u6027\u5bfe\u7b56\u3068\u30b9\u30ea\u30e0\u56fa\u6709\u306e\u6ce8\u610f\u70b9<\/h3>\n\n\n\n<p>Slim Framework\u3067\u306f\u3001\u57fa\u672c\u7684\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56\u306b\u52a0\u3048\u3066\u3001\u30d5\u30ec\u30fc\u30e0\u30ef\u30fc\u30af\u7279\u6709\u306e\u6ce8\u610f\u70b9\u304c\u3042\u308a\u307e\u3059\u3002\u4ee5\u4e0b\u306e\u5b9f\u88c5\u4f8b\u3092\u53c2\u8003\u306b\u3001\u5805\u7262\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56\u3092\u5b9f\u73fe\u3057\u307e\u3057\u3087\u3046\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>XSS\u5bfe\u7b56\u306e\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Middleware\/SecurityHeadersMiddleware.php\nnamespace App\\Middleware;\n\nuse Psr\\Http\\Message\\ResponseInterface as Response;\nuse Psr\\Http\\Message\\ServerRequestInterface as Request;\nuse Psr\\Http\\Server\\MiddlewareInterface;\nuse Psr\\Http\\Server\\RequestHandlerInterface as RequestHandler;\n\nclass SecurityHeadersMiddleware implements MiddlewareInterface\n{\n    public function process(Request $request, RequestHandler $handler): Response\n    {\n        $response = $handler-&gt;handle($request);\n\n        return $response\n            -&gt;withHeader('X-Frame-Options', 'DENY')\n            -&gt;withHeader('X-Content-Type-Options', 'nosniff')\n            -&gt;withHeader('X-XSS-Protection', '1; mode=block')\n            -&gt;withHeader('Content-Security-Policy', \"default-src 'self'\");\n    }\n}\n\n\/\/ HTML\u30a8\u30b9\u30b1\u30fc\u30d7\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3\nclass HtmlPurifier\n{\n    public static function clean(string $input): string\n    {\n        return htmlspecialchars($input, ENT_QUOTES, 'UTF-8');\n    }\n\n    public static function cleanArray(array $input): array\n    {\n        return array_map([self::class, 'clean'], $input);\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>CSRF\u5bfe\u7b56\u306e\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Middleware\/CsrfMiddleware.php\nnamespace App\\Middleware;\n\nclass CsrfMiddleware implements MiddlewareInterface\n{\n    private $session;\n\n    public function __construct(SessionInterface $session)\n    {\n        $this-&gt;session = $session;\n    }\n\n    public function process(Request $request, RequestHandler $handler): Response\n    {\n        \/\/ GET\u30ea\u30af\u30a8\u30b9\u30c8\u306f\u30b9\u30ad\u30c3\u30d7\n        if ($request-&gt;getMethod() === 'GET') {\n            return $handler-&gt;handle($request);\n        }\n\n        $token = $request-&gt;getHeaderLine('X-CSRF-Token');\n        if (!$this-&gt;validateToken($token)) {\n            throw new HttpForbiddenException($request, 'Invalid CSRF token');\n        }\n\n        return $handler-&gt;handle($request);\n    }\n\n    private function validateToken(string $token): bool\n    {\n        $storedToken = $this-&gt;session-&gt;get('csrf_token');\n        return hash_equals($storedToken, $token);\n    }\n\n    public function generateToken(): string\n    {\n        $token = bin2hex(random_bytes(32));\n        $this-&gt;session-&gt;set('csrf_token', $token);\n        return $token;\n    }\n}\n\n\/\/ \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3067\u306e\u30c8\u30fc\u30af\u30f3\u51fa\u529b\n$app-&gt;get('\/form', function (Request $request, Response $response) {\n    $csrf = $this-&gt;get(CsrfMiddleware::class);\n    $token = $csrf-&gt;generateToken();\n\n    return $this-&gt;get('view')-&gt;render($response, 'form.php', [\n        'csrf_token' =&gt; $token\n    ]);\n});<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-17\">\u30ed\u30b0\u7ba1\u7406\u3068\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<p>\u52b9\u679c\u7684\u306a\u30ed\u30b0\u7ba1\u7406\u3068\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u306f\u3001\u554f\u984c\u306e\u65e9\u671f\u767a\u898b\u3068\u89e3\u6c7a\u306b\u4e0d\u53ef\u6b20\u3067\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u69cb\u9020\u5316\u30ed\u30b0\u306e\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Logger\/StructuredLogger.php\nnamespace App\\Logger;\n\nuse Monolog\\Logger;\nuse Monolog\\Handler\\StreamHandler;\nuse Monolog\\Formatter\\JsonFormatter;\n\nclass StructuredLogger\n{\n    private $logger;\n\n    public function __construct(string $name)\n    {\n        $this-&gt;logger = new Logger($name);\n\n        $handler = new StreamHandler(\n            __DIR__ . '\/..\/..\/logs\/app.log',\n            Logger::INFO\n        );\n        $handler-&gt;setFormatter(new JsonFormatter());\n\n        $this-&gt;logger-&gt;pushHandler($handler);\n    }\n\n    public function logRequest(Request $request, array $context = []): void\n    {\n        $this-&gt;logger-&gt;info('HTTP Request', [\n            'method' =&gt; $request-&gt;getMethod(),\n            'uri' =&gt; (string) $request-&gt;getUri(),\n            'headers' =&gt; $request-&gt;getHeaders(),\n            'ip' =&gt; $request-&gt;getServerParam('REMOTE_ADDR'),\n            'user_agent' =&gt; $request-&gt;getHeaderLine('User-Agent'),\n            ...$context\n        ]);\n    }\n\n    public function logError(\\Throwable $error, array $context = []): void\n    {\n        $this-&gt;logger-&gt;error($error-&gt;getMessage(), [\n            'file' =&gt; $error-&gt;getFile(),\n            'line' =&gt; $error-&gt;getLine(),\n            'trace' =&gt; $error-&gt;getTraceAsString(),\n            ...$context\n        ]);\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30ab\u30b9\u30bf\u30e0\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30e9\u306e\u5b9f\u88c5<\/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=\"\">&lt;?php\n\/\/ src\/Error\/CustomErrorHandler.php\nnamespace App\\Error;\n\nuse Psr\\Http\\Message\\ResponseInterface;\nuse Slim\\Exception\\HttpNotFoundException;\nuse Slim\\Interfaces\\ErrorHandlerInterface;\n\nclass CustomErrorHandler implements ErrorHandlerInterface\n{\n    private $logger;\n    private $displayErrors;\n\n    public function __construct(StructuredLogger $logger, bool $displayErrors = false)\n    {\n        $this-&gt;logger = $logger;\n        $this-&gt;displayErrors = $displayErrors;\n    }\n\n    public function __invoke(\n        Request $request,\n        Throwable $exception,\n        bool $displayErrorDetails,\n        bool $logErrors,\n        bool $logErrorDetails\n    ): ResponseInterface\n    {\n        \/\/ \u30a8\u30e9\u30fc\u306e\u30ed\u30b0\u8a18\u9332\n        $this-&gt;logger-&gt;logError($exception);\n\n        \/\/ \u30a8\u30e9\u30fc\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u751f\u6210\n        $payload = [\n            'error' =&gt; [\n                'message' =&gt; $this-&gt;displayErrors \n                    ? $exception-&gt;getMessage() \n                    : 'An error occurred',\n                'code' =&gt; 500\n            ]\n        ];\n\n        if ($exception instanceof HttpNotFoundException) {\n            $payload['error']['code'] = 404;\n        }\n\n        $response = new Response();\n        $response-&gt;getBody()-&gt;write(json_encode($payload));\n\n        return $response\n            -&gt;withStatus($payload['error']['code'])\n            -&gt;withHeader('Content-Type', 'application\/json');\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">\u30e6\u30cb\u30c3\u30c8\u30c6\u30b9\u30c8\u3068CI\u306e\u5c0e\u5165\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u81ea\u52d5\u30c6\u30b9\u30c8\u3068CI\/CD\u30d1\u30a4\u30d7\u30e9\u30a4\u30f3\u306e\u5c0e\u5165\u306b\u3088\u308a\u3001\u54c1\u8cea\u3092\u62c5\u4fdd\u3057\u306a\u304c\u3089\u7d99\u7d9a\u7684\u306a\u30c7\u30d7\u30ed\u30a4\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30e6\u30cb\u30c3\u30c8\u30c6\u30b9\u30c8\u306e\u5b9f\u88c5\u4f8b<\/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=\"\">&lt;?php\n\/\/ tests\/Controllers\/UserControllerTest.php\nnamespace Tests\\Controllers;\n\nuse PHPUnit\\Framework\\TestCase;\nuse App\\Controllers\\UserController;\n\nclass UserControllerTest extends TestCase\n{\n    private $controller;\n    private $mockRepository;\n\n    protected function setUp(): void\n    {\n        $this-&gt;mockRepository = $this-&gt;createMock(UserRepository::class);\n        $this-&gt;controller = new UserController($this-&gt;mockRepository);\n    }\n\n    public function testGetUsers()\n    {\n        $expectedUsers = [\n            ['id' =&gt; 1, 'name' =&gt; 'Test User']\n        ];\n\n        $this-&gt;mockRepository\n            -&gt;expects($this-&gt;once())\n            -&gt;method('findAll')\n            -&gt;willReturn($expectedUsers);\n\n        $request = $this-&gt;createMock(Request::class);\n        $response = $this-&gt;createMock(Response::class);\n\n        $result = $this-&gt;controller-&gt;getUsers($request, $response);\n\n        $this-&gt;assertInstanceOf(Response::class, $result);\n        \/\/ \u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u5185\u5bb9\u3092\u691c\u8a3c\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>GitHub Actions\u3092\u4f7f\u7528\u3057\u305fCI\u8a2d\u5b9a<\/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=\"\"># .github\/workflows\/ci.yml\nname: CI\n\non:\n  push:\n    branches: [ main ]\n  pull_request:\n    branches: [ main ]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions\/checkout@v2\n\n    - name: Setup PHP\n      uses: shivammathur\/setup-php@v2\n      with:\n        php-version: '8.1'\n        extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, dom, filter, gd, json, xmlwriter\n        coverage: xdebug\n\n    - name: Validate composer.json and composer.lock\n      run: composer validate\n\n    - name: Install dependencies\n      run: composer install --prefer-dist --no-progress --no-suggest\n\n    - name: Run test suite\n      run: composer run-script test\n\n    - name: Run PHP CS Fixer\n      run: composer run-script cs-fix\n\n    - name: Run PHPStan\n      run: composer run-script analyse<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u306b\u3088\u308a\u3001\u30bb\u30ad\u30e5\u30a2\u3067\u4fdd\u5b88\u6027\u306e\u9ad8\u3044\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u7d99\u7d9a\u7684\u306b\u904b\u7528\u3067\u304d\u307e\u3059\u3002\u7279\u306b\u672c\u756a\u74b0\u5883\u3067\u306f\u3001\u5b9a\u671f\u7684\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3068\u30ed\u30b0\u306e\u76e3\u8996\u3092\u5fd8\u308c\u305a\u306b\u884c\u3044\u307e\u3057\u3087\u3046\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-2476","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\/2476","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=2476"}],"version-history":[{"count":2,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2476\/revisions"}],"predecessor-version":[{"id":2478,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2476\/revisions\/2478"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2476"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2476"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2476"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}