{"id":2623,"date":"2025-03-24T08:46:55","date_gmt":"2025-03-23T23:46:55","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=2623"},"modified":"2025-03-24T08:47:23","modified_gmt":"2025-03-23T23:47:23","slug":"laravel-jetstream%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9a%e5%b0%8e%e5%85%a5%e3%81%8b%e3%82%89%e5%ae%9f%e8%b7%b5%e3%81%be%e3%81%a7%e8%a7%a3%e8%aa%ac%e3%81%99%e3%82%8b7%e3%81%a4%e3%81%ae","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=2623","title":{"rendered":"Laravel Jetstream\u5b8c\u5168\u30ac\u30a4\u30c9\uff1a\u5c0e\u5165\u304b\u3089\u5b9f\u8df5\u307e\u3067\u89e3\u8aac\u3059\u308b7\u3064\u306e\u91cd\u8981\u30dd\u30a4\u30f3\u30c8\u30102024\u5e74\u7248\u3011"},"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\">Laravel Jetstream \u3068\u306f\uff1f\u57fa\u790e\u304b\u3089\u7406\u89e3\u3059\u308b\u7279\u5fb4\u3068\u6a5f\u80fd<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">\u30b9\u30bf\u30fc\u30bf\u30fc\u30ad\u30c3\u30c8\u3068\u3057\u3066\u306eJetstream\u306e\u4f4d\u7f6e\u3065\u3051<\/a>      <\/li>      <li>        <a href=\"#i-2\">Breeze\u3068Fortify\u3068\u306e\u5fb9\u5e95\u6bd4\u8f03<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-3\">\u4e3b\u8981\u6a5f\u80fd\u306e\u8a73\u7d30\u4e00\u89a7<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-4\">Jetstream\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3068\u521d\u671f\u8a2d\u5b9a<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-5\">\u52d5\u4f5c\u74b0\u5883\u306e\u78ba\u8a8d\u3068\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806<\/a>      <\/li>      <li>        <a href=\"#i-6\">Livewire \u3068 Inertia \u306e\u9078\u629e\u57fa\u6e96\u3068\u7279\u5fb4<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-7\">\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u30dd\u30a4\u30f3\u30c8<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-8\">\u8a8d\u8a3c\u6a5f\u80fd\u306e\u5b9f\u88c5\u3068\u62e1\u5f35\u65b9\u6cd5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-9\">\u4e8c\u8981\u7d20\u8a8d\u8a3c\u306e\u8a2d\u5b9a\u3068\u5b9f\u88c5\u624b\u9806<\/a>      <\/li>      <li>        <a href=\"#i-10\">\u30e1\u30fc\u30eb\u78ba\u8a8d\u6a5f\u80fd\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-11\">\u30bd\u30fc\u30b7\u30e3\u30eb\u30ed\u30b0\u30a4\u30f3\u306e\u8ffd\u52a0\u5b9f\u88c5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-12\">\u30c1\u30fc\u30e0\u7ba1\u7406\u6a5f\u80fd\u306e\u6d3b\u7528\u8853<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-13\">\u30c1\u30fc\u30e0\u4f5c\u6210\u3068\u30ed\u30fc\u30eb\u7ba1\u7406\u306e\u57fa\u672c\u8a2d\u5b9a<\/a>      <\/li>      <li>        <a href=\"#i-14\">\u30dd\u30ea\u30b7\u30fc\u3068\u30c1\u30fc\u30e0\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-15\">\u30c1\u30fc\u30e0\u62db\u5f85\u6a5f\u80fd\u306e\u5b9f\u88c5\u4f8b<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-16\">UI\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-17\">Tailwind CSS\u3092\u6d3b\u7528\u3057\u305f\u30c7\u30b6\u30a4\u30f3\u8abf\u6574<\/a>      <\/li>      <li>        <a href=\"#i-18\">\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-19\">\u30ec\u30b9\u30dd\u30f3\u30b7\u30d6\u30c7\u30b6\u30a4\u30f3\u306e\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-20\">Jetstream\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-21\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u30d6\u30e9\u30a6\u30b6\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u5236\u5fa1<\/a>      <\/li>      <li>        <a href=\"#i-22\">API\u8a8d\u8a3c\u7ba1\u7406\u306e\u5b9f\u88c5\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-23\">\u30af\u30ed\u30b9\u30b5\u30a4\u30c8\u30ea\u30af\u30a8\u30b9\u30c8\u30d5\u30a9\u30fc\u30b8\u30a7\u30ea\u5bfe\u7b56<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-24\">\u5b9f\u969b\u306e\u904b\u7528\u3067\u306e\u6ce8\u610f\u70b9\u3068\u30c8\u30e9\u30d6\u30eb\u5bfe\u51e6<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-25\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>      <\/li>      <li>        <a href=\"#i-26\">\u3088\u304f\u3042\u308b\u30a8\u30e9\u30fc\u3068\u305d\u306e\u89e3\u6c7a\u65b9\u6cd5<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-27\">\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u6642\u306e\u4e92\u63db\u6027\u78ba\u8a8d\u30dd\u30a4\u30f3\u30c8<\/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\">Laravel Jetstream \u3068\u306f\uff1f\u57fa\u790e\u304b\u3089\u7406\u89e3\u3059\u308b\u7279\u5fb4\u3068\u6a5f\u80fd<\/h2>\n\n\n\n<p>Laravel Jetstream\u306f\u3001Laravel\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u3068\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30b9\u30bf\u30fc\u30bf\u30fc\u30ad\u30c3\u30c8\u3092\u63d0\u4f9b\u3059\u308b\u516c\u5f0f\u30d1\u30c3\u30b1\u30fc\u30b8\u3067\u3059\u30022020\u5e749\u6708\u306b\u30ea\u30ea\u30fc\u30b9\u3055\u308c\u3066\u4ee5\u6765\u3001\u30e2\u30c0\u30f3\u306aWeb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u958b\u767a\u306b\u5fc5\u8981\u306a\u57fa\u672c\u6a5f\u80fd\u3092\u52b9\u7387\u7684\u306b\u5b9f\u88c5\u3067\u304d\u308b\u5f37\u529b\u306a\u30c4\u30fc\u30eb\u3068\u3057\u3066\u5e83\u304f\u63a1\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">\u30b9\u30bf\u30fc\u30bf\u30fc\u30ad\u30c3\u30c8\u3068\u3057\u3066\u306eJetstream\u306e\u4f4d\u7f6e\u3065\u3051<\/h3>\n\n\n\n<p>Jetstream\u306f\u5358\u306a\u308b\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u3067\u306f\u306a\u304f\u3001\u4ee5\u4e0b\u306e\u6a5f\u80fd\u3092\u7d71\u5408\u3057\u305f\u5305\u62ec\u7684\u306a\u30b9\u30bf\u30fc\u30bf\u30fc\u30ad\u30c3\u30c8\u3068\u3057\u3066\u4f4d\u7f6e\u3065\u3051\u3089\u308c\u3066\u3044\u307e\u3059\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u57fa\u76e4<\/strong><\/li>\n\n\n\n<li>\u30ed\u30b0\u30a4\u30f3\/\u767b\u9332\u6a5f\u80fd<\/li>\n\n\n\n<li>\u30d1\u30b9\u30ef\u30fc\u30c9\u30ea\u30bb\u30c3\u30c8<\/li>\n\n\n\n<li>\u30e1\u30fc\u30eb\u78ba\u8a8d\u6a5f\u80fd<\/li>\n\n\n\n<li>\u4e8c\u8981\u7d20\u8a8d\u8a3c\uff082FA\uff09<\/li>\n\n\n\n<li><strong>\u30e2\u30c0\u30f3\u306a\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u69cb\u6210<\/strong><\/li>\n\n\n\n<li>Livewire\u307e\u305f\u306fInertia.js\u306e\u9078\u629e<\/li>\n\n\n\n<li>TailwindCSS\u306b\u3088\u308b\u6d17\u7df4\u3055\u308c\u305fUI\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8<\/li>\n\n\n\n<li>Alpine.js\u306b\u3088\u308b\u30a4\u30f3\u30bf\u30e9\u30af\u30c6\u30a3\u30d6\u306a\u6a5f\u80fd<\/li>\n\n\n\n<li><strong>\u30c1\u30fc\u30e0\u7ba1\u7406\u6a5f\u80fd<\/strong><\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u306e\u4f5c\u6210\u3068\u7ba1\u7406<\/li>\n\n\n\n<li>\u30ed\u30fc\u30eb\u30d9\u30fc\u30b9\u306e\u6a29\u9650\u7ba1\u7406<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u30e1\u30f3\u30d0\u30fc\u306e\u62db\u5f85\u30b7\u30b9\u30c6\u30e0<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">Breeze\u3068Fortify\u3068\u306e\u5fb9\u5e95\u6bd4\u8f03<\/h3>\n\n\n\n<p>Laravel\u306e\u30b9\u30bf\u30fc\u30bf\u30fc\u30ad\u30c3\u30c8\u306b\u306fJetstream\u4ee5\u5916\u306b\u3082Breeze\u3068Fortify\u304c\u3042\u308a\u307e\u3059\u304c\u3001\u305d\u308c\u305e\u308c\u306b\u7279\u5fb4\u304c\u3042\u308a\u307e\u3059\uff1a<\/p>\n\n\n<div id=\"id-5440d37b-ed34-41cb-b948-5c2cc71ddaa3\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6a5f\u80fd<\/th><th>Jetstream<\/th><th>Breeze<\/th><th>Fortify<\/th><\/tr><\/thead><tbody><tr><td>\u8a8d\u8a3c\u57fa\u76e4<\/td><td>\u2705<\/td><td>\u2705<\/td><td>\u2705<\/td><\/tr><tr><td>2FA\u5bfe\u5fdc<\/td><td>\u2705<\/td><td>\u274c<\/td><td>\u2705<\/td><\/tr><tr><td>\u30c1\u30fc\u30e0\u7ba1\u7406<\/td><td>\u2705<\/td><td>\u274c<\/td><td>\u274c<\/td><\/tr><tr><td>API\u5bfe\u5fdc<\/td><td>\u2705<\/td><td>\u30aa\u30d7\u30b7\u30e7\u30f3<\/td><td>\u2705<\/td><\/tr><tr><td>\u5b66\u7fd2\u66f2\u7dda<\/td><td>\u9ad8\u3081<\/td><td>\u4f4e\u3081<\/td><td>\u4e2d\u7a0b\u5ea6<\/td><\/tr><tr><td>\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u6027<\/td><td>\u9ad8\u3044<\/td><td>\u9ad8\u3044<\/td><td>\u975e\u5e38\u306b\u9ad8\u3044<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"i-3\">\u4e3b\u8981\u6a5f\u80fd\u306e\u8a73\u7d30\u4e00\u89a7<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u8a8d\u8a3c\u6a5f\u80fd<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u8a8d\u8a3c<\/li>\n\n\n\n<li>\u30c8\u30fc\u30af\u30f3\u30d9\u30fc\u30b9\u306eAPI\u8a8d\u8a3c<\/li>\n\n\n\n<li>\u4e8c\u8981\u7d20\u8a8d\u8a3c\uff08Google Authenticator\u5bfe\u5fdc\uff09<\/li>\n\n\n\n<li>\u30d6\u30e9\u30a6\u30b6\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7ba1\u7406<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u60c5\u5831\u306e\u66f4\u65b0<\/li>\n\n\n\n<li>\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u5199\u771f\u306e\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9<\/li>\n\n\n\n<li>\u30d1\u30b9\u30ef\u30fc\u30c9\u5909\u66f4<\/li>\n\n\n\n<li>\u4e8c\u8981\u7d20\u8a8d\u8a3c\u306e\u6709\u52b9\u5316\/\u7121\u52b9\u5316<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30c1\u30fc\u30e0\u6a5f\u80fd<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c1\u30fc\u30e0\u306e\u4f5c\u6210\u3068\u7ba1\u7406<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u30e1\u30f3\u30d0\u30fc\u306e\u62db\u5f85<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u8a2d\u5b9a\u306e\u7ba1\u7406<\/li>\n\n\n\n<li>\u30ed\u30fc\u30eb\u3068\u30d1\u30fc\u30df\u30c3\u30b7\u30e7\u30f3\u306e\u8a2d\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u6a5f\u80fd<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>CSRF\u4fdd\u8b77<\/li>\n\n\n\n<li>XSS\u5bfe\u7b56<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u56fa\u5b9a\u653b\u6483\u5bfe\u7b56<\/li>\n\n\n\n<li>\u30ec\u30fc\u30c8\u5236\u9650<\/li>\n<\/ul>\n\n\n\n<p>Jetstream\u306f\u3001\u3053\u308c\u3089\u306e\u6a5f\u80fd\u3092\u7d71\u5408\u7684\u306b\u63d0\u4f9b\u3059\u308b\u3053\u3068\u3067\u3001\u958b\u767a\u8005\u304c\u672c\u8cea\u7684\u306a\u30d3\u30b8\u30cd\u30b9\u30ed\u30b8\u30c3\u30af\u306e\u5b9f\u88c5\u306b\u96c6\u4e2d\u3067\u304d\u308b\u74b0\u5883\u3092\u6574\u3048\u3066\u3044\u307e\u3059\u3002\u7279\u306b\u3001\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3084\u30e6\u30fc\u30b6\u30fc\u7ba1\u7406\u306b\u95a2\u3059\u308b\u6a19\u6e96\u7684\u306a\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\u304c\u7d44\u307f\u8fbc\u307e\u308c\u3066\u3044\u308b\u305f\u3081\u3001\u5b89\u5168\u3067\u4fe1\u983c\u6027\u306e\u9ad8\u3044\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u7d20\u65e9\u304f\u69cb\u7bc9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-4\">Jetstream\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3068\u521d\u671f\u8a2d\u5b9a<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">\u52d5\u4f5c\u74b0\u5883\u306e\u78ba\u8a8d\u3068\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806<\/h3>\n\n\n\n<p>Jetstream\u3092\u5c0e\u5165\u3059\u308b\u524d\u306b\u3001\u4ee5\u4e0b\u306e\u8981\u4ef6\u3092\u6e80\u305f\u3057\u3066\u3044\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\uff1a<\/p>\n\n\n\n<p><strong>\u5fc5\u8981\u8981\u4ef6\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP 8.1\u4ee5\u4e0a<\/li>\n\n\n\n<li>Laravel 10.x\u4ee5\u4e0a<\/li>\n\n\n\n<li>Node.js 16\u4ee5\u4e0a<\/li>\n\n\n\n<li>Composer\u306e\u6700\u65b0\u7248<\/li>\n<\/ul>\n\n\n\n<p>\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u624b\u9806\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\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=\"\"># \u65b0\u3057\u3044Laravel\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4f5c\u6210\ncomposer create-project laravel\/laravel example-app\n\n# \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3078\u79fb\u52d5\ncd example-app\n\n# Jetstream\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\ncomposer require laravel\/jetstream\n\n# Livewire\u30b9\u30bf\u30c3\u30af\u3067\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\nphp artisan jetstream:install livewire\n\n# \u307e\u305f\u306f\u3001Inertia\u30b9\u30bf\u30c3\u30af\u3067\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\nphp artisan jetstream:install inertia<\/pre>\n\n\n\n<p>\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u5f8c\u306e\u8ffd\u52a0\u624b\u9806\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=\"\"># \u4f9d\u5b58\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\nnpm install\n\n# \u30a2\u30bb\u30c3\u30c8\u306e\u30d3\u30eb\u30c9\nnpm run build\n\n# \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\nphp artisan migrate<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">Livewire \u3068 Inertia \u306e\u9078\u629e\u57fa\u6e96\u3068\u7279\u5fb4<\/h3>\n\n\n\n<p>Jetstream\u3067\u306f\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u30b9\u30bf\u30c3\u30af\u3068\u3057\u3066Livewire\u3068Inertia.js\u306e2\u3064\u306e\u9078\u629e\u80a2\u304c\u7528\u610f\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>Livewire\u3092\u9078\u3076\u3079\u304d\u5834\u5408\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP\u4e2d\u5fc3\u306e\u958b\u767a\u3092\u884c\u3044\u305f\u3044\u5834\u5408<\/li>\n\n\n\n<li>JavaScript\u306e\u77e5\u8b58\u304c\u9650\u3089\u308c\u3066\u3044\u308b\u30c1\u30fc\u30e0<\/li>\n\n\n\n<li>\u30b7\u30f3\u30d7\u30eb\u306a\u30a4\u30f3\u30bf\u30e9\u30af\u30b7\u30e7\u30f3\u3067\u5341\u5206\u306a\u5834\u5408<\/li>\n\n\n\n<li>\u30b5\u30fc\u30d0\u30fc\u30b5\u30a4\u30c9\u30ec\u30f3\u30c0\u30ea\u30f3\u30b0\u3092\u91cd\u8996\u3059\u308b\u5834\u5408<\/li>\n<\/ul>\n\n\n\n<p><strong>Inertia.js\u3092\u9078\u3076\u3079\u304d\u5834\u5408\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30e2\u30c0\u30f3\u306aSPA\u4f53\u9a13\u3092\u63d0\u4f9b\u3057\u305f\u3044\u5834\u5408<\/li>\n\n\n\n<li>Vue.js\u306e\u77e5\u8b58\u304c\u3042\u308b\u30c1\u30fc\u30e0<\/li>\n\n\n\n<li>\u8907\u96d1\u306a\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u6a5f\u80fd\u304c\u5fc5\u8981\u306a\u5834\u5408<\/li>\n\n\n\n<li>\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b5\u30a4\u30c9\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u91cd\u8996\u3059\u308b\u5834\u5408<\/li>\n<\/ul>\n\n\n<div id=\"id-535f438f-e519-4c17-8f2f-3663afbaacd0\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u6a5f\u80fd\u6bd4\u8f03<\/th><th>Livewire<\/th><th>Inertia.js<\/th><\/tr><\/thead><tbody><tr><td>\u5b66\u7fd2\u66f2\u7dda<\/td><td>\u7de9\u3084\u304b<\/td><td>\u3084\u3084\u6025<\/td><\/tr><tr><td>PHP\u4f9d\u5b58\u5ea6<\/td><td>\u9ad8\u3044<\/td><td>\u4f4e\u3044<\/td><\/tr><tr><td>JS\u4f9d\u5b58\u5ea6<\/td><td>\u4f4e\u3044<\/td><td>\u9ad8\u3044<\/td><\/tr><tr><td>\u958b\u767a\u901f\u5ea6<\/td><td>\u901f\u3044<\/td><td>\u4e2d\u7a0b\u5ea6<\/td><\/tr><tr><td>\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u6027<\/td><td>\u4e2d\u7a0b\u5ea6<\/td><td>\u9ad8\u3044<\/td><\/tr><tr><td>SEO\u5bfe\u5fdc<\/td><td>\u5bb9\u6613<\/td><td>\u8981\u5bfe\u7b56<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"i-7\">\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u30dd\u30a4\u30f3\u30c8<\/h3>\n\n\n\n<p>Jetstream\u306e\u8a2d\u5b9a\u306f<code>config\/jetstream.php<\/code>\u3067\u7ba1\u7406\u3055\u308c\u307e\u3059\u3002\u4e3b\u8981\u306a\u8a2d\u5b9a\u9805\u76ee\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\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=\"\">return [\n    \/\/ Jetstream\u306e\u30b9\u30bf\u30c3\u30af\u9078\u629e\uff08livewire or inertia\uff09\n    'stack' =&gt; 'livewire',\n\n    \/\/ \u6709\u52b9\u306b\u3059\u308b\u6a5f\u80fd\u306e\u9078\u629e\n    'features' =&gt; [\n        Features::profilePhotos(),      \/\/ \u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u5199\u771f\n        Features::api(),                \/\/ API\u6a5f\u80fd\n        Features::teams(),              \/\/ \u30c1\u30fc\u30e0\u6a5f\u80fd\n        Features::accountDeletion(),    \/\/ \u30a2\u30ab\u30a6\u30f3\u30c8\u524a\u9664\n    ],\n\n    \/\/ \u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u5199\u771f\u306e\u30c7\u30a3\u30b9\u30af\u8a2d\u5b9a\n    'profile_photo_disk' =&gt; 'public',\n];<\/pre>\n\n\n\n<p>\u91cd\u8981\u306a\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\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=\"\">   \/\/ app\/Http\/Kernel.php\n   protected $middlewareGroups = [\n       'web' =&gt; [\n           \/\/ Jetstream\u306e\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\n           \\Laravel\\Jetstream\\Http\\Middleware\\AuthenticateSession::class,\n       ],\n   ];<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u8a8d\u8a3c\u30ac\u30fc\u30c9\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=\"\">   \/\/ config\/auth.php\n   'guards' =&gt; [\n       'web' =&gt; [\n           'driver' =&gt; 'session',\n           'provider' =&gt; 'users',\n       ],\n       'api' =&gt; [\n           'driver' =&gt; 'sanctum',\n           'provider' =&gt; 'users',\n       ],\n   ];<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30e1\u30fc\u30eb\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=\"\">   \/\/ .env\n   MAIL_MAILER=smtp\n   MAIL_HOST=mailhog\n   MAIL_PORT=1025\n   MAIL_USERNAME=null\n   MAIL_PASSWORD=null\n   MAIL_ENCRYPTION=null\n   MAIL_FROM_ADDRESS=\"hello@example.com\"<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u8a2d\u5b9a\u3092\u9069\u5207\u306b\u884c\u3046\u3053\u3068\u3067\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8981\u4ef6\u306b\u5408\u308f\u305b\u305fJetstream\u306e\u74b0\u5883\u3092\u69cb\u7bc9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u8a2d\u5b9a\u5909\u66f4\u5f8c\u306f\u5fc5\u305a\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u30af\u30ea\u30a2\u3059\u308b\u3053\u3068\u3092\u63a8\u5968\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=\"\">php artisan config:clear\nphp artisan cache:clear\nphp artisan view:clear<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-8\">\u8a8d\u8a3c\u6a5f\u80fd\u306e\u5b9f\u88c5\u3068\u62e1\u5f35\u65b9\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u4e8c\u8981\u7d20\u8a8d\u8a3c\u306e\u8a2d\u5b9a\u3068\u5b9f\u88c5\u624b\u9806<\/h3>\n\n\n\n<p>Jetstream\u306e\u4e8c\u8981\u7d20\u8a8d\u8a3c\uff082FA\uff09\u306f\u3001Google Authenticator\u306a\u3069\u306e\u8a8d\u8a3c\u30a2\u30d7\u30ea\u306b\u5bfe\u5fdc\u3057\u3066\u3044\u307e\u3059\u3002\u5b9f\u88c5\u624b\u9806\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>2FA\u6a5f\u80fd\u306e\u6709\u52b9\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=\"\">\/\/ config\/jetstream.php\n'features' =&gt; [\n    Features::twoFactorAuthentication([\n        'confirm' =&gt; true,      \/\/ \u78ba\u8a8d\u3092\u5fc5\u9808\u306b\u3059\u308b\n        'confirmPassword' =&gt; true  \/\/ \u30d1\u30b9\u30ef\u30fc\u30c9\u78ba\u8a8d\u3092\u8981\u6c42\n    ]),\n],<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u306e\u8ffd\u52a0<\/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=\"\">\/\/ app\/Actions\/Fortify\/TwoFactorAuthenticationController.php\nuse Laravel\\Fortify\\Actions\\ConfirmTwoFactorAuthentication;\n\nclass CustomTwoFactorAuthenticationController extends ConfirmTwoFactorAuthentication\n{\n    public function __invoke(Request $request)\n    {\n        \/\/ \u30ab\u30b9\u30bf\u30e0\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        $validated = $request-&gt;validate([\n            'code' =&gt; 'required|string|size:6',\n        ]);\n\n        \/\/ \u8a8d\u8a3c\u51e6\u7406\n        if (! $request-&gt;user()-&gt;confirmTwoFactorAuthentication($validated['code'])) {\n            throw ValidationException::withMessages([\n                'code' =&gt; [__('The provided two factor authentication code was invalid.')],\n            ]);\n        }\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">\u30e1\u30fc\u30eb\u78ba\u8a8d\u6a5f\u80fd\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u30e1\u30fc\u30eb\u78ba\u8a8d\u6a5f\u80fd\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3067\u304d\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30ab\u30b9\u30bf\u30e0\u30e1\u30fc\u30eb\u901a\u77e5\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=\"\">\/\/ app\/Notifications\/CustomVerifyEmail.php\nuse Illuminate\\Auth\\Notifications\\VerifyEmail;\n\nclass CustomVerifyEmail extends VerifyEmail\n{\n    public function toMail($notifiable)\n    {\n        $verificationUrl = $this-&gt;verificationUrl($notifiable);\n\n        return (new MailMessage)\n            -&gt;subject('\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306e\u78ba\u8a8d')\n            -&gt;markdown('emails.verify-email', [\n                'url' =&gt; $verificationUrl,\n                'user' =&gt; $notifiable\n            ]);\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u78ba\u8a8d\u30e1\u30fc\u30eb\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\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=\"\">&lt;!-- resources\/views\/emails\/verify-email.blade.php --&gt;\n@component('mail::message')\n# \u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306e\u78ba\u8a8d\n\n\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u5316\u3059\u308b\u306b\u306f\u4ee5\u4e0b\u306e\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002\n\n@component('mail::button', ['url' =&gt; $url])\n\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3092\u78ba\u8a8d\n@endcomponent\n\n@endcomponent<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u78ba\u8a8d\u30ed\u30b8\u30c3\u30af\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/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=\"\">\/\/ app\/Models\/User.php\nuse App\\Notifications\\CustomVerifyEmail;\n\nclass User extends Authenticatable implements MustVerifyEmail\n{\n    public function sendEmailVerificationNotification()\n    {\n        $this-&gt;notify(new CustomVerifyEmail);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-11\">\u30bd\u30fc\u30b7\u30e3\u30eb\u30ed\u30b0\u30a4\u30f3\u306e\u8ffd\u52a0\u5b9f\u88c5<\/h3>\n\n\n\n<p>Jetstream\u306b\u30bd\u30fc\u30b7\u30e3\u30eb\u30ed\u30b0\u30a4\u30f3\u3092\u8ffd\u52a0\u3059\u308b\u624b\u9806\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Laravel Socialite\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=\"\">composer require laravel\/socialite<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u8ffd\u52a0<\/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=\"\">\/\/ config\/services.php\nreturn [\n    'github' =&gt; [\n        'client_id' =&gt; env('GITHUB_CLIENT_ID'),\n        'client_secret' =&gt; env('GITHUB_CLIENT_SECRET'),\n        'redirect' =&gt; env('GITHUB_CALLBACK_URL'),\n    ],\n    'google' =&gt; [\n        'client_id' =&gt; env('GOOGLE_CLIENT_ID'),\n        'client_secret' =&gt; env('GOOGLE_CLIENT_SECRET'),\n        'redirect' =&gt; env('GOOGLE_CALLBACK_URL'),\n    ],\n];<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30eb\u30fc\u30c8\u306e\u8ffd\u52a0<\/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=\"\">\/\/ routes\/web.php\nuse Laravel\\Socialite\\Facades\\Socialite;\n\nRoute::get('\/auth\/{provider}', function ($provider) {\n    return Socialite::driver($provider)-&gt;redirect();\n})-&gt;name('social.login');\n\nRoute::get('\/auth\/{provider}\/callback', function ($provider) {\n    $user = Socialite::driver($provider)-&gt;user();\n\n    \/\/ \u30e6\u30fc\u30b6\u30fc\u53d6\u5f97\u307e\u305f\u306f\u4f5c\u6210\n    $authUser = User::updateOrCreate([\n        'email' =&gt; $user-&gt;email,\n    ], [\n        'name' =&gt; $user-&gt;name,\n        'password' =&gt; Hash::make(Str::random(24)),\n    ]);\n\n    Auth::login($authUser);\n\n    return redirect('\/dashboard');\n})-&gt;name('social.callback');<\/pre>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li><strong>\u30ed\u30b0\u30a4\u30f3\u30d5\u30a9\u30fc\u30e0\u306e\u4fee\u6b63<\/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;!-- resources\/views\/auth\/login.blade.php --&gt;\n&lt;div class=\"social-auth-links text-center mt-4\"&gt;\n    &lt;a href=\"{{ route('social.login', 'github') }}\" class=\"btn btn-block btn-github\"&gt;\n        &lt;i class=\"fab fa-github\"&gt;&lt;\/i&gt; GitHub\u3067\u30ed\u30b0\u30a4\u30f3\n    &lt;\/a&gt;\n    &lt;a href=\"{{ route('social.login', 'google') }}\" class=\"btn btn-block btn-google\"&gt;\n        &lt;i class=\"fab fa-google\"&gt;&lt;\/i&gt; Google\u3067\u30ed\u30b0\u30a4\u30f3\n    &lt;\/a&gt;\n&lt;\/div&gt;<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u306b\u3088\u308a\u3001\u30bb\u30ad\u30e5\u30a2\u3067\u67d4\u8edf\u306a\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u3092\u69cb\u7bc9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u5b9f\u88c5\u6642\u306f\u4ee5\u4e0b\u306e\u70b9\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u4e8c\u8981\u7d20\u8a8d\u8a3c\u306e\u6709\u52b9\u5316\u306f\u6bb5\u968e\u7684\u306b\u884c\u3046<\/li>\n\n\n\n<li>\u30e1\u30fc\u30eb\u78ba\u8a8d\u306e\u518d\u9001\u4fe1\u5236\u9650\u3092\u9069\u5207\u306b\u8a2d\u5b9a\u3059\u308b<\/li>\n\n\n\n<li>\u30bd\u30fc\u30b7\u30e3\u30eb\u30ed\u30b0\u30a4\u30f3\u6642\u306e\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u3092\u4e01\u5be7\u306b\u5b9f\u88c5\u3059\u308b<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u30c8\u30fc\u30af\u30f3\u306e\u6709\u52b9\u671f\u9650\u3092\u9069\u5207\u306b\u8a2d\u5b9a\u3059\u308b<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-12\">\u30c1\u30fc\u30e0\u7ba1\u7406\u6a5f\u80fd\u306e\u6d3b\u7528\u8853<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">\u30c1\u30fc\u30e0\u4f5c\u6210\u3068\u30ed\u30fc\u30eb\u7ba1\u7406\u306e\u57fa\u672c\u8a2d\u5b9a<\/h3>\n\n\n\n<p>Jetstream\u306e\u30c1\u30fc\u30e0\u6a5f\u80fd\u306f\u3001\u8907\u6570\u30e6\u30fc\u30b6\u30fc\u3067\u5171\u540c\u4f5c\u696d\u3092\u884c\u3046\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u6700\u9069\u306a\u6a5f\u80fd\u3092\u63d0\u4f9b\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30c1\u30fc\u30e0\u6a5f\u80fd\u306e\u6709\u52b9\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=\"\">\/\/ config\/jetstream.php\nreturn [\n    'features' =&gt; [\n        Features::teams(['invitations' =&gt; true]),\n    ],\n];<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u57fa\u672c\u7684\u306a\u30ed\u30fc\u30eb\u306e\u5b9a\u7fa9<\/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=\"\">\/\/ app\/Providers\/JetstreamServiceProvider.php\nuse Laravel\\Jetstream\\Jetstream;\n\npublic function boot(): void\n{\n    $this-&gt;configurePermissions();\n}\n\nprotected function configurePermissions(): void\n{\n    Jetstream::defaultApiTokenPermissions(['read']);\n\n    Jetstream::role('admin', 'Administrator', [\n        'create',\n        'read',\n        'update',\n        'delete',\n        'manage-team',\n    ]);\n\n    Jetstream::role('editor', 'Editor', [\n        'create',\n        'read',\n        'update',\n    ]);\n\n    Jetstream::role('viewer', 'Viewer', [\n        'read',\n    ]);\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-14\">\u30dd\u30ea\u30b7\u30fc\u3068\u30c1\u30fc\u30e0\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u30c1\u30fc\u30e0\u306b\u95a2\u9023\u3059\u308b\u30dd\u30ea\u30b7\u30fc\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3067\u304d\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30c1\u30fc\u30e0\u30dd\u30ea\u30b7\u30fc\u306e\u62e1\u5f35<\/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=\"\">\/\/ app\/Policies\/TeamPolicy.php\nclass TeamPolicy extends Policy\n{\n    public function create(User $user): bool\n    {\n        \/\/ \u30d7\u30e9\u30f3\u306b\u57fa\u3065\u3044\u3066\u30c1\u30fc\u30e0\u4f5c\u6210\u3092\u5236\u9650\n        return $user-&gt;subscription?-&gt;canCreateTeams() ?? false;\n    }\n\n    public function addTeamMember(User $user, Team $team): bool\n    {\n        \/\/ \u30c1\u30fc\u30e0\u30e1\u30f3\u30d0\u30fc\u6570\u306e\u5236\u9650\n        return $team-&gt;users()-&gt;count() &lt; 10;\n    }\n\n    public function updateTeamMember(User $user, Team $team, User $teamMember): bool\n    {\n        return $user-&gt;hasTeamPermission($team, 'manage-team');\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30c1\u30fc\u30e0\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\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=\"\">\/\/ app\/Http\/Middleware\/EnsureTeamRole.php\nclass EnsureTeamRole\n{\n    public function handle($request, Closure $next, string $role)\n    {\n        $team = $request-&gt;user()-&gt;currentTeam;\n\n        if (! $team || ! $request-&gt;user()-&gt;hasTeamRole($team, $role)) {\n            abort(403, '\u5fc5\u8981\u306a\u6a29\u9650\u304c\u3042\u308a\u307e\u305b\u3093\u3002');\n        }\n\n        return $next($request);\n    }\n}\n\n\/\/ app\/Http\/Kernel.php\nprotected $routeMiddleware = [\n    'team.role' =&gt; \\App\\Http\\Middleware\\EnsureTeamRole::class,\n];<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-15\">\u30c1\u30fc\u30e0\u62db\u5f85\u6a5f\u80fd\u306e\u5b9f\u88c5\u4f8b<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30ab\u30b9\u30bf\u30e0\u62db\u5f85\u30e1\u30fc\u30eb\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=\"\">\/\/ app\/Notifications\/CustomTeamInvitation.php\nclass CustomTeamInvitation extends TeamInvitation\n{\n    public function toMail($notifiable): MailMessage\n    {\n        return (new MailMessage)\n            -&gt;subject('\u30c1\u30fc\u30e0\u3078\u306e\u62db\u5f85')\n            -&gt;markdown('mail.team.invitation', [\n                'invitation' =&gt; $this-&gt;invitation,\n                'team' =&gt; $this-&gt;team,\n            ]);\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u62db\u5f85\u51e6\u7406\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/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=\"\">\/\/ app\/Actions\/Jetstream\/InviteTeamMember.php\nclass InviteTeamMember implements InviteTeamMemberContract\n{\n    public function invite(User $user, Team $team, string $email, string $role = null): void\n    {\n        \/\/ \u62db\u5f85\u524d\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\n        Gate::forUser($user)-&gt;authorize('addTeamMember', $team);\n\n        $this-&gt;validateMaximumTeamMembers($team);\n\n        \/\/ \u62db\u5f85\u306e\u4f5c\u6210\n        $invitation = $team-&gt;teamInvitations()-&gt;create([\n            'email' =&gt; $email,\n            'role' =&gt; $role,\n            'expires_at' =&gt; now()-&gt;addDays(7),\n        ]);\n\n        \/\/ \u30ab\u30b9\u30bf\u30e0\u901a\u77e5\u306e\u9001\u4fe1\n        Notification::route('mail', $email)\n            -&gt;notify(new CustomTeamInvitation($invitation));\n    }\n\n    protected function validateMaximumTeamMembers(Team $team): void\n    {\n        $count = $team-&gt;allUsers()-&gt;count();\n        $max = config('jetstream.max_team_members', 5);\n\n        if ($count &gt;= $max) {\n            throw ValidationException::withMessages([\n                'email' =&gt; ['\u30c1\u30fc\u30e0\u30e1\u30f3\u30d0\u30fc\u306e\u4e0a\u9650\u306b\u9054\u3057\u3066\u3044\u307e\u3059\u3002'],\n            ]);\n        }\n    }\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u62db\u5f85\u53d7\u8afe\u51e6\u7406\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/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=\"\">\/\/ routes\/web.php\nRoute::get('\/team-invitations\/{invitation}', function (TeamInvitation $invitation) {\n    if (! auth()-&gt;check()) {\n        auth()-&gt;login($invitation-&gt;team-&gt;owner);\n    }\n\n    if (Gate::check('acceptTeamInvitation', $invitation)) {\n        $invitation-&gt;team-&gt;users()-&gt;attach(auth()-&gt;id(), ['role' =&gt; $invitation-&gt;role]);\n\n        $invitation-&gt;delete();\n\n        return redirect(config('fortify.home'))-&gt;banner(\n            '\u62db\u5f85\u3092\u53d7\u8afe\u3057\u307e\u3057\u305f\u3002'\n        );\n    }\n\n    return abort(403);\n})-&gt;middleware(['signed']);<\/pre>\n\n\n\n<p>\u5b9f\u88c5\u6642\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u8003\u616e\u4e8b\u9805<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u62db\u5f85\u30ea\u30f3\u30af\u306e\u6709\u52b9\u671f\u9650\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30c1\u30fc\u30e0\u30e1\u30f3\u30d0\u30fc\u6570\u306e\u4e0a\u9650\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30ed\u30fc\u30eb\u306b\u57fa\u3065\u304f\u30a2\u30af\u30bb\u30b9\u5236\u5fa1<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30c1\u30fc\u30e0\u95a2\u9023\u306e\u30af\u30a8\u30ea\u306e\u30ad\u30e3\u30c3\u30b7\u30e5<\/li>\n\n\n\n<li>N+1\u554f\u984c\u306e\u56de\u907f<\/li>\n\n\n\n<li>\u975e\u540c\u671f\u51e6\u7406\u306e\u6d3b\u7528<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>UX\u5411\u4e0a\u306e\u305f\u3081\u306eTips<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u62db\u5f85\u72b6\u614b\u306e\u53ef\u8996\u5316<\/li>\n\n\n\n<li>\u308f\u304b\u308a\u3084\u3059\u3044\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8<\/li>\n\n\n\n<li>\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u901a\u77e5\u306e\u5b9f\u88c5<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-16\">UI\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-17\">Tailwind CSS\u3092\u6d3b\u7528\u3057\u305f\u30c7\u30b6\u30a4\u30f3\u8abf\u6574<\/h3>\n\n\n\n<p>Jetstream\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u30c7\u30b6\u30a4\u30f3\u306f\u512a\u308c\u3066\u3044\u307e\u3059\u304c\u3001\u591a\u304f\u306e\u5834\u5408\u3001\u4f01\u696d\u72ec\u81ea\u306e\u30d6\u30e9\u30f3\u30c9\u30ab\u30e9\u30fc\u3084\u30c7\u30b6\u30a4\u30f3\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\u306b\u5408\u308f\u305b\u305f\u8abf\u6574\u304c\u5fc5\u8981\u3068\u306a\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>1. \u30ab\u30e9\u30fc\u30d1\u30ec\u30c3\u30c8\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/strong><\/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=\"\">\/\/ tailwind.config.js\nmodule.exports = {\n    theme: {\n        extend: {\n            colors: {\n                brand: {\n                    50: '#f2f8ff',\n                    100: '#e6f1ff',\n                    200: '#bfdaff',\n                    300: '#99c3ff',\n                    400: '#4d94ff',\n                    500: '#0066ff',  \/\/ \u30d7\u30e9\u30a4\u30de\u30ea\u30fc\u30ab\u30e9\u30fc\n                    600: '#005ce6',\n                    700: '#004db3',\n                    800: '#003d8c',\n                    900: '#003166',\n                },\n            },\n        },\n    },\n}<\/pre>\n\n\n\n<p><strong>\u5b9f\u88c5\u4f8b\uff1a\u30ab\u30b9\u30bf\u30e0\u30dc\u30bf\u30f3\u306e\u4f5c\u6210<\/strong><\/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;!-- resources\/views\/components\/custom-button.blade.php --&gt;\n@props([\n    'type' =&gt; 'button',\n    'variant' =&gt; 'primary',\n])\n\n@php\n$baseClasses = 'inline-flex items-center px-4 py-2 border rounded-md font-semibold text-xs uppercase tracking-widest focus:outline-none focus:ring-2 focus:ring-offset-2 transition ease-in-out duration-150';\n$variants = [\n    'primary' =&gt; 'border-transparent bg-brand-500 text-white hover:bg-brand-600 focus:bg-brand-600 active:bg-brand-600 focus:ring-brand-400',\n    'secondary' =&gt; 'border-gray-300 bg-white text-gray-700 hover:text-gray-900 hover:bg-gray-50 focus:ring-brand-400',\n    'danger' =&gt; 'border-transparent bg-red-500 text-white hover:bg-red-600 focus:ring-red-400',\n];\n@endphp\n\n&lt;button\n    type=\"{{ $type }}\"\n    {{ $attributes-&gt;merge(['class' =&gt; $baseClasses . ' ' . $variants[$variant]]) }}\n&gt;\n    {{ $slot }}\n&lt;\/button&gt;<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\u65b9\u6cd5<\/h3>\n\n\n\n<p>Jetstream\u306e\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b\u969b\u306f\u3001\u6bb5\u968e\u7684\u306a\u30a2\u30d7\u30ed\u30fc\u30c1\u3092\u53d6\u308b\u3053\u3068\u304c\u91cd\u8981\u3067\u3059\u3002<\/p>\n\n\n\n<p><strong>1. \u30d7\u30ed\u30d5\u30a3\u30fc\u30eb\u30ab\u30fc\u30c9\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u4f8b<\/strong><\/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=\"\">\/\/ app\/View\/Components\/CustomProfileCard.php\nclass CustomProfileCard extends Component\n{\n    public $user;\n    public $team;\n\n    public function __construct($user, $team = null)\n    {\n        $this-&gt;user = $user;\n        $this-&gt;team = $team;\n    }\n\n    public function render()\n    {\n        return view('components.custom-profile-card', [\n            'roles' =&gt; $this-&gt;team ? $this-&gt;user-&gt;roles-&gt;where('team_id', $this-&gt;team-&gt;id) : collect(),\n            'lastActive' =&gt; $this-&gt;getLastActiveTime(),\n        ]);\n    }\n\n    private function getLastActiveTime()\n    {\n        return Cache::get('user-last-active-' . $this-&gt;user-&gt;id);\n    }\n}<\/pre>\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;!-- resources\/views\/components\/custom-profile-card.blade.php --&gt;\n&lt;div class=\"bg-white rounded-lg shadow\"&gt;\n    &lt;div class=\"p-6\"&gt;\n        &lt;div class=\"flex items-center\"&gt;\n            &lt;div class=\"flex-shrink-0 h-20 w-20\"&gt;\n                &lt;img class=\"h-20 w-20 rounded-full object-cover\" src=\"{{ $user-&gt;profile_photo_url }}\" alt=\"{{ $user-&gt;name }}\"&gt;\n            &lt;\/div&gt;\n            &lt;div class=\"ml-6\"&gt;\n                &lt;h3 class=\"text-2xl font-semibold text-gray-900\"&gt;\n                    {{ $user-&gt;name }}\n                &lt;\/h3&gt;\n                &lt;p class=\"text-sm text-gray-500\"&gt;\n                    {{ $user-&gt;email }}\n                &lt;\/p&gt;\n                @if($lastActive)\n                    &lt;p class=\"text-xs text-gray-400 mt-1\"&gt;\n                        \u6700\u7d42\u30a2\u30af\u30c6\u30a3\u30d6: {{ $lastActive-&gt;diffForHumans() }}\n                    &lt;\/p&gt;\n                @endif\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n        @if($team &amp;&amp; $roles-&gt;isNotEmpty())\n            &lt;div class=\"mt-4 border-t pt-4\"&gt;\n                &lt;h4 class=\"text-sm font-medium text-gray-500\"&gt;\u30c1\u30fc\u30e0\u3067\u306e\u5f79\u5272&lt;\/h4&gt;\n                &lt;div class=\"mt-2 flex flex-wrap gap-2\"&gt;\n                    @foreach($roles as $role)\n                        &lt;span class=\"inline-flex items-center px-3 py-0.5 rounded-full text-sm font-medium bg-brand-100 text-brand-800\"&gt;\n                            {{ $role-&gt;name }}\n                        &lt;\/span&gt;\n                    @endforeach\n                &lt;\/div&gt;\n            &lt;\/div&gt;\n        @endif\n    &lt;\/div&gt;\n&lt;\/div&gt;<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-19\">\u30ec\u30b9\u30dd\u30f3\u30b7\u30d6\u30c7\u30b6\u30a4\u30f3\u306e\u6700\u9069\u5316\u30c6\u30af\u30cb\u30c3\u30af<\/h3>\n\n\n\n<p>\u30e2\u30d0\u30a4\u30eb\u30d5\u30a1\u30fc\u30b9\u30c8\u306e\u30a2\u30d7\u30ed\u30fc\u30c1\u3092\u63a1\u7528\u3057\u3001\u6bb5\u968e\u7684\u306b\u6a5f\u80fd\u3092\u62e1\u5f35\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>1. \u30c0\u30c3\u30b7\u30e5\u30dc\u30fc\u30c9\u30ec\u30a4\u30a2\u30a6\u30c8\u306e\u6700\u9069\u5316<\/strong><\/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;!-- resources\/views\/layouts\/dashboard.blade.php --&gt;\n&lt;div class=\"min-h-screen bg-gray-100\"&gt;\n    &lt;div class=\"flex flex-col md:flex-row\"&gt;\n        &lt;!-- \u30b5\u30a4\u30c9\u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\uff08\u30e2\u30d0\u30a4\u30eb\u3067\u306f\u975e\u8868\u793a\uff09 --&gt;\n        &lt;div class=\"hidden md:flex md:w-64 md:flex-col md:fixed md:inset-y-0\"&gt;\n            &lt;nav class=\"flex-1 px-2 py-4 bg-white border-r border-gray-200\"&gt;\n                &lt;!-- \u30ca\u30d3\u30b2\u30fc\u30b7\u30e7\u30f3\u9805\u76ee --&gt;\n            &lt;\/nav&gt;\n        &lt;\/div&gt;\n\n        &lt;!-- \u30e1\u30a4\u30f3\u30b3\u30f3\u30c6\u30f3\u30c4 --&gt;\n        &lt;div class=\"flex-1 md:ml-64\"&gt;\n            &lt;!-- \u30e2\u30d0\u30a4\u30eb\u7528\u30d8\u30c3\u30c0\u30fc --&gt;\n            &lt;div class=\"sticky top-0 z-10 md:hidden\"&gt;\n                &lt;header class=\"px-4 py-2 bg-white shadow\"&gt;\n                    &lt;div class=\"flex items-center justify-between\"&gt;\n                        &lt;button type=\"button\" @click=\"sidebarOpen = true\" class=\"text-gray-500 hover:text-gray-600\"&gt;\n                            &lt;span class=\"sr-only\"&gt;\u30e1\u30cb\u30e5\u30fc\u3092\u958b\u304f&lt;\/span&gt;\n                            &lt;svg class=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\"&gt;\n                                &lt;path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 6h16M4 12h16M4 18h16\" \/&gt;\n                            &lt;\/svg&gt;\n                        &lt;\/button&gt;\n                    &lt;\/div&gt;\n                &lt;\/header&gt;\n            &lt;\/div&gt;\n\n            &lt;!-- \u30b3\u30f3\u30c6\u30f3\u30c4\u30a8\u30ea\u30a2 --&gt;\n            &lt;main class=\"py-6\"&gt;\n                &lt;div class=\"mx-auto max-w-7xl px-4 sm:px-6 md:px-8\"&gt;\n                    {{ $slot }}\n                &lt;\/div&gt;\n            &lt;\/main&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;<\/pre>\n\n\n\n<p><strong>\u5b9f\u88c5\u306e\u30dd\u30a4\u30f3\u30c8<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u9045\u5ef6\u8aad\u307f\u8fbc\u307f<\/li>\n\n\n\n<li>\u753b\u50cf\u306e\u6700\u9069\u5316<\/li>\n\n\n\n<li>CSS\u306e\u6700\u5c0f\u5316<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30a2\u30af\u30bb\u30b7\u30d3\u30ea\u30c6\u30a3\u5bfe\u5fdc<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9069\u5207\u306a\u898b\u51fa\u3057\u69cb\u9020<\/li>\n\n\n\n<li>\u30d5\u30a9\u30fc\u30ab\u30b9\u53ef\u80fd\u306a\u8981\u7d20\u306e\u8996\u899a\u7684\u30d5\u30a3\u30fc\u30c9\u30d0\u30c3\u30af<\/li>\n\n\n\n<li>\u30ad\u30fc\u30dc\u30fc\u30c9\u64cd\u4f5c\u306e\u30b5\u30dd\u30fc\u30c8<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u4fdd\u5b88\u6027\u306e\u5411\u4e0a<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5171\u901a\u30b9\u30bf\u30a4\u30eb\u306e\u5909\u6570\u5316<\/li>\n\n\n\n<li>\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8\u306e\u7c92\u5ea6\u306e\u9069\u5207\u306a\u8a2d\u8a08<\/li>\n\n\n\n<li>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u6574\u5099<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u306b\u3088\u308a\u3001Jetstream\u306e\u30c7\u30d5\u30a9\u30eb\u30c8\u30c7\u30b6\u30a4\u30f3\u3092\u57fa\u76e4\u3068\u3057\u306a\u304c\u3089\u3001\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u56fa\u6709\u306e\u8981\u4ef6\u306b\u5bfe\u5fdc\u3057\u305f\u9b45\u529b\u7684\u306aUI\u3092\u69cb\u7bc9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-20\">Jetstream\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-21\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u30d6\u30e9\u30a6\u30b6\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u5236\u5fa1<\/h3>\n\n\n\n<p>Jetstream\u306b\u306f\u9ad8\u5ea6\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u6a5f\u80fd\u304c\u7d44\u307f\u8fbc\u307e\u308c\u3066\u3044\u307e\u3059\u304c\u3001\u3055\u3089\u306a\u308b\u5f37\u5316\u304c\u53ef\u80fd\u3067\u3059\u3002<\/p>\n\n\n\n<p><strong>1. \u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u5f37\u5316<\/strong><\/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=\"\">\/\/ config\/session.php\nreturn [\n    'lifetime' =&gt; env('SESSION_LIFETIME', 120),     \/\/ \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\uff08\u5206\uff09\n    'expire_on_close' =&gt; true,                      \/\/ \u30d6\u30e9\u30a6\u30b6\u3092\u9589\u3058\u305f\u6642\u306b\u671f\u9650\u5207\u308c\n    'encrypt' =&gt; true,                              \/\/ \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6697\u53f7\u5316\n    'same_site' =&gt; 'lax',                          \/\/ SameSite\u5c5e\u6027\u306e\u8a2d\u5b9a\n];<\/pre>\n\n\n\n<p><strong>2. \u30a2\u30af\u30c6\u30a3\u30d6\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u7ba1\u7406\u5b9f\u88c5<\/strong><\/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=\"\">\/\/ app\/Http\/Controllers\/ActiveSessionController.php\nclass ActiveSessionController extends Controller\n{\n    public function index(Request $request)\n    {\n        return view('security.active-sessions', [\n            'sessions' =&gt; collect($request-&gt;session()-&gt;all())\n                -&gt;map(function ($value, $key) use ($request) {\n                    return [\n                        'agent' =&gt; $request-&gt;header('User-Agent'),\n                        'ip' =&gt; $request-&gt;ip(),\n                        'last_active' =&gt; now(),\n                    ];\n                }),\n        ]);\n    }\n\n    public function destroy(Request $request, $sessionId)\n    {\n        if ($sessionId !== $request-&gt;session()-&gt;getId()) {\n            \/\/ \u4ed6\u306e\u30c7\u30d0\u30a4\u30b9\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u524a\u9664\n            Session::getHandler()-&gt;destroy($sessionId);\n        }\n\n        return back(303);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-22\">API\u8a8d\u8a3c\u7ba1\u7406\u306e\u5b9f\u88c5\u65b9\u6cd5<\/h3>\n\n\n\n<p>Sanctum\u3092\u4f7f\u7528\u3057\u305fAPI\u8a8d\u8a3c\u306e\u5b89\u5168\u306a\u5b9f\u88c5\u65b9\u6cd5\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>1. API\u30c8\u30fc\u30af\u30f3\u8a2d\u5b9a\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/strong><\/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=\"\">\/\/ app\/Providers\/JetstreamServiceProvider.php\nuse Laravel\\Jetstream\\Jetstream;\n\npublic function boot()\n{\n    Jetstream::defaultApiTokenPermissions(['read']);\n\n    Jetstream::permissions([\n        'read',\n        'create',\n        'update',\n        'delete',\n        'admin',\n    ]);\n\n    \/\/ \u30c8\u30fc\u30af\u30f3\u306e\u6709\u52b9\u671f\u9650\u8a2d\u5b9a\n    Sanctum::refreshTokens(function ($token, $user) {\n        return $token-&gt;created_at-&gt;addDays(7);\n    });\n}<\/pre>\n\n\n\n<p><strong>2. \u30bb\u30ad\u30e5\u30a2\u306aAPI\u30eb\u30fc\u30c8\u306e\u5b9a\u7fa9<\/strong><\/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=\"\">\/\/ routes\/api.php\nRoute::middleware(['auth:sanctum', 'verified'])-&gt;group(function () {\n    Route::get('\/user\/profile', function (Request $request) {\n        \/\/ \u30ec\u30fc\u30c8\u5236\u9650\u306e\u9069\u7528\n        return Cache::remember('user.'.$request-&gt;user()-&gt;id.'.profile', 60, function () use ($request) {\n            return $request-&gt;user()-&gt;load('profile');\n        });\n    })-&gt;middleware(['throttle:api']);\n\n    \/\/ \u6a29\u9650\u306b\u57fa\u3065\u304f\u30eb\u30fc\u30c8\u5236\u9650\n    Route::middleware(['ability:admin'])-&gt;group(function () {\n        Route::post('\/admin\/users', [AdminController::class, 'store']);\n    });\n});<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-23\">\u30af\u30ed\u30b9\u30b5\u30a4\u30c8\u30ea\u30af\u30a8\u30b9\u30c8\u30d5\u30a9\u30fc\u30b8\u30a7\u30ea\u5bfe\u7b56<\/h3>\n\n\n\n<p>CSRF\u5bfe\u7b56\u3092\u5f37\u5316\u3059\u308b\u5b9f\u88c5\u4f8b\u3092\u793a\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>1. CSRF\u30df\u30c9\u30eb\u30a6\u30a7\u30a2\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/strong><\/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=\"\">\/\/ app\/Http\/Middleware\/CustomVerifyCsrfToken.php\nuse Illuminate\\Foundation\\Http\\Middleware\\VerifyCsrfToken;\n\nclass CustomVerifyCsrfToken extends VerifyCsrfToken\n{\n    protected $except = [\n        \/\/ CSRF\u4fdd\u8b77\u304b\u3089\u9664\u5916\u3059\u308bURL\n        'stripe\/*',\n        'webhook\/*',\n    ];\n\n    protected function tokensMatch($request)\n    {\n        $token = $request-&gt;input('_token') ?: $request-&gt;header('X-CSRF-TOKEN');\n\n        if (!$token &amp;&amp; $header = $request-&gt;header('X-XSRF-TOKEN')) {\n            $token = Crypt::decrypt($header, static::serialized());\n        }\n\n        \/\/ \u30c8\u30fc\u30af\u30f3\u306e\u691c\u8a3c\u5f37\u5316\n        if (!is_string($token)) {\n            return false;\n        }\n\n        $sessionToken = $request-&gt;session()-&gt;token();\n\n        return hash_equals(\n            $sessionToken,\n            $token\n        );\n    }\n}<\/pre>\n\n\n\n<p><strong>2. \u30bb\u30ad\u30e5\u30a2\u306a\u30d5\u30a9\u30fc\u30e0\u5b9f\u88c5<\/strong><\/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;!-- resources\/views\/forms\/secure-form.blade.php --&gt;\n&lt;form method=\"POST\" action=\"{{ route('secure.action') }}\" \n      x-data=\"{ submitting: false }\"\n      @submit.prevent=\"if(!submitting) { submitting = true; $event.target.submit(); }\"&gt;\n    @csrf\n\n    &lt;!-- \u30ef\u30f3\u30bf\u30a4\u30e0\u30c8\u30fc\u30af\u30f3\u306e\u751f\u6210 --&gt;\n    &lt;input type=\"hidden\" name=\"one_time_token\" value=\"{{ Str::random(40) }}\"&gt;\n\n    &lt;!-- \u4e8c\u91cd\u9001\u4fe1\u9632\u6b62 --&gt;\n    &lt;x-button :disabled=\"submitting\"&gt;\n        &lt;span x-show=\"!submitting\"&gt;\u9001\u4fe1&lt;\/span&gt;\n        &lt;span x-show=\"submitting\"&gt;\u51e6\u7406\u4e2d...&lt;\/span&gt;\n    &lt;\/x-button&gt;\n&lt;\/form&gt;<\/pre>\n\n\n\n<p><strong>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5f37\u5316\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u5165\u529b\u5024\u306e\u30d0\u30ea\u30c7\u30fc\u30b7\u30e7\u30f3\u5f37\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=\"\">\/\/ app\/Http\/Requests\/SecureFormRequest.php\nclass SecureFormRequest extends FormRequest\n{\n    public function rules()\n    {\n        return [\n            'email' =&gt; ['required', 'email', 'max:255', 'regex:\/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$\/'],\n            'password' =&gt; [\n                'required',\n                'string',\n                'min:12',\n                'regex:\/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&amp;])[A-Za-z\\d@$!%*?&amp;]{12,}$\/',\n            ],\n            'one_time_token' =&gt; ['required', 'string', 'size:40'],\n        ];\n    }\n\n    public function messages()\n    {\n        return [\n            'password.regex' =&gt; '\u30d1\u30b9\u30ef\u30fc\u30c9\u306f\u5927\u6587\u5b57\u3001\u5c0f\u6587\u5b57\u3001\u6570\u5b57\u3001\u7279\u6b8a\u6587\u5b57\u3092\u542b\u3080\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002',\n        ];\n    }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>\u30ed\u30b0\u30a4\u30f3\u8a66\u884c\u306e\u5236\u9650<\/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=\"\">\/\/ app\/Http\/Controllers\/Auth\/CustomLoginController.php\nuse Illuminate\\Cache\\RateLimiter;\n\nclass CustomLoginController extends Controller\n{\n    protected function attemptLogin(Request $request)\n    {\n        $limiter = app(RateLimiter::class);\n        $key = 'login.'.$request-&gt;ip();\n\n        if ($limiter-&gt;tooManyAttempts($key, 5)) {\n            $seconds = $limiter-&gt;availableIn($key);\n            throw ValidationException::withMessages([\n                'email' =&gt; [__('auth.throttle', ['seconds' =&gt; $seconds])],\n            ]);\n        }\n\n        if (Auth::attempt($request-&gt;only('email', 'password'))) {\n            $limiter-&gt;clear($key);\n            return true;\n        }\n\n        $limiter-&gt;hit($key, 60);\n        return false;\n    }\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30d8\u30c3\u30c0\u30fc\u306e\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=\"\">\/\/ app\/Http\/Middleware\/SecurityHeaders.php\nclass SecurityHeaders\n{\n    public function handle($request, Closure $next)\n    {\n        $response = $next($request);\n\n        $response-&gt;headers-&gt;set('X-Frame-Options', 'SAMEORIGIN');\n        $response-&gt;headers-&gt;set('X-XSS-Protection', '1; mode=block');\n        $response-&gt;headers-&gt;set('X-Content-Type-Options', 'nosniff');\n        $response-&gt;headers-&gt;set('Referrer-Policy', 'strict-origin-when-cross-origin');\n        $response-&gt;headers-&gt;set('Content-Security-Policy', \"default-src 'self'\");\n        $response-&gt;headers-&gt;set('Permissions-Policy', 'geolocation=()');\n\n        return $response;\n    }\n}<\/pre>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u306b\u3088\u308a\u3001Jetstream\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3092\u5927\u5e45\u306b\u5f37\u5316\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u305f\u3060\u3057\u3001\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306f\u7d99\u7d9a\u7684\u306a\u53d6\u308a\u7d44\u307f\u304c\u5fc5\u8981\u306a\u5206\u91ce\u3067\u3042\u308a\u3001\u5b9a\u671f\u7684\u306a\u898b\u76f4\u3057\u3068\u66f4\u65b0\u304c\u91cd\u8981\u3067\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-24\">\u5b9f\u969b\u306e\u904b\u7528\u3067\u306e\u6ce8\u610f\u70b9\u3068\u30c8\u30e9\u30d6\u30eb\u5bfe\u51e6<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-25\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h3>\n\n\n\n<p>Jetstream\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u6700\u9069\u5316\u3059\u308b\u305f\u3081\u306e\u4e3b\u8981\u306a\u30dd\u30a4\u30f3\u30c8\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p><strong>1. \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30af\u30a8\u30ea\u306e\u6700\u9069\u5316<\/strong><\/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=\"\">\/\/ app\/Models\/Team.php\nclass Team extends JetstreamTeam\n{\n    public function members()\n    {\n        \/\/ N+1\u554f\u984c\u3092\u9632\u3050\u305f\u3081\u306eEager Loading\n        return $this-&gt;users()\n            -&gt;with(['profile', 'permissions'])\n            -&gt;withCount(['activities' =&gt; function ($query) {\n                $query-&gt;where('created_at', '&gt;=', now()-&gt;subDays(30));\n            }]);\n    }\n\n    \/\/ \u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u6d3b\u7528\u3057\u305f\u30e1\u30f3\u30d0\u30fc\u6570\u306e\u53d6\u5f97\n    public function getMemberCountAttribute()\n    {\n        $cacheKey = \"team_{$this-&gt;id}_member_count\";\n\n        return Cache::remember($cacheKey, now()-&gt;addHours(1), function () {\n            return $this-&gt;users()-&gt;count();\n        });\n    }\n}<\/pre>\n\n\n\n<p><strong>2. \u30ad\u30e3\u30c3\u30b7\u30e5\u6226\u7565\u306e\u5b9f\u88c5<\/strong><\/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=\"\">\/\/ app\/Providers\/AppServiceProvider.php\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        \/\/ \u30b0\u30ed\u30fc\u30d0\u30eb\u30ad\u30e3\u30c3\u30b7\u30e5\u8a2d\u5b9a\n        if (config('app.env') === 'production') {\n            View::cache();\n            Route::cache();\n        }\n\n        \/\/ \u30e2\u30c7\u30eb\u30a4\u30d9\u30f3\u30c8\u3067\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u30af\u30ea\u30a2\n        Team::updated(function ($team) {\n            Cache::tags(['team_' . $team-&gt;id])-&gt;flush();\n        });\n    }\n}\n\n\/\/ app\/Http\/Controllers\/TeamDashboardController.php\nclass TeamDashboardController extends Controller\n{\n    public function show(Team $team)\n    {\n        $cacheKey = \"team_dashboard_{$team-&gt;id}\";\n\n        $dashboardData = Cache::tags(['team_' . $team-&gt;id])-&gt;remember(\n            $cacheKey,\n            now()-&gt;addMinutes(15),\n            function () use ($team) {\n                return [\n                    'members' =&gt; $team-&gt;members()-&gt;paginate(10),\n                    'activities' =&gt; $team-&gt;recentActivities(),\n                    'statistics' =&gt; $this-&gt;calculateTeamStatistics($team),\n                ];\n            }\n        );\n\n        return view('teams.dashboard', $dashboardData);\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-26\">\u3088\u304f\u3042\u308b\u30a8\u30e9\u30fc\u3068\u305d\u306e\u89e3\u6c7a\u65b9\u6cd5<\/h3>\n\n\n\n<p><strong>1. \u8a8d\u8a3c\u95a2\u9023\u306e\u30c8\u30e9\u30d6\u30eb\u5bfe\u51e6<\/strong><\/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=\"\">\/\/ app\/Exceptions\/Handler.php\nclass Handler extends ExceptionHandler\n{\n    public function register()\n    {\n        $this-&gt;renderable(function (AuthenticationException $e, $request) {\n            if ($request-&gt;expectsJson()) {\n                return response()-&gt;json([\n                    'error' =&gt; 'Unauthenticated.',\n                    'message' =&gt; '\u8a8d\u8a3c\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u5207\u308c\u307e\u3057\u305f\u3002\u518d\u5ea6\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u304f\u3060\u3055\u3044\u3002'\n                ], 401);\n            }\n        });\n\n        \/\/ \u30bb\u30c3\u30b7\u30e7\u30f3\u5207\u308c\u306e\u691c\u51fa\u3068\u51e6\u7406\n        $this-&gt;renderable(function (TokenMismatchException $e, $request) {\n            return redirect()-&gt;route('login')\n                -&gt;withErrors(['session' =&gt; '\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u5207\u308c\u307e\u3057\u305f\u3002\u518d\u5ea6\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u304f\u3060\u3055\u3044\u3002']);\n        });\n    }\n}\n\n\/\/ \u30bb\u30c3\u30b7\u30e7\u30f3\u30c8\u30e9\u30d6\u30eb\u306e\u8a3a\u65ad\u30d8\u30eb\u30d1\u30fc\nclass SessionDiagnostics\n{\n    public static function checkSessionConfiguration()\n    {\n        $issues = [];\n\n        if (!ini_get('session.save_handler')) {\n            $issues[] = '\u30bb\u30c3\u30b7\u30e7\u30f3\u30cf\u30f3\u30c9\u30e9\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002';\n        }\n\n        if (!is_writable(config('session.files'))) {\n            $issues[] = '\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u66f8\u304d\u8fbc\u307f\u6a29\u9650\u304c\u3042\u308a\u307e\u305b\u3093\u3002';\n        }\n\n        return $issues;\n    }\n}<\/pre>\n\n\n\n<p><strong>2. \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u30a8\u30e9\u30fc\u306e\u51e6\u7406<\/strong><\/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=\"\">\/\/ app\/Providers\/DatabaseServiceProvider.php\nclass DatabaseServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        \/\/ \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u63a5\u7d9a\u30a8\u30e9\u30fc\u306e\u76e3\u8996\n        DB::listen(function ($query) {\n            if ($query-&gt;time &gt; 1000) {  \/\/ 1\u79d2\u4ee5\u4e0a\u304b\u304b\u308b\u30af\u30a8\u30ea\u3092\u691c\u51fa\n                Log::warning('\u30b9\u30ed\u30fc\u30af\u30a8\u30ea\u3092\u691c\u51fa:', [\n                    'sql' =&gt; $query-&gt;sql,\n                    'time' =&gt; $query-&gt;time,\n                    'bindings' =&gt; $query-&gt;bindings,\n                ]);\n            }\n        });\n\n        \/\/ \u30c7\u30c3\u30c9\u30ed\u30c3\u30af\u691c\u51fa\n        DB::connection()-&gt;beforeExecuting(function ($query) {\n            \/\/ \u30af\u30a8\u30ea\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u306e\u8a2d\u5b9a\n            DB::statement('SET SESSION wait_timeout = 28800');\n        });\n    }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-27\">\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u6642\u306e\u4e92\u63db\u6027\u78ba\u8a8d\u30dd\u30a4\u30f3\u30c8<\/h3>\n\n\n\n<p><strong>1. \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u524d\u306e\u78ba\u8a8d\u4e8b\u9805<\/strong><\/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=\"\">\/\/ app\/Console\/Commands\/PreUpdateCheck.php\nclass PreUpdateCheck extends Command\n{\n    protected $signature = 'jetstream:pre-update-check';\n\n    public function handle()\n    {\n        $this-&gt;info('Jetstream\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u524d\u306e\u78ba\u8a8d\u3092\u958b\u59cb\u3057\u307e\u3059...');\n\n        \/\/ \u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u30d5\u30a1\u30a4\u30eb\u306e\u78ba\u8a8d\n        $customizations = $this-&gt;checkCustomizations();\n        if ($customizations-&gt;isNotEmpty()) {\n            $this-&gt;warn('\u4ee5\u4e0b\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3055\u308c\u3066\u3044\u307e\u3059:');\n            $customizations-&gt;each(fn($file) =&gt; $this-&gt;line(\"- {$file}\"));\n        }\n\n        \/\/ \u4f9d\u5b58\u30d1\u30c3\u30b1\u30fc\u30b8\u306e\u4e92\u63db\u6027\u78ba\u8a8d\n        $this-&gt;checkDependencies();\n\n        \/\/ \u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u306e\u78ba\u8a8d\n        if (!$this-&gt;confirmBackup()) {\n            $this-&gt;error('\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u3092\u5148\u306b\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002');\n            return 1;\n        }\n    }\n\n    private function checkCustomizations()\n    {\n        $publishedFiles = [\n            resource_path('views\/vendor\/jetstream'),\n            resource_path('views\/layouts'),\n            resource_path('js\/Components'),\n        ];\n\n        return collect($publishedFiles)\n            -&gt;filter(fn($path) =&gt; File::exists($path));\n    }\n}<\/pre>\n\n\n\n<p><strong>2. \u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u5f8c\u306e\u691c\u8a3c<\/strong><\/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=\"\">\/\/ app\/Console\/Commands\/PostUpdateVerification.php\nclass PostUpdateVerification extends Command\n{\n    public function handle()\n    {\n        $this-&gt;info('\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u5f8c\u306e\u691c\u8a3c\u3092\u958b\u59cb\u3057\u307e\u3059...');\n\n        \/\/ \u5fc5\u8981\u306a\u30c6\u30fc\u30d6\u30eb\u306e\u5b58\u5728\u78ba\u8a8d\n        $this-&gt;verifyDatabaseTables();\n\n        \/\/ \u8a8d\u8a3c\u6a5f\u80fd\u306e\u52d5\u4f5c\u78ba\u8a8d\n        $this-&gt;verifyAuthentication();\n\n        \/\/ \u30a2\u30bb\u30c3\u30c8\u306e\u30b3\u30f3\u30d1\u30a4\u30eb\u78ba\u8a8d\n        $this-&gt;verifyAssets();\n    }\n\n    private function verifyDatabaseTables()\n    {\n        $requiredTables = [\n            'users', 'teams', 'team_user', 'sessions',\n            'personal_access_tokens',\n        ];\n\n        foreach ($requiredTables as $table) {\n            if (!Schema::hasTable($table)) {\n                $this-&gt;error(\"\u30c6\u30fc\u30d6\u30eb '{$table}' \u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002\");\n                $this-&gt;info(\"php artisan migrate \u3092\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002\");\n            }\n        }\n    }\n}<\/pre>\n\n\n\n<p><strong>\u5b9f\u904b\u7528\u6642\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u76e3\u8996\u3068\u30ed\u30b0\u7ba1\u7406<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30a8\u30e9\u30fc\u30ed\u30b0\u306e\u5b9a\u671f\u7684\u306a\u78ba\u8a8d<\/li>\n\n\n\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30e1\u30c8\u30ea\u30af\u30b9\u306e\u53ce\u96c6<\/li>\n\n\n\n<li>\u30e6\u30fc\u30b6\u30fc\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u306e\u76e3\u8996<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u6226\u7565<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5b9a\u671f\u7684\u306a\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30d0\u30c3\u30af\u30a2\u30c3\u30d7<\/li>\n\n\n\n<li>\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u7ba1\u7406<\/li>\n\n\n\n<li>\u30ea\u30b9\u30c8\u30a2\u624b\u9806\u306e\u6587\u66f8\u5316<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3\u5bfe\u7b56<\/strong><\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6c34\u5e73\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u306e\u6e96\u5099<\/li>\n\n\n\n<li>\u30ad\u30e3\u30c3\u30b7\u30e5\u6226\u7565\u306e\u6700\u9069\u5316<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u5206\u6563\u5316<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5bfe\u7b56\u3092\u5b9f\u65bd\u3059\u308b\u3053\u3068\u3067\u3001Jetstream\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u5b89\u5b9a\u904b\u7528\u304c\u53ef\u80fd\u306b\u306a\u308a\u307e\u3059\u3002\u7279\u306b\u3001\u5b9f\u904b\u7528\u74b0\u5883\u3067\u306f\u5b9a\u671f\u7684\u306a\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u3068\u30e1\u30f3\u30c6\u30ca\u30f3\u30b9\u304c\u91cd\u8981\u3067\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-2623","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\/2623","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=2623"}],"version-history":[{"count":2,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2623\/revisions"}],"predecessor-version":[{"id":2625,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/2623\/revisions\/2625"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}