{"id":10020430,"date":"2024-12-01T15:39:43","date_gmt":"2024-12-01T07:39:43","guid":{"rendered":"https:\/\/itmax.cn\/?p=10020430"},"modified":"2024-12-01T15:39:43","modified_gmt":"2024-12-01T07:39:43","slug":"laravel-%e5%a4%9a%e6%80%81%e5%85%b3%e8%81%94%e7%9a%84%e6%a8%a1%e5%9e%8b%e6%9c%ac%e5%9c%b0%e5%8c%96%e5%a5%97%e7%94%a8","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10020430","title":{"rendered":"Laravel \u591a\u6001\u5173\u8054\u7684\u6a21\u578b\u672c\u5730\u5316\u5957\u7528"},"content":{"rendered":"<h2>Laravel \u591a\u6001\u5173\u8054\u7684\u6a21\u578b\u672c\u5730\u5316\u5957\u7528<\/h2>\n<h3>\u524d\u8a00<\/h3>\n<p>\u5728\u9879\u76ee\u4e2d\uff0c\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5355\u4e2a\u5b57\u6bb5\u6765\u521b\u5efa\u4e00\u4e2a\u4e00\u5bf9\u4e00\u6216\u8005\u4e00\u5bf9\u591a\u5173\u8054\uff0c\u6bd4\u5982\u4e00\u4e2a User \u6709\u591a\u4e2a Post\u3002<\/p>\n<p>\u800c\u9664\u4e86\u8fd9\u4e9b\uff0c\u6211\u4eec\u5076\u5c14\u4f1a\u9047\u5230\u4e00\u4e9b\u5173\u8054\u5173\u7cfb\u9664\u4e86\u9700\u8981\u6839\u636e ID \u8fdb\u884c\u5173\u8054\u5916\uff0c\u8fd8\u53ef\u80fd\u9700\u8981\u6839\u636e\u4e0d\u540c\u7684 Type \u53bb\u5173\u8054\u4e0d\u540c\u7684\u6a21\u578b\uff0c\u800c\u8fd9\uff0c\u5c31\u662f\u591a\u6001\u5173\u8054\u3002<\/p>\n<p>\u5728 Laravel \u4e2d\uff0c\u4e3a\u6211\u4eec\u63d0\u4f9b\u4e86\u5f00\u7bb1\u5373\u7528\u7684\u591a\u6001\u5173\u8054\u3002<\/p>\n<h3>\u51c6\u5907\u73af\u5883<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u8f6f\u4ef6<\/th>\n<th>\u7248\u672c<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Windows 11<\/td>\n<td>24H2<\/td>\n<\/tr>\n<tr>\n<td>PHP<\/td>\n<td>8.2.6 ZTS Visual C++ 2019 x64<\/td>\n<\/tr>\n<tr>\n<td>Xdebug<\/td>\n<td>3.3.2<\/td>\n<\/tr>\n<tr>\n<td>SQLite<\/td>\n<td>&#8212;<\/td>\n<\/tr>\n<tr>\n<td>Laravel Framework<\/td>\n<td>11.34.2 <sub>[\u6ce81]<\/sub><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h4>\u8868\u7ed3\u6784<sub>[\u6ce82]<\/sub><\/h4>\n<pre style=\"display:none;\"><code class=\"mermaid\">classDiagram\ndirection BT\nclass comments {\n   varchar commentable_type\n   integer commentable_id\n   text body\n   datetime created_at\n   datetime updated_at\n   integer id\n}\nclass posts {\n   varchar title\n   text content\n   datetime created_at\n   datetime updated_at\n   integer id\n}\nclass videos {\n   varchar title\n   varchar url\n   datetime created_at\n   datetime updated_at\n   integer id\n}\n<\/code><\/pre>\n<p>\u5982\u4e0a\u56fe\u6240\u793a\uff0c\u6211\u4eec\u5b58\u5728\u4e09\u5f20\u8868\uff0c\u5176\u4e2d\uff0ccomments \u4f7f\u7528 commentable_id \u5206\u522b\u4e0e posts \u548c videos \u5173\u8054\uff0c\u81f3\u4e8e\u5177\u4f53\u9700\u8981\u5173\u8054\u54ea\u4e00\u4e2a\u6a21\u578b\uff0c\u5219\u9700\u8981\u6839\u636e commentable_type \u6765\u51b3\u5b9a\u3002<\/p>\n<p>\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cLaravel \u5728 commentable_type \u4e2d\u586b\u5145\u7684\u662f Post \u548c Video \u6a21\u578b\u7684\u5b8c\u6574\u547d\u540d\u7a7a\u95f4\u7c7b\u540d\u3002\u4e5f\u5c31\u662f\u5206\u522b\u4e3a\uff1a<code>App\/Models\/Post<\/code> \u548c <code>App\/Models\/Video<\/code>\uff0c\u8fd9\u4e2a\u8bbe\u8ba1\u5e26\u6765\u4e86\u4e00\u4e9b\u5c0f\u95ee\u9898\u3002<\/p>\n<ul>\n<li>\u6211\u4eec\u7684 type \u5b57\u6bb5\u548c\u5b9e\u4f53\u7c7b\u540d\u5f3a\u5173\u8054\u4e86\uff0c\u5982\u679c\u5c06\u6765\u7c7b\u53ef\u80fd\u8981\u6539\u540d\u5b57\uff0c\u5c31\u52bf\u5fc5\u8981\u4fee\u6539\u6570\u636e\u5e93\u5185\u7684\u6570\u636e\u624d\u884c\u3002<\/li>\n<li>\u8fd9\u91cc\u9762\u5305\u542b\u4e86 <code>\/<\/code> \u8fd9\u4e2a \u201c\u9ebb\u70e6\u201d\u7684\u5b57\u7b26\uff0c\u6709\u4e9b SQL \u5de5\u5177\u4f60\u8fd8\u9700\u8981\u591a\u6b21\u8f6c\u4e49\u540e\u624d\u80fd\u6784\u6210\u6700\u7ec8\u7684\u67e5\u8be2\uff0c\u5c24\u5176\u662f\u6709\u4e9b\u7279\u522b\u7684\u67e5\u8be2\u3002<\/li>\n<li>\u8fd9\u91cc\u5b8c\u6574\u7684\u7c7b\u540d\u592a\u8fc7\u4e8e\u5197\u957f\uff0c\u4ed6\u4eec\u51e0\u4e4e\u90fd\u6709\u4e00\u6837\u7684\u524d\u7f00\uff0c\u53ea\u662f\u540e\u9762\u7684\u7c7b\u540d\u4e0d\u4e00\u6837\u800c\u5df2\u3002<\/li>\n<\/ul>\n<p>\u57fa\u4e8e\u4ee5\u4e0a\u7684\u95ee\u9898\uff0cLaravel \u5b98\u65b9\u4e5f\u63d0\u4f9b\u4e86\u89e3\u51b3\u65b9\u6848\uff0c\u5c31\u662f\u4f7f\u7528 <code>Relation::morphMap<\/code> \u65b9\u6cd5\uff0c\u5b83\u7528\u8d77\u6765\u5c31\u50cf\u4e0b\u9762\u8fd9\u6837\u3002<\/p>\n<pre><code class=\"php\">public function boot(){\n    Relation::morphMap([\n        'post' =&gt; 'App\/Models\/Post',\n        'video' =&gt; 'App\/Models\/Video',\n    ]);\n}<\/code><\/pre>\n<p>\u7b49\u7b49\uff0c\u4e0d\u5bf9\u554a\uff0c\u6211\u770b\u6587\u6863\u4e2d\u660e\u660e\u662f <code>Relation::enforceMorphMap<\/code>\uff0c\u4f60\u600e\u4e48\u8bf4\u662f <code>morphMap<\/code>\uff0c\u5176\u5b9e\u90fd\u6ca1\u9519\uff0c\u867d\u7136\u4f60\u73b0\u5728\u770b\u5230\u6700\u65b0\u7684 Laravel \u6587\u6863\u4e2d\u63d0\u5230\u7684\u662f <code>Relation::enforceMorphMap<\/code> \uff0c\u4f46\u662f\u5b9e\u9645\u4e0a\uff0c<code>morphMap<\/code> \u4e5f\u662f\u53ef\u4ee5\u7528\u7684\uff0c\u56e0\u4e3a\u8fd9\u662f\u4e4b\u524d\u9057\u7559\u4e0b\u7684\u65b9\u6cd5\uff0c\u90a3\u65e2\u7136\u6709 <code>morphMap<\/code> \u4e86\uff0c\u4e3a\u4ec0\u4e48\u8fd8\u9700\u8981 <code>enforceMorphMap<\/code>\uff1f<\/p>\n<p>\u95ee\u5f97\u597d\uff0c\u5728\u4f7f\u7528 <code>morphMap<\/code> \u6211\u4eec\u53ef\u4ee5\u9009\u62e9\u4e3a\u90e8\u5206\u7684 morph \u8bbe\u7f6e\u6620\u5c04\uff0c\u6bd4\u5982\u4e0a\u9762\u7684\u4f8b\u5b50\u4e2d\uff0c\u6211\u53ef\u4ee5\u53ea\u6620\u5c04 post\u3001\u800c\u4e0d\u6620\u5c04 video\uff0c\u4e5f\u5c31\u662f\u8bf4\uff0c\u5728\u6570\u636e\u5e93\u4e2d\uff0cpost \u7684 type \u4fdd\u5b58\u7684\u662f post\u3001\u800c video \u5374\u4fdd\u5b58\u7684 <code>App\/Models\/Video<\/code>\uff0c\u9020\u6210\u4e86\u4e00\u79cd\u4e0d\u4e00\u81f4\u4e86\u3002\u5c24\u5176\u662f\u8fd9\u91cc\u7684 \u201c\u591a\u6001\u201d\uff0c\u5c31\u610f\u5473\u7740\uff0c\u4e00\u5f00\u59cb\u53ef\u80fd\u53ea\u6709\u8fd9\u4e24\u4e2a\u7c7b\u578b\uff0c\u7ed3\u679c\u540e\u9762\u53c8\u65b0\u589e\u4e00\u4e2a\u7c7b\u578b\uff0c\u524d\u9762\u7684\u4f60\u90fd\u6620\u5c04\u4e86\uff0c\u800c\u540e\u9762\u7684\u540c\u4e8b\u5fd8\u4e86\u6620\u5c04\uff0c\u5c31\u5bfc\u81f4\u6570\u636e\u5e93\u91cc\u9762\u7684\u6570\u636e\u770b\u8d77\u6765\u4e71\u7cdf\u7cdf\u7684\u4e86\u3002<\/p>\n<p>\u6240\u4ee5\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u81ea Laravel 8.x \u5f00\u59cb\uff0c\u5f15\u5165\u4e86 <a href=\"https:\/\/link.segmentfault.com\/?enc=aD9FgJJ%2Fp15ZbPwbuVB9kg%3D%3D.0mSQfWh1WYBs8rLFTqSaK3ThWVnYch7cbatypiAuou%2F4ds84nnm8kYpci%2FsNed1txPF4ct%2BMU8NEno6HD7OS8Q%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">enforceMorphMap<\/a> \u8fd9\u4e2a Feature\uff0c\u5e76\u4e14\u6587\u6863\u91cc\u9762\u4e5f\u6539\u4e3a\u4e86\u8fd9\u4e2a\u65b9\u6cd5\uff0c\u73b0\u5728\u5982\u679c\u4f60\u4f7f\u7528\u4e86\u8fd9\u4e2a\uff0c\u6a21\u578b\u5374\u5fd8\u4e86\u6620\u5c04\uff0c\u5c31\u4f1a\u629b\u51fa\u4e00\u4e2a <code>ClassMorphViolationException<\/code> \u5f02\u5e38\uff0c\u800c\u4e0d\u662f\u50cf\u4e4b\u524d\u90a3\u6837\u9ed8\u4e0d\u4f5c\u58f0\uff0c\u4ece\u800c\u5e2e\u52a9\u4f60\u5728\u5f00\u53d1\u9636\u6bb5\u53d1\u73b0\u8fd9\u4e2a\u95ee\u9898\uff0c\u5b83\u5185\u90e8\u5176\u5b9e\u662f\u8c03\u7528\u4e86 <code>requireMorphMap<\/code> + <code>morphMap<\/code> \u800c\u5df2\uff0c\u5f53\u7136\uff0c\u5982\u679c\u4f60\u559c\u6b22\u4e4b\u524d\u90a3\u6837\uff0c\u8fd8\u662f\u53ef\u4ee5\u8c03\u7528\u65e7\u7684 <code>morphMap<\/code> \u65b9\u6cd5 \u3002<\/p>\n<h3>\u9047\u5230\u7684\u95ee\u9898<\/h3>\n<p>\u5b9e\u9645\u4e0a\uff0c\u4e0a\u9762\u90fd\u662f\u7406\u60f3\u5b8c\u7f8e\u72b6\u6001\uff0c\u6709\u4e00\u4e9b\u7279\u522b\u7684\u9650\u5236\u3002<\/p>\n<ul>\n<li>\u5b9a\u4e49\u7684\u522b\u540d\u5fc5\u987b\u662f\u5168\u5c40\u552f\u4e00\u7684\u3002<\/li>\n<li>\u4f7f\u7528\u6570\u5b57\u4f5c\u4e3a\u522b\u540d\u65f6\uff0c\u88ab\u610f\u5916\u7684\u91cd\u7f6e\uff08Laravel &lt; 5.5\uff09<\/li>\n<\/ul>\n<p>\u6709\u65f6\u5019\u6211\u4eec\u7684\u4e1a\u52a1\u4e2d\u5c31\u662f\u4f7f\u7528\u4e86\u6570\u5b57\u6765\u533a\u5206\u4e0d\u540c\u7684 type\uff0c\u5e76\u4e14\u4e0d\u540c\u6a21\u578b\u7684 type \u53ef\u80fd\u8fd8\u4f1a\u91cd\u590d\uff0c\u6bd4\u5982\u6211\u4eec\u5e0c\u671b\u5728 Comment \u4e2d\uff0ctype 1\/2 \u5206\u522b\u8868\u793a Post \u548c Video\uff0c\u800c\u5728 Attachment \u4e2d\uff0ctype 1\/2 \u53c8\u5206\u522b\u8868\u793a User \u548c Product\u3002<\/p>\n<p>\u901a\u5e38\u6211\u4eec\u76f4\u63a5\u8fd9\u6837\u505a\u7684\u8bdd\uff0c\u90fd\u4f1a\u5f97\u5230\u4e00\u4e2a\u9519\u8bef\uff1a<code>Class name must be a valid object or a string<\/code>\uff0c\u5b83\u6765\u81ea\u4e8e PHP\uff0c\u56e0\u4e3a PHP \u5728\u5c1d\u8bd5 new \u8fd9\u4e2a\u7c7b\u7684\u65f6\u5019\uff0c\u65e0\u6cd5\u89e3\u6790\u4e86\u3002<\/p>\n<p>\u8fd9\u4e2a\u9700\u6c42\u5f88\u201c\u5e38\u89c1\u201d\u662f\u5427\uff0c\u4f46\u662f\u76ee\u524d\u5374\u505a\u4e0d\u5230\u3002<\/p>\n<p>\u5728\u65e9\u671f\u7684\u7248\u672c\u4e2d\uff0c\u5176\u5b9e\u8fd8\u5b58\u5728\u53e6\u5916\u4e00\u4e2a\u7531 <code>morphMap<\/code> \u5e26\u6765\u7684\u95ee\u9898<\/p>\n<pre><code class=\"php\">    public static function morphMap(array $map = null, $merge = true)\n    {\n        $map = static::buildMorphMapFromModels($map);\n\n        if (is_array($map)) {\n            static::$morphMap = $merge &amp;&amp; static::$morphMap\n                            ? array_merge(static::$morphMap, $map) : $map;\n        }\n\n        return static::$morphMap;\n    }\n<\/code><\/pre>\n<p>\u5982\u4e0a\u7684\u4ee3\u7801\u4e2d\uff0c\u5982\u679c\u6211\u4eec\u4f20\u5165\u7684\u6620\u5c04\u952e\u662f\u6570\u5b57\u7684\uff0c\u4ee3\u7801\u8fdb\u5165 array_merge \u7684\u5206\u652f\u65f6\uff0c\u5c31\u4f1a\u56e0\u4e3a array_merge \u5bfc\u81f4\u7d22\u5f15\u88ab\u91cd\u7f6e\u2026\u2026<\/p>\n<ul>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=sTT9VWk7eWI4AQ2jluCMCw%3D%3D.vu%2FBZ%2Fu01tRSstloG%2FUeYqgUCeoEVgB%2BhcNlGbgjNLDW4i8S0o6kvk1S0HOW1u6FL%2BSlZfHSwsN0kvkGBjHamA%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Illuminate\/Database\/Eloquent\/Relations\/Relation::morphMap should allow numeric types \u00b7 Issue #12845 \u00b7 laravel\/framework<\/a><\/li>\n<\/ul>\n<p>\u5728\u4e0a\u9762\u7684\u8fd9\u4e2a\u8ba8\u8bba\u4e2d\uff0c\u8fd8\u63d0\u5230\u4e86\u53e6\u5916\u4e00\u4e2a\u95ee\u9898\uff0c\u5c31\u662f\u80fd\u5426\u4ee5\u7ec4\u7684\u65b9\u5f0f\uff0c\u4e3a\u6bcf\u4e2a\u90fd\u5b9a\u4e49\u6620\u5c04\uff0c\u4e0d\u8fc7\u8fd9\u4e2a\u95ee\u9898\u7684\u8ba8\u8bba\u5e76\u6ca1\u6709\u7ed3\u679c\uff0c\u4f46\u662f\u7c7b\u4f3c\u7684\u671f\u5f85\u8fd8\u662f\u633a\u591a\u7684\uff0c\u751a\u81f3\u8fd8\u51fa\u73b0\u4e86\u4e00\u4e9b\u504f\u95e8\u7684\u3002<\/p>\n<ul>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=DU144cjJIRIVnebSovE%2B4A%3D%3D.zQVSowP3ILnP1dv%2FMGk%2BvkG72fEXIrowxhp2Iggb9RKoLwbo7FaWHSlpIyHbhulD\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\/[8.x] Option to use table names when morphing by taylorotwell \u00b7 Pull Request #38451 \u00b7 laravel\/framework<\/a><\/li>\n<\/ul>\n<p>\u8fd9\u4e2a PR \u4e2d\uff0c\u6dfb\u52a0\u4e86\u4e00\u4e2a <code>Relation::morphUsingTableNames()<\/code> \u65b9\u6cd5\uff0c\u7528\u4e8e\u81ea\u52a8\u6620\u5c04\u8868\u540d\uff0c\u4f46\u662f\u56e0\u4e3a\u4e00\u4e9b\u590d\u6742\u7684\u539f\u56e0\uff0c\u8fd9\u4e2a PR \u6700\u540e\u8fd8\u662f\u88ab Revert \u4e86\uff0c\u56e0\u4e3a\u5b83\u8fd8\u5b58\u5728\u4e00\u4e9b\u5176\u4ed6\u4e0d\u80fd\u88ab\u4fee\u590d\u7684[\u95ee\u9898<a href=\"https:\/\/link.segmentfault.com\/?enc=gFqNip%2FIDf7F3xWH9Vz%2Fhw%3D%3D.%2F0cTv9C5VCBESMGaCnBVkV5bkWb8CJegNokwpWlIywUyOAZGLdNp%2B7X2dPYWDttPUDllM2tIXZqFCW447Qh23g%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">https:\/\/github.com\/laravel\/framework\/issues\/35519<\/a>]()\u3002<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"723\" height=\"170\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdfbpM\" alt=\"image.png\" title=\"image.png\"><\/p>\n<p>\u5176\u5b9e\u5728\u8fd9\u4e2a PR \u4e2d\uff0c\u8fd8\u6709\u53e6\u5916\u4e00\u4e2a<a href=\"https:\/\/link.segmentfault.com\/?enc=a5Qai6yKHu3ooy07dVkf4w%3D%3D.ZAOOKY3TePwyrAndh5R9EHzRsLajMLk0u0eJwZYeifLoAnXlGLb%2BLSBQjNiIewAl9%2ByKS1cby0Zzz2WsHPEwvraQksr5GnFEZxIF1sFMOao%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u58f0\u97f3<\/a>\uff1a<\/p>\n<p><img decoding=\"async\" width=\"723\" height=\"148\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdfbpN\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<blockquote>\n<h4><strong><a href=\"https:\/\/link.segmentfault.com\/?enc=Y45tTCYstCW1Zle4DhJLXg%3D%3D.bPqCuqRkmPnwOmaPvQBjDiVi%2BiDrxpKRIrCfHoqKJDk%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">imliam<\/a><\/strong> <a href=\"https:\/\/link.segmentfault.com\/?enc=cc0EFfnnJhOOK%2FdluaK9cg%3D%3D.sRw3Cced0o2ngoOraHk4VL%2BMLXYpbiP6Ru8iI1acCzvOcymcIz3%2F5xIO2QQLKF41%2BHSea7CcH5vcQ4iIitzTZxpU12WMnbktnvHxU9o8wss%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">on Aug 20, 2021<\/a><\/h4>\n<p>While this code is being changed, maybe it would also be useful to add an optional property\/method to models (eg. <code>morphableName<\/code>) that can be used &#8211; so each model can represent its own morphable name itself instead of being done elsewhere in a map?<\/p>\n<\/blockquote>\n<h3>\u5bfb\u627e\u89e3\u836f<\/h3>\n<p>\u4e0d\u8fc7\u503c\u5f97\u4e00\u63d0\u7684\u662f Laravel \u4e2d\u786e\u5b9e\u6709\u4e00\u4e2a\u5b58\u5728\u7c7b\u4f3c\u80fd\u529b\u7684\u65b9\u6cd5\uff0c\u90a3\u5c31\u662f <code>HasRelationships::getActualClassNameForMorph<\/code>\uff0c\u76ee\u524d\uff0c\u4ed6\u4f1a\u5728\u4f60\u4f7f\u7528<strong>\u5355\u4e2a\u6a21\u578b<\/strong>\u8bbf\u95ee\u5c1a\u672a\u52a0\u8f7d\u7684\u591a\u6001\u6a21\u578b\u65f6\u88ab\u8c03\u7528\uff0c\u4f1a\u4f20\u5165 type \u7684\u503c\u4f5c\u4e3a\u53c2\u6570\uff0c\u4e5f\u5c31\u662f\u8bf4\uff0c\u5982\u679c\u6570\u636e\u5e93\u4e2d\u4fdd\u5b58\u7684\u662f 1 \uff0c\u8fd9\u91cc\u5c31\u4f1a\u4f20\u5165 1\u3002<\/p>\n<p>\u8fd9\u4e2a\u65b9\u6cd5\u7684\u9ed8\u8ba4\u5b9e\u73b0\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"php\">    public static function getActualClassNameForMorph($class)\n    {\n        return Arr::get(Relation::morphMap() ?: [], $class, $class);\n    }\n<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u8fd9\u91cc\u5b9e\u9645\u4e0a\u5c31\u662f\u8c03\u7528\u4e86\u524d\u9762\u5b9a\u4e49\u7684\u6620\u5c04\u800c\u5df2\uff0c\u73b0\u5728\u6211\u4eec\u5230 Comment \u6dfb\u52a0\u8fd9\u4e2a\u65b9\u6cd5\u7684\u590d\u5199\uff1a<\/p>\n<pre><code class=\"php\">    public static function getActualClassNameForMorph($class)\n    {\n        return match ((int) $class) {\n            1 =&gt; Post::class,\n            2 =&gt; Video::class,\n            default =&gt; parent::getActualClassNameForMorph($class),\n        };\n    }\n<\/code><\/pre>\n<p>\u7136\u540e\u4f60\u5c31\u4f1a\u53d1\u73b0\u4e00\u4e2a\uff0c\u597d\u50cf\u786e\u5b9e\u53ef\u4ee5\u3002\u5f53\u4f60\u6267\u884c\u7f16\u5199\u4e0b\u9762\u7684\u4ee3\u7801\u65f6\uff0c\u4f60\u786e\u5b9e\u62ff\u5230\u4e86\u5bf9\u5e94\u7684 commentable<\/p>\n<pre><code class=\"php\">dump(\/App\/Models\/Comment::first()-&gt;commentable);<\/code><\/pre>\n<p>\u770b\u8d77\u6765\u5f88\u7f8e\u597d\uff0c\u4f60\u5e94\u66f4\u5f88\u5feb\u5c31\u4f1a\u53d1\u73b0\uff0c\u8fd9\u5b9e\u9645\u4e0a\u5e26\u6765\u4e86\u53e6\u5916\u4e00\u4e2a\u95ee\u9898\uff0c<strong>\u4f60\u6ca1\u6cd5\u4f7f\u7528 with \u548c load \u8fdb\u884c\u9884\u52a0\u8f7d\u5173\u7cfb\u4e86<\/strong>\u3002<\/p>\n<p>\u5f53\u4f60\u4f7f\u7528 with \u6216\u8005 load \u65f6\uff0c\u4f60\u5c06\u4f1a\u5f97\u5230\u4e00\u4e2a\u8ddf\u6ca1\u6709\u4f7f\u7528\u8fd9\u4e2a\u65b9\u6cd5\u65f6\u4e00\u6837\u7684\u9519\u8bef\uff1a<code>Class name must be a valid object or a string<\/code>\uff0c\u662f\u7684\uff0c\u6ca1\u9519\uff0c\u4ed6\u5c31\u662f\u771f\u7684\u6ca1\u6709\u4f7f\u7528\u8fd9\u4e2a\u65b9\u6cd5\u2026\u2026\uff0c\u60f3\u4e0d\u5230\u5427\u3002<\/p>\n<p>\u8fd9\u5176\u5b9e\u662f Laravel \u7ed9\u6211\u4eec\u5f00\u7684\u4e00\u4e2a\u201c\u5c0f\u73a9\u7b11\u201d\uff0c\u5f53\u6211\u4eec\u4ece\u4e00\u4e2a\u5c1a\u672a\u9884\u52a0\u8f7d commentable \u7684\u6a21\u578b\u65f6\uff0c\u5982\u679c\u8bbf\u95ee commentable\uff0c\u90a3\u4e48 Laravel \u6309\u7167\u4ee5\u4e0b\u8def\u5f84\u6765\u8bbf\u95ee\u5230\u6211\u4eec\u521a\u521a\u8986\u76d6\u7684 <code>getActualClassNameForMorph<\/code> \u65b9\u6cd5\u3002<\/p>\n<pre style=\"display:none;\"><code class=\"mermaid\">graph TD\n    A[HasRelationships.morphInstanceTo]\n    B[HasRelationships.morphTo]\n    C[Comment.commentable]\n\n    B --&gt; A\n    C --&gt; B<\/code><\/pre>\n<p>Laravel \u5148\u8c03\u7528\u4e86\u6211\u4eec\u7684\u5173\u7cfb\u65b9\u6cd5 commentable\uff0c\u7136\u540e\u5173\u7cfb\u91cc\u9762\u8c03\u7528\u4e86 morphTo\uff0c\u63a5\u7740\u53c8\u8c03\u7528\u4e86 morphInstanceTo\uff0c\u7136\u540e\u5728 morphInstanceTo \u8c03\u7528\u4e86\u6211\u4eec\u521a\u521a\u521b\u5efa\u7684\u65b9\u6cd5\u3002<\/p>\n<pre><code class=\"php\">    protected function morphInstanceTo($target, $name, $type, $id, $ownerKey)\n    {\n        $instance = $this-&gt;newRelatedInstance(\n            static::getActualClassNameForMorph($target)\n        );\n\n        return $this-&gt;newMorphTo(\n            $instance-&gt;newQuery(), $this, $id, $ownerKey ?? $instance-&gt;getKeyName(), $type, $name\n        );\n    }<\/code><\/pre>\n<p>\u6ce8\u610f\uff0c\u8fd9\u91cc\u4e4b\u6240\u4ee5\u80fd\u591f\u8bbf\u95ee\u5230\u6211\u4eec\u5b9a\u4e49\u7684 <code>getActualClassNameForMorph<\/code> \u65b9\u6cd5\uff0c\u6b63\u662f\u56e0\u4e3a\u8fd9\u91cc\u4f7f\u7528\u4e86 <code>statis<\/code> \u8fdb\u884c\u8c03\u7528\uff08<a href=\"https:\/\/link.segmentfault.com\/?enc=KtTSlYTgyZsvivj3skKIoQ%3D%3D.VISSAAOTHVsoNqKZIw4xYYg%2B7FDKJMk0SXGRR4frfFI2NIlUKNqVmjm5fzb20DiUjzINcytRrrplLRJl6H3pl%2F3%2B2QNW3%2Fnz63f6GqaposQ%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u5ef6\u8fdf\u7ed1\u5b9a<\/a>\uff09<\/p>\n<p>\u73b0\u5728\uff0c\u518d\u6765\u770b\u770b <code>getActualClassNameForMorph<\/code> \u7684\u53e6\u4e00\u6761\u8bbf\u95ee\u8def\u5f84<\/p>\n<pre style=\"display:none;\"><code class=\"mermaid\">graph TD\n    E[MorphTo.createModelByType]\n    F[MorphTo.getResultsByType]\n    G[MorphTo.getEager]\n    H[Builder.eagerLoadRelation]\n    I[Builder.eagerLoadRelations]\n    J[Model.load]\n    K[Builder.get]\n    L[HasOneOrManyThrough.get]\n    M[BelongsToMany.get]\n\n    F --&gt; E\n    G --&gt; F\n    H --&gt; G\n    I --&gt; H\n    J --&gt; I\n    K --&gt; I\n    L --&gt; I\n    M --&gt; I<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u5e38\u7528\u7684 Builder.get \u548c Model.load \u90fd\u6700\u7ec8\u4f1a\u8bbf\u95ee\u5230 <code>MorphTo.createModelByType<\/code>\u6700\u7ec8\u5728\u8fd9\u4e2a\u65b9\u6cd5\u91cc\u9762\u8c03\u7528\u4e86 <code>getActualClassNameForMorph<\/code><\/p>\n<pre><code class=\"php\">    public function createModelByType($type)\n    {\n        $class = Model::getActualClassNameForMorph($type);\n\n        return tap(new $class, function ($instance) {\n            if (! $instance-&gt;getConnectionName()) {\n                $instance-&gt;setConnection($this-&gt;getConnection()-&gt;getName());\n            }\n        });\n    }<\/code><\/pre>\n<p>\u800c\u8fd9\u91cc\u5374\u4f7f\u7528\u4e86 Model \u8fdb\u884c\u8c03\u7528\uff0c\u8fd9\u662f\u4e3a\u4ec0\u4e48\u5462\uff1f<\/p>\n<p>\u73b0\u5728\u6765\u4f1a\u770b\u4e00\u4e0b\u5b8c\u6574\u7684\u8c03\u7528\u8def\u5f84<\/p>\n<pre style=\"display:none;\"><code class=\"mermaid\">graph TD\n    N[HasRelationships.getActualClassNameForMorph]\n    A[HasRelationships.morphInstanceTo]\n    B[HasRelationships.morphTo]\n    C[Comment.commentable]\n    E[MorphTo.createModelByType]\n    F[MorphTo.getResultsByType]\n    G[MorphTo.getEager]\n    H[Builder.eagerLoadRelation]\n    I[Builder.eagerLoadRelations]\n    J[Builder.get]\n    K[BelongsToMany.get]\n    L[Model.load]\n    M[HasOneOrManyThrough.get]\n\n    A --&gt; N\n    B --&gt; A\n    C --&gt; B\n    E --&gt; N\n    F --&gt; E\n    G --&gt; F\n    H --&gt; G\n    I --&gt; H\n    J --&gt; I\n    K --&gt; I\n    L --&gt; I\n    M --&gt; I<\/code><\/pre>\n<p>\u53ef\u4ee5\u770b\u5230\uff0c\u5f53\u6211\u4eec\u76f4\u63a5\u8bbf\u95ee commentable \u7684\u65f6\u5019\uff0c\u5b9e\u9645\u4e0a\u662f\u8d70\u4e86\u5de6\u8fb9\u7684\u8def\u5f84\uff0c\u800c\u5f53\u6211\u4eec\u4f7f\u7528 with\/load \u65f6\u8d70\u7684\u662f\u53f3\u8fb9\u7684\u8def\u5f84\u3002<\/p>\n<p>\u6b64\u65f6\u6700\u5927\u7684\u533a\u522b\u5c31\u5728\u4e8e\uff0c<code>HasRelationships<\/code> \u672c\u8eab\u662f\u4e00\u4e2a Trait\uff0c\u5b83\u5728\u57fa\u7840 Model \u4e2d\u88ab use\uff0c\u90a3\u4e5f\u5c31\u662f\u8bf4\uff0c\u5728\u4e0a\u9762\u8c03\u7528 <code>HasRelationships.morphInstanceTo<\/code> \u7684\u65f6\u5019 <code>static<\/code> \u5b9e\u9645\u4e0a\u8fd8\u662f\u6211\u4eec\u8c03\u7528\u7684 Model\uff08Comment\uff09\uff0c\u800c MorphTo \u5462\uff1f\u5b83\u662f\u4e00\u4e2a\u5355\u72ec\u7684\u7c7b\uff0c\u6240\u4ee5\u8fd9\u91cc\u662f\u7528\u4e86 Model \u8fdb\u884c\u8c03\u7528\uff0c\u90a3\u6211\u8fd9\u91cc\u5c31\u8bbf\u95ee\u4e0d\u5230 Comment \u5417\uff1f\u5176\u5b9e\u4e0d\u7136\uff0c\u5728 MorphTo \u8fd9\u4e2a\u7c7b\u4e2d\uff0c\u56e0\u4e3a\u5176\u7956\u5148\u7c7b\u662f Relation\uff0c\u5176\u5b9e\u91cc\u9762\u6709\u4e00\u4e2a parent \u5c5e\u6027\uff0c\u8fd9\u4e2a\u5c5e\u6027\u4fdd\u5b58\u7684\u5c31\u662f Comment \u7684\u5b9e\u4f8b\u3002<\/p>\n<pre style=\"display:none;\"><code class=\"mermaid\">classDiagram\n    Relation &lt;|-- BelongsTo\n    BelongsTo &lt;|-- MorphTo\n\n    Relation : +Model parent\n    class Relation\n    class BelongsTo \n    class MorphTo<\/code><\/pre>\n<p>\u4f46\u662f\uff0c\u81f3\u4e8e Laravel \u4e2d\u4e3a\u4ec0\u4e48\u4f1a\u8fd9\u6837\u505a\uff0c\u6682\u65f6\u4e0d\u592a\u6e05\u695a\uff0c\u6ca1\u6709\u627e\u5230\u76f8\u5173\u8d44\u6599\u3002<\/p>\n<p>\u503c\u5f97\u4e00\u63d0\u7684\u662f\uff0c\u5728 Laravel 5.4 \u4e4b\u524d\uff0c\u786e\u5b9e\u6709\u8fc7\u7c7b\u4f3c\u7684\u7528\u6cd5\uff0c\u6b64\u540e\u90fd\u88ab\u53d6\u4ee3\u4e86\u3002<\/p>\n<p><img decoding=\"async\" width=\"723\" height=\"258\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdfbpO\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<ul>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=8WZYthVk3Jducltbm9E0Dw%3D%3D.sSro0bt3qzWMzEi6OZCGeuQhAYE8DmEG2WgEbLvCJY8TUWkUabicVXhCMO11cKisJ7mriC8Cq2Iat0l49lI1O4hlw%2B7BjScPZXl%2F984uJxp6XT%2FP7%2FmRelmVYpb4QUvKfGEqi3qayOAgj4SCmcrrIc2Lrp2FyhGLdmxlbrnUYjbyGgQc2oW4489y9QOC45zx7ktIrkRJzu8fXRcOiB%2FbQ1nufWhRkBZef9xNV7kGiX8%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Cleaning up morphTo relationship. \u00b7 laravel\/framework@3cf7f17<\/a><\/li>\n<\/ul>\n<p>\u5176\u5b9e\u4ece\u4e0a\u9762\u7684 PR \u4e2d\u4e0d\u96be\u770b\u5230\uff0c\u4e00\u5f00\u59cb <code>morphInstanceTo<\/code> \u91cc\u9762\u4e5f\u662f\u4f7f\u7528\u7684 <code>Model<\/code> \u8fdb\u884c\u8c03\u7528\u3002<\/p>\n<p><img decoding=\"async\" width=\"723\" height=\"439\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdfbpP\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<p>\u53ea\u662f\u5728\u968f\u540e\u7684\u4e00\u4e2a <a href=\"https:\/\/link.segmentfault.com\/?enc=8KqmRQh%2FqeaQxceOSMka%2BA%3D%3D.2g7F%2BeA7twN8vgiwa3ZbwYlFerFfU7TrV7htsknj%2FwLoxhXoifPdrMohMLG5jP2f\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">PR<\/a> \u4e2d\uff0c\u6709\u4eba\u8d21\u732e\u4e86\u4e00\u6b21\uff0c\u5e76\u4e14\u628a\u8fd9\u91cc\u6539\u6210\u4e86 <code>static<\/code> \u8c03\u7528\uff0c\u5e76\u4e14\u539f\u56e0\u4e5f\u662f\u8fd9\u4e2a\u8d21\u732e\u8005\u5e0c\u671b\u4f7f\u7528\u6570\u5b57\u6765\u4e3a\u6bcf\u4e2a\u6a21\u578b\u5b9a\u4e49\u6620\u5c04\uff0c\u8fd9\u4e2a PR \u4e5f\u662f\u88ab\u5408\u5e76\u4e86\uff0c\u4e5f\u5c31\u8fbe\u5230\u4e86\u73b0\u5728\u7684\u6837\u5b50\uff0c\u4f46\u662f\u5bf9\u4e8e <code>createModelByType<\/code> \u91cc\u9762\u7684\u8c03\u7528\uff0c\u8fd9\u4f4d\u8d21\u732e\u8005\u4e5f\u63d0\u4ea4\u4e86 <a href=\"https:\/\/link.segmentfault.com\/?enc=cnX7d6hlb9hfTHK3v8UKjw%3D%3D.UH8e2Un2FJks9qIrN7P8sCuNreTvY0Gp7yIvPfcQ1Qi7FcFuGLXJHyOi%2F8MBcIPB\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">PR<\/a>\uff0c\u4f46\u662f\u8fd9\u4e2a PR \u56e0\u4e3a Travis \u7684\u6d4b\u8bd5\u5931\u8d25\u4e86\uff0c\u56e0\u4e3a\u4ed6\u8fd9\u91cc\u662f\u76f4\u63a5\u7c97\u66b4\u7684\u8c03\u7528\u4e86 <code>static<\/code>\uff0c\u524d\u9762\u8bf4\u8fc7\uff0c\u8fd9\u91cc\u7684 static \u5b9e\u9645\u4e0a\u662f\u6307\u5411\u4e86 MorphTo\uff0c\u6240\u4ee5\u81ea\u7136\u662f\u884c\u4e0d\u901a\u7684\uff0c\u4e14\u4f5c\u8005\u6ca1\u6709\u53ca\u65f6\u7ef4\u62a4\uff0c\u88ab\u5173\u95ed\u4e86\uff0c\u81f3\u6b64\u5c31\u9057\u7559\u81f3\u4eca \ud83e\udee5<\/p>\n<ul>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=gwEU0jDYoCnVuRfBuclTWw%3D%3D.q4LUE9iVGdmf5uErXyYK%2FjeKlHy%2B84JXN4lGrzuntT%2B9do2yr%2FEOZnA3eBl6CRc%2F\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">5.4 Allow getActualClassNameForMorph() used by createModelByType() to be overridden by masterwto \u00b7 Pull Request #18099 \u00b7 laravel\/framework<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=T%2Br4fmlpHkxmavuT9k%2FgJg%3D%3D.ne2MtE4%2BcgZwRp3nB643mVXVGkB30%2FJljDsA7%2BiF8hXAq1KrmGrp5q2VyLQ5uD0Y\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">5.4 Update HasRelations::morphInstanceTo() by masterwto \u00b7 Pull Request #18058 \u00b7 laravel\/framework<\/a><\/li>\n<\/ul>\n<p>\u73b0\u5728\uff0c\u8ba9\u6211\u4eec\u6253\u5f00 MorphTo::createModelByType \uff0c\u4fee\u6539 Model \u4e3a parent<\/p>\n<pre><code class=\"diff\">    public function createModelByType($type)\n    {\n-        $class = Model::getActualClassNameForMorph($type);\n+        $class = $this-&gt;parent::getActualClassNameForMorph($type);\n\n        return tap(new $class, function ($instance) {\n            if (! $instance-&gt;getConnectionName()) {\n                $instance-&gt;setConnection($this-&gt;getConnection()-&gt;getName());\n            }\n        });\n    }<\/code><\/pre>\n<p>ok\uff0c\u8fd4\u56de\u6211\u4eec\u7684\u4ee3\u7801\uff0c\u4f60\u5c31\u53ef\u4ee5\u53d1\u73b0 load \u548c with \u90fd\u53ef\u4ee5\u6b63\u5e38\u5de5\u4f5c\u4e86\u3002<\/p>\n<p>\u4f46\u662f\uff0c\u8fd9\u5c31\u591f\u4e86\u5417\uff1f<\/p>\n<p>\u5982\u679c\u4f60\u7684\u8868\u4e2d\u53ea\u6709\u4e00\u4e2a\u8fd9\u6837\u7684\u591a\u6001\u5173\u8054\u5173\u7cfb\uff0c\u8fd9\u5c31\u591f\u4e86\uff0c\u5982\u679c\u4f60\u6709\u591a\u4e2a\uff0c\u8fd9\u53ef\u80fd\u4f1a\u4e0d\u591f\uff0c\u56e0\u4e3a\uff0cgetActualClassNameForMorph \u8fd9\u91cc\u867d\u7136\u662f\u4f20\u5165\u7684 type\uff0c\u4f46\u662f\u4ed6\u5e76\u6ca1\u6709\u544a\u8bc9\u4f60\uff0c\u8fd9\u662f\u6765\u81ea\u54ea\u4e00\u4e2a\u5b57\u6bb5\uff0c\u8fd9\u5728\u9884\u52a0\u8f7d(with\/load) \u7684\u65f6\u5019\u53d8\u5f97\u6781\u4e3a\u56f0\u96be\u3002<\/p>\n<p>\u5f53\u7136\uff0c\u66f4\u91cd\u8981\u7684\u662f\u76ee\u524d\u8fd9\u4e2a\u8fd8\u662f\u8981\u4f60\u53bb\u6539\u6838\u5fc3\u7684\u4ee3\u7801\u6216\u8005\u901a\u8fc7\u5176\u4ed6\u65b9\u5f0f\u6539\u6838\u5fc3\u7684\u4ee3\u7801\uff0c\u6709\u4e9b\u96be\u4ee5\u8fbe\u5230\u3002<\/p>\n<h3>\u9677\u5165\u50f5\u5c40<\/h3>\n<p>\u5176\u5b9e\u5728\u51e0\u5e74\u524d\u6211\u4e5f\u5904\u7406\u8fc7\u8fd9\u4e2a\u95ee\u9898\u5f53\u7136\u662f\u8fd8\u5728\u7528 Laravel 5.4 \u7248\u672c\uff0c\u5f53\u65f6\u6839\u636e\u4e00\u901a\u8c03\u8bd5\u540e\uff0c\u786e\u5b9a\u4e86 Laravel \u5185\u90e8\u5728\u8bbf\u95ee\u5173\u8054\u5b57\u6bb5\u7684\u65f6\u5019\uff0c\u5176\u5b9e\u662f\u4f1a\u901a\u8fc7\u8bbf\u95ee\u5668\u7684 <code>get*Attribute<\/code>\uff0c\u6240\u4ee5\u5f53\u65f6\u7684\u89e3\u51b3\u65b9\u6848\u5c31\u662f\uff0c\u521b\u5efa\u4e86\u4e00\u4e2a <code>getCommentableTypeAttribute<\/code> \u8fd9\u6837\u7684 \u8bbf\u95ee\u5668\u3002<\/p>\n<pre><code class=\"php\">    public function commentableType(): Attribute\n    {\n        return Attribute::get(fn($value) =&gt; match ((int) $value) {\n            1 =&gt; Post::class,\n            2 =&gt; Video::class,\n            default =&gt; $value,\n        });\n    }\n<\/code><\/pre>\n<p>\u597d\u50cf\u786e\u5b9e\u53ef\u4ee5\uff0cwith\/load \u90fd\u5de5\u4f5c\u4e86\u3002<\/p>\n<p>\u4f46\u662f\uff0c\u5f53\u6211\u4eec\u4e0d\u9002\u7528 with\/load \u65f6\uff0c\u76f4\u63a5\u8bbf\u95ee\u672a\u52a0\u8f7d\u7684\u5173\u7cfb\u5c5e\u6027\uff08commentable\uff09\u65f6\uff0c\u4f60\u5c31\u4f1a\u53d1\u73b0\uff0c\u53c8\u51fa\u9519\u4e86\uff0c\u8fd9\u6b21\u5f97\u5230\u7684\u65f6 <code>Class &quot;1&quot; not found<\/code> \u8fd9\u6837\u7684\u9519\u8bef\u3002<\/p>\n<p>What\uff1f<\/p>\n<p>\u5176\u5b9e\u554a\uff0c\u8fd9\u662f\u5728 <code>HasRelationships::morphTo<\/code> \u8fd9\u4e2a\u65b9\u6cd5\u7684 return \u90a3\u91cc\uff0c\u6709\u4e00\u4e2a\u5224\u65ad\uff0c\u5176\u4e3b\u8981\u76ee\u7684\u662f\uff0c\u4f7f\u7528 <code>getAttributeFromArray<\/code> \u83b7\u53d6\u6a21\u578b\u7684 <code>$attributes<\/code> \u5c5e\u6027\uff0c\u5e76\u4e14\u8fd4\u56de\u6307\u5b9a key \u7684\uff0c\u4e5f\u5c31\u662f\u8bf4\uff0c\u4ed6\u8fd9\u91cc\u5b9e\u9645\u4e0a\u65f6\u76f4\u63a5\u8bbf\u95ee\u7684 attributes \u7684\u503c\uff0c\u5e76\u4e0d\u4f1a\u7ecf\u8fc7\u4efb\u4f55\u7684\u8bbf\u95ee\u5668\u2026\u2026\uff0c\u81ea\u7136\u5c31\u6ca1\u6cd5\u4f7f\u7528\u3002<\/p>\n<pre><code class=\"php\">    public function morphTo($name = null, $type = null, $id = null, $ownerKey = null)\n    {\n        \/\/ If no name is provided, we will use the backtrace to get the function name\n        \/\/ since that is most likely the name of the polymorphic interface. We can\n        \/\/ use that to get both the class and foreign key that will be utilized.\n        $name = $name ?: $this-&gt;guessBelongsToRelation();\n\n        [$type, $id] = $this-&gt;getMorphs(\n            Str::snake($name), $type, $id\n        );\n\n        \/\/ If the type value is null it is probably safe to assume we're eager loading\n        \/\/ the relationship. In this case we'll just pass in a dummy query where we\n        \/\/ need to remove any eager loads that may already be defined on a model.\n        return is_null($class = $this-&gt;getAttributeFromArray($type)) || $class === ''\n                    ? $this-&gt;morphEagerTo($name, $type, $id, $ownerKey)\n                    : $this-&gt;morphInstanceTo($class, $name, $type, $id, $ownerKey);\n    }\n<\/code><\/pre>\n<p>\u4e0d\u8fc7\uff0c\u6ce8\u610f\u540e\u9762\u7684\u5224\u65ad\uff0c\u5982\u679c attributes \u6709\u8fd9\u4e2a\u5b57\u6bb5\uff0c\u5c31\u4f1a\u8c03\u7528 <code>morphEagerTo<\/code>\uff0c\u53cd\u4e4b\u8c03\u7528\u540e\u9762\u7684 <code>morphInstanceTo<\/code>\uff0c\u5176\u5b9e\u8fd9\u91cc\u7684\u6ce8\u91ca\u5c31\u5199\u7684\u5f88\u660e\u767d\uff0c\u5982\u679c\u6b64\u65f6\u4ece attributes \u4e0a\u83b7\u53d6\u7684 type \u4e3a\u7a7a\uff0c\u90a3\u4e48\u5c31\u6709\u53ef\u80fd\u6211\u4eec\u5176\u5b9e\u662f\u5728\u4f7f\u7528 with(\u56e0\u4e3a\u8fd9\u65f6\u5019\u67e5\u8be2\u5e76\u6ca1\u6709\u7ed3\u675f\uff0c\u6240\u4ee5\u8fd4\u56de\u4e86 <code>morphEagerTo<\/code>)\uff0c\u800c\u73b0\u5728\u8fd9\u91cc\u662f\u6709\u503c\u7684\uff0c\u4e5f\u5c31\u662f\u6570\u636e\u5e93\u91cc\u9762\u4fdd\u5b58\u7684 1\/2\uff0c\u4e0d\u8fc7\uff0c\u522b\u5fd8\u4e86\uff0c\u4e0a\u9762\u63d0\u5230\u7684\u4f17\u591a <code>getActualClassNameForMorph<\/code> \u8c03\u7528\u8005\u4e2d\uff0c\u5c31\u6709\u8fd9\u4e2a <code>morphInstanceTo<\/code>,\u662f\u7684\uff0c\u6ca1\u9519\u3002\u3002\u3002\u6211\u4eec\u8fd8\u53ef\u80fd\u9700\u8981\u91cd\u5199 <code>getActualClassNameForMorph<\/code> \u65b9\u6cd5\u6765\u5e94\u5bf9\u6ca1\u6709\u9884\u52a0\u8f7d\u7684\u60c5\u51b5\u3002<\/p>\n<p>\u73b0\u5728\u52a0\u4e0a\u4e4b\u524d\u7684 <code>getActualClassNameForMorph<\/code> \u5b9e\u73b0\uff0c\u5c31\u6210\u4e86\u4e0b\u9762\u8fd9\u6837<\/p>\n<pre><code class=\"php\">public function commentable(): MorphTo\n{\n    return $this-&gt;morphTo();\n}    \n\npublic static function getActualClassNameForMorph($class)\n{\n    return match ((int) $class) {\n        1 =&gt; Post::class,\n        2 =&gt; Video::class,\n        default =&gt; parent::getActualClassNameForMorph($class),\n    };\n}\n\npublic function commentableType(): Attribute\n{\n    return Attribute::get(fn($value) =&gt; match ((int) $value) {\n        1 =&gt; Post::class,\n        2 =&gt; Video::class,\n        default =&gt; $value,\n    });\n}\n<\/code><\/pre>\n<p>\u4f60\u8fd8\u53ef\u4ee5\u4f7f\u7528\u65e7\u7248\u7684 <code>get*Attribute<\/code> \u65b9\u6cd5\u3002<\/p>\n<pre><code class=\"php\">public function commentable(): MorphTo\n{\n    return $this-&gt;morphTo();\n}    \n\npublic static function getActualClassNameForMorph($class)\n{\n    return match ((int) $class) {\n        1 =&gt; Post::class,\n        2 =&gt; Video::class,\n        default =&gt; parent::getActualClassNameForMorph($class),\n    };\n}\n\npublic function getCommentableTypeAttribute($value)\n{\n    return match ((int) $value) {\n        1 =&gt; Post::class,\n        2 =&gt; Video::class,\n        default =&gt; $value,\n    };\n}\n<\/code><\/pre>\n<p>\u73b0\u5728\uff0c\u5237\u65b0\u9875\u9762\uff0c\u4f60\u4f1a\u53d1\u73b0\u57fa\u672c\u5df2\u7ecf\u5b8c\u7f8e\u4e86\uff0c\u6211\u4eec\u6ca1\u6709\u6539\u53d8\u4efb\u4f55 Laravel \u5185\u90e8\u7684\u4ee3\u7801\uff0c\u53ea\u662f\u6539\u53d8\u4e86\u6211\u4eec\u7684\u6a21\u578b\u3002<\/p>\n<p>\u73b0\u5728\u53ef\u4ee5\u76f4\u63a5\u8bbf\u95ee commentable \uff0c\u4e5f\u53ef\u4ee5\u4f7f\u7528 with\/load<\/p>\n<p>\u5230\u6b64\u5c31\u5b8c\u7f8e\u4e86\u5417\uff1f<\/p>\n<p>\u4e0d\uff0c\u5e76\u6ca1\u6709<\/p>\n<p>\u4ed4\u7ec6\u89c2\u5bdf\uff0c\u4f60\u4f1a\u53d1\u73b0\u4e0a\u9762\u8fd9\u4e2a\u65b9\u6848\u8fd8\u5b58\u5728\u4e00\u4e2a\u5c0f\u5c0f\u7684\u95ee\u9898\uff0c\u90a3\u5c31\u662f\u6211\u4eec\u5fc5\u987b\u8981\u8986\u76d6 commentable_type \u7684\u8bfb\u51fa\u5b57\u6bb5\uff0c\u8fd9\u6837\u6211\u4eec\u5982\u679c\u9700\u8981\u5728\u63a5\u53e3\u8fd4\u56de\u65f6\uff0c\u5c31\u4f1a\u663e\u793a\u6210\u6211\u4eec\u8f6c\u6362\u540e\u7684\u7c7b\u540d\u4e86\uff0c\u800c\u4e0d\u662f\u539f\u59cb\u7684 1\/2\uff0c\u90a3\u4e48\u6709\u6ca1\u6709\u529e\u6cd5\u5462\uff0c\u5176\u5b9e\u662f\u6709\u7684\uff0c\u90a3\u5c31\u662f\u518d\u65b0\u5efa\u4e00\u4e2a commentTypeRef \u7684\u5b57\u6bb5\uff0c\u5728\u8fd9\u91cc\u9762\u8fd4\u56de\u539f\u59cb\u503c\uff0c\u73b0\u5728\u4f60\u7684 Comment \u6a21\u578b\u5e94\u8be5\u5c31\u4f1a\u50cf\u4e0b\u9762\u8fd9\u6837\u3002<\/p>\n<pre><code class=\"php\">&lt;?php\n\nnamespace App\/Models;\n\nuse Illuminate\/Database\/Eloquent\/Casts\/Attribute;\nuse Illuminate\/Database\/Eloquent\/Factories\/HasFactory;\nuse Illuminate\/Database\/Eloquent\/Model;\nuse Illuminate\/Database\/Eloquent\/Relations\/MorphTo;\n\nclass Comment extends Model\n{\n    use HasFactory;\n\n    protected $appends = ['commentable_type_ref'];\n\n    public static function getActualClassNameForMorph($class)\n    {\n        return match ((int) $class) {\n            1 =&gt; Post::class,\n            2 =&gt; Video::class,\n            default =&gt; parent::getActualClassNameForMorph($class),\n        };\n    }\n\n    public function commentable(): MorphTo\n    {\n        return $this-&gt;morphTo();\n    }\n\n    public function commentableType(): Attribute\n    {\n        return Attribute::get(fn($value) =&gt; match ((int) $value) {\n            1 =&gt; Post::class,\n            2 =&gt; Video::class,\n            default =&gt; $value,\n        });\n    }\n\n    public function commentableTypeRef(): Attribute\n    {\n        return Attribute::get(fn() =&gt; (int) $this-&gt;attributes['commentable_type']);\n    }\n\n\n}\n<\/code><\/pre>\n<p>\u73b0\u5728\u63a5\u53e3\u4f1a\u8fd4\u56de\u4e00\u4e2a <code>commentable_type_ref<\/code> \u5b57\u6bb5\uff0c\u6211\u8fd9\u91cc\u5077\u61d2\u4e86\uff0c\u76f4\u63a5\u8f6c\u4e3a int \u4e86\u3002<\/p>\n<p>\u5f88\u597d\uff0c\u4f46\u7f8e\u4e2d\u4e0d\u8db3\uff0c\u95ee\u9898\u867d\u7136\u89e3\u51b3\u4e86\uff0c\u4f46\u662f\u524d\u7aef\u539f\u6765\u7528\u6765\u5224\u65ad\u7684\u5b57\u6bb5\u53d8\u4e86\uff0c\u4e0d\u8fc7\u8fd9\u4e5f\u65e0\u4f24\u5927\u96c5\uff0c\u8ddf\u524d\u7aef\u53cb\u597d\u6c9f\u901a\u4e00\u4e0b\u5c31\u597d\u4e86\u3002<\/p>\n<p>\u5982\u679c\u4f60\u60f3\u66f4\u8fdb\u4e00\u6b65\uff0c\u90a3\u4e0d\u59a8\u7ee7\u7eed\u770b\u770b\u3002<\/p>\n<h3>\u66f4\u8fdb\u4e00\u6b65<\/h3>\n<p>\u5728\u4e0a\u9762\u7684\u5185\u5bb9\u4e2d\uff0c\u6211\u4eec\u57fa\u672c\u5df2\u7ecf\u89e3\u51b3\u4e86\u6211\u4eec\u7684\u9700\u6c42\uff0c\u53ea\u662f\u6709\u4e00\u4e9b\u5c0f\u7455\u75b5\u3002<\/p>\n<p>\u73b0\u5728\u6765\u601d\u8003\u4e00\u4e2a\u95ee\u9898\uff0c\u5728\u6211\u4eec\u521b\u5efa\u6a21\u578b\u5173\u8054\u7684\u65f6\u5019\uff0c\u4f7f\u7528\u5230\u7684\u5b57\u6bb5\uff0c\u662f\u5fc5\u987b\u8981\u6570\u636e\u5e93\u4e2d\u5b58\u5728\u7684\u5417\uff1f<\/p>\n<pre><code class=\"php\">&lt;?php\n\nnamespace App\/Models;\n\nuse Illuminate\/Database\/Eloquent\/Casts\/Attribute;\nuse Illuminate\/Database\/Eloquent\/Factories\/HasFactory;\nuse Illuminate\/Database\/Eloquent\/Model;\nuse Illuminate\/Database\/Eloquent\/Relations\/BelongsTo;\nuse Illuminate\/Database\/Eloquent\/Relations\/MorphMany;\n\nclass Post extends Model\n{\n    use HasFactory;\n\n    public function comments(): MorphMany\n    {\n        return $this-&gt;morphMany(Comment::class, 'commentable');\n    }\n\n    public function user(): BelongsTo\n    {\n        return $this-&gt;belongsTo(User::class, 'user_id');\n    }\n\n    public function userId(): Attribute\n    {\n        return Attribute::get(fn() =&gt; $this-&gt;id);\n    }\n}\n<\/code><\/pre>\n<p>\u5728\u8fd9\u91cc\uff0c\u6211\u4eec\u4e3a Post \u6a21\u578b\u521b\u5efa\u4e86\u4e00\u4e2a user \u7684\u5173\u7cfb\uff0c\u5982\u679c\u4f60\u67e5\u770b\u6700\u521d\u7684\u8868\u5b9a\u4e49\u4ee3\u7801\uff0c\u4f60\u4f1a\u53d1\u73b0\uff0cposts \u8868\u91cc\u9762\u5e76\u6ca1\u6709 user_id \u8fd9\u4e2a\u5b57\u6bb5\uff0c\u800c\u6211\u5374\u5728\u4e0b\u9762\u4f7f\u7528\u83b7\u53d6\u5176\u521b\u5efa\u4e86\u4e00\u4e2a user_id \u5b57\u6bb5\uff0c\u90a3\u8fd9\u6837\u80fd\u884c\u5417\uff1f<\/p>\n<p>\u7b54\u6848\u662f\u53ef\u884c\u7684\u3002<\/p>\n<pre><code class=\"diff\">Route::get('\/', function () {\n-    $comments = \/App\/Models\/Comment::limit(5)-&gt;get();\n-\n-    $comments-&gt;load('commentable');\n-    $comment = $comments-&gt;first();\n-    $commentable = $comment-&gt;commentable;\n-\n-    return $comments;\n-\n+    \n+    $post = \/App\/Models\/Post::with('user')-&gt;first();\n+\n+    return $post;\n});\n<\/code><\/pre>\n<pre><code class=\"json\">{\n    &quot;id&quot;: 1,\n    &quot;title&quot;: &quot;voluptatibus&quot;,\n    &quot;content&quot;: &quot;fugit&quot;,\n    &quot;created_at&quot;: &quot;2024-11-29T15:44:42.000000Z&quot;,\n    &quot;updated_at&quot;: &quot;2024-11-29T15:44:42.000000Z&quot;,\n    &quot;user&quot;: {\n        &quot;id&quot;: 1,\n        &quot;name&quot;: &quot;Test User&quot;,\n        &quot;email&quot;: &quot;test@example.com&quot;,\n        &quot;email_verified_at&quot;: &quot;2024-12-01T03:53:24.000000Z&quot;,\n        &quot;created_at&quot;: &quot;2024-12-01T03:53:24.000000Z&quot;,\n        &quot;updated_at&quot;: &quot;2024-12-01T03:53:24.000000Z&quot;\n    }\n}<\/code><\/pre>\n<p>\u6ca1\u9519\uff0c\u5b83\u53ef\u4ee5\u6b63\u786e\u7684\u52a0\u8f7d\u51fa user \u6765\uff0c\u5e76\u4e14\u8fd8\u53ef\u4ee5\u4f7f\u7528 with\/load \u548c\u76f4\u63a5\u8bbf\u95ee\u3002<\/p>\n<p>\u6709\u6ca1\u6709\u4e00\u70b9\u70b9\u7684\u60ca\u8bb6\uff0c\u8fd9\u4fbf\u662f\u89e3\u51b3\u524d\u9762\u8fd9\u4e2a\u95ee\u9898\u7684\u6240\u5728\u3002<\/p>\n<p>\u73b0\u5728\uff0c \u56de\u5230 Comment \u6a21\u578b\uff0c\u628a\u539f\u672c commentable \u91cc\u9762\u7684 morphTo \u53c2\u6570\u5b8c\u5584\u4e00\u4e0b,\uff0c\u540c\u65f6\u6e05\u7406\u6389\u4e0d\u518d\u9700\u8981\u7684 commentable_type_ref \u5427\uff0c\u73b0\u5728\u8ba9\u6211\u4eec\u7528\u56de\u4e4b\u524d\u7684\u6d4b\u8bd5\u4ee3\u7801\u3002<\/p>\n<pre><code class=\"diff\">-protected $appends = ['commentable_type_ref'];\n\n...\n\npublic function commentable(): MorphTo\n{\n-    return $this-&gt;morphTo();\n+    return $this-&gt;morphTo('commentable', 'commentable_type_class', 'commentable_id', 'id');\n}\n\n-public function commentableType(): Attribute\n+public function commentableTypeClass(): Attribute\n{\n-    return Attribute::get(fn($value) =&gt; match ((int) $value) {\n+    return Attribute::get(fn() =&gt; match ((int) $this-&gt;commentable_type) {\n        1 =&gt; Post::class,\n        2 =&gt; Video::class,\n-       default =&gt; $value,\n+       default =&gt; $this-&gt;commentable_type,\n    });\n}\n\n\n-public function commentableTypeRef(): Attribute\n-{\n-    return Attribute::get(fn() =&gt; (int) $this-&gt;attributes['commentable_type']);\n-}\n\n<\/code><\/pre>\n<p>\u5f97\u5230\u7ed3\u679c<\/p>\n<pre><code class=\"json\">[\n    {\n        &quot;id&quot;: 1,\n        &quot;commentable_type&quot;: &quot;1&quot;,\n        &quot;commentable_id&quot;: 5,\n        &quot;body&quot;: &quot;iste&quot;,\n        &quot;created_at&quot;: &quot;2024-11-29T15:48:28.000000Z&quot;,\n        &quot;updated_at&quot;: &quot;2024-11-29T15:48:28.000000Z&quot;,\n        &quot;commentable&quot;: {\n            &quot;id&quot;: 5,\n            &quot;title&quot;: &quot;sunt&quot;,\n            &quot;content&quot;: &quot;numquam&quot;,\n            &quot;created_at&quot;: &quot;2024-11-29T15:48:28.000000Z&quot;,\n            &quot;updated_at&quot;: &quot;2024-11-29T15:48:28.000000Z&quot;\n        }\n    }\n]<\/code><\/pre>\n<p>\u73b0\u5728\uff0c\u5b8c\u7f8e\u4e86\u6ca1\uff1f\u6211\u53ea\u60f3\u8bf4\uff0c \u8fd8\u5dee\u4e00\u70b9\u70b9~<\/p>\n<p>\u4e3a\u4e86\u540e\u9762\u7684\u6b65\u9aa4\u66f4\u6e05\u6670\uff0c\u6211\u5148\u6765\u88c5\u4e00\u4e2a <code>laravel-debugger<\/code><\/p>\n<pre><code>composer require barryvdh\/laravel-debugbar --dev<\/code><\/pre>\n<p>\u522b\u5fd8\u4e86\u5728 <code>.env<\/code> \u4e2d\u6dfb\u52a0\u914d\u7f6e\u9879\u4ee5\u542f\u7528<\/p>\n<pre><code>DEBUGBAR_ENABLED=true<\/code><\/pre>\n<p>\u55f7\uff0c\u73b0\u5728\u4f60\u8bbf\u95ee\u63a5\u53e3\u5e94\u8be5\u4e0d\u4f1a\u770b\u5230 laravel-debugger\uff0c\u8fd9\u662f\u56e0\u4e3a\u4ed6\u4e0d\u4f1a\u5bf9 JSON \u54cd\u5e94\u751f\u6548\uff0c\u5982\u679c\u60f3\u8981\u770b\u5230\uff0c\u53ef\u4ee5\u968f\u4fbf\u8bbf\u95ee\u4e00\u4e2a 404 \u9875\u9762\uff0c\u7136\u540e\u5c31\u80fd\u770b\u5230\u90a3\u4e2a\u719f\u6089\u7684 icon \u4e86\uff0c\u7136\u540e\u70b9\u51fb icon\uff0c\u518d\u70b9\u51fb\u53f3\u4e0a\u89d2\u7684\u4ece\u53f3\u81f3\u5de6\u7b2c\u4e09\u4e2a\u56fe\u6807\uff08\u6253\u5f00\u6587\u4ef6\uff09\uff0c\u9009\u62e9\u5176\u4ed6\u9875\u9762\u7684\u8bf7\u6c42\u3002<\/p>\n<p><img decoding=\"async\" width=\"723\" height=\"375\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdfbpQ\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<p>\u73b0\u5728\uff0c\u628a\u6211\u4eec\u7684\u6d4b\u8bd5\u4ee3\u7801\u6539\u6210\u4e0b\u9762\u8fd9\u6837<\/p>\n<pre><code class=\"php\">Route::get('\/', function () {\n    $comments = \/App\/Models\/Comment::limit(1)-&gt;get();\n    $comment = $comments-&gt;first();\n\n    return $comment-&gt;commentable;\n});<\/code><\/pre>\n<p>\u7136\u540e\u4f60\u5c31\u5f97\u5230\u4e86\u7ed3\u679c<\/p>\n<pre><code class=\"json\">{\n    &quot;id&quot;: 5,\n    &quot;commentable_type&quot;: &quot;1&quot;,\n    &quot;commentable_id&quot;: 5,\n    &quot;body&quot;: &quot;reprehenderit&quot;,\n    &quot;created_at&quot;: &quot;2024-11-29T15:48:28.000000Z&quot;,\n    &quot;updated_at&quot;: &quot;2024-11-29T15:48:28.000000Z&quot;\n}<\/code><\/pre>\n<p>\u662f\u7684\uff0c\u4f60\u6ca1\u6709\u770b\u9519\u2026\u2026\uff0c\u8fd9\u91cc\u660e\u660e\u8fd4\u56de\u7684\u662f commentable\uff0c\u4e5f\u5c31\u662f\u539f\u672c\u5e94\u8be5\u8fd4\u56de Post \u6216\u8005 Video \u7684\uff0c\u8fd9\u91cc\u5374\u8c8c\u4f3c\u8fd4\u56de\u4e86 comments.id = 5 \u7684\u6570\u636e\uff0c\u6709\u4e9b\u79bb\u8c31\u5427\u3002\u3002\u3002<\/p>\n<p><img decoding=\"async\"   referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/remote\/1460000045525586\" alt=\" title=\"\u591a\u6001\u5173\u8054\u7684\u6a21\u578b\u672c\u5730\u5316\u5957\u7528.assetsimage-20241201122814943.png\"\" title=\" title=\"loading=lazy><\/p>\n<p>\u8fd8\u8bb0\u5f97\u6211\u4eec\u524d\u9762\u63d0\u5230\u7684 <code>morphTo<\/code> \u65b9\u6cd5\u5417\uff1f\u8fd9\u91cc\u4e5f\u4f1a\u8d70\u5230\u7684\u5594\uff0c\u4ed6\u4f1a\u4f7f\u7528 <code>getAttributeFromArray<\/code> \u6765\u83b7\u53d6 <code>$attributes<\/code> \u5c5e\u6027\u4e0a\u7684\u5b57\u6bb5\u6765\u5224\u65ad\uff08\u5728\u8fd9\u91cc\u7406\u8bba\u4e0a\u662f\u6570\u636e\u5e93\u4e2d\u7684\u5b57\u6bb5\uff09\uff0c\u5982\u679c\u83b7\u53d6\u5230\u4e86\uff0c\u4ed6\u4f1a\u8c03\u7528 <code>morphInstanceTo<\/code>\uff0c\u53cd\u4e4b\u4ed6\u5219\u8ba4\u4e3a\u8fd9\u662f\u4e00\u4e2a\u6765\u81ea <code>with<\/code>\u7684\u8c03\u7528\uff0c\u7ee7\u800c\u8c03\u7528 <code>morphEagerTo<\/code><\/p>\n<p>\u800c\u6211\u4eec\u8fd9\u91cc\u7684 <code>commentable_type_class<\/code> \u5176\u5b9e\u662f\u865a\u6784\u800c\u6765\u7684\uff0c\u5b83\u5e76\u4e0d\u5b58\u5728\u4e8e\u6570\u636e\u5e93\u4e2d\u7684\u771f\u5b9e\u5b57\u6bb5\uff0c\u81ea\u7136\uff0c\u8fd9\u91cc\u83b7\u53d6\u51fa\u6765\u7684\u5c31\u6210\u4e86\u7a7a\uff0c\u8fdb\u5165\u4e86\u9884\u52a0\u8f7d\u7684\u903b\u8f91\uff0c\u800c\u5b9e\u9645\u4e0a\u6211\u4eec\u5176\u5b9e\u662f\u5728\u76f4\u63a5\u8bbf\u95ee\u672a\u9884\u52a0\u8f7d\u7684\u6570\u636e\uff0c\u5c31\u5bfc\u81f4\u4e86\u8fd9\u4e2a\u9519\u8bef\u3002<\/p>\n<p>\u5982\u4f55\u4fee\u590d\u8fd9\u4e2a\u95ee\u9898\uff1f\u65e2\u7136\uff0c\u6211\u4eec\u9700\u8981\u7ed9\u6570\u636e\u5e93\u8fd4\u56de\u7684\u7ed3\u679c\u6dfb\u52a0\u4e00\u4e2a\u5b57\u6bb5\uff0c\u90a3\u5728 select \u7684\u65f6\u5019\uff0c\u5904\u7406\u4e00\u4e0b\u4e0d\u5c31\u597d\u4e86\u5417\uff1f<\/p>\n<pre><code class=\"php\">Route::get('\/', function () {\n    $comments = \/App\/Models\/Comment::select(['*', DB::raw(&quot;CASE\n        WHEN commentable_type = 1 THEN '\/\/App\/\/Models\/\/Post'\n        WHEN commentable_type = 2 THEN '\/\/App\/\/Models\/\/Video'\n        ELSE commentable_type\n    END AS commentable_type_class&quot;)])-&gt;limit(1)-&gt;get();\n    $comment = $comments-&gt;first();\n\n    return $comment-&gt;commentable;\n});\n<\/code><\/pre>\n<p>\u786e\u5b9e\uff0c\u6211\u4eec\u901a\u8fc7\u8fd9\u6837\u89e3\u51b3\u4e86\u524d\u9762\u7684 bug\uff0c\u5b9e\u73b0\u6211\u4eec\u7684\u9700\u6c42\uff0c\u53ea\u662f\u4ee3\u7801\u770b\u8d77\u6765\u6709\u4ebf\u70b9\u70b9\u7cdf\u7cd5 \ud83e\udd14<\/p>\n<p>\u4ec0\u4e48\uff1f\u8fd8\u6709\u9ad8\u624b\uff01<\/p>\n<h3>\u6700\u7ec8\u65b9\u6848<\/h3>\n<p>\u5176\u5b9e\u53c2\u8003\u524d\u9762\u7684\u5185\u5bb9\u4e0d\u96be\u53d1\u73b0\uff0c\u6211\u4eec\u524d\u9762\u90fd\u5b8c\u6210\u4e86\uff0c\u53ea\u662f\uff0c\u5728\u6700\u540e\u4e00\u90e8\uff0c\u9700\u8981\u5411 <code>$attributes<\/code> \u6dfb\u52a0\u5b57\u6bb5\u8fd9\u91cc\u5361\u4f4f\u4e86\uff0c\u90a3\u4e48\uff0c\u6709\u6ca1\u6709\u4ec0\u4e48\u65b9\u6cd5\uff0c\u53ef\u4ee5\u8ba9\u6211\u4eec\u5728 <code>$attributes<\/code> \u4e0a\u6dfb\u52a0\u5b57\u6bb5\u5462\uff0c\u7b54\u6848\u662f\u6709\u7684\u3002<\/p>\n<p>\u4f60\u53ef\u80fd\u4f1a\u60f3\u5230\uff0c\u5982\u679c\u53ea\u662f\u5f80\u4e0a\u9762\u6dfb\u52a0\u4e00\u4e2a\u5b57\u6bb5\uff0c\u90a3\u76f4\u63a5\u8986\u76d6\u6a21\u578b\u7684 boot \u65b9\u6cd5\u7136\u540e\u7ed9 <code>$attributes<\/code> \u8ffd\u52a0\u4e00\u4e2a\u4e0d\u5c31\u597d\u4e86\u3002<\/p>\n<p>\u4f46\u662f\uff0c\u90a3\u8fd8\u662f\u53ef\u80fd\u4f1a\u5f71\u54cd\u5230\u4e0a\u9762\u7684 morphTo \u65b9\u6cd5\uff0c\u6240\u4ee5\uff0c\u6211\u4eec\u7684\u6700\u7ec8\u76ee\u7684\u662f\uff0c\u8981\u627e\u5230\u4e00\u4e2a\u5408\u9002\u7684\u65f6\u673a\u53bb\u6dfb\u52a0\uff0c\u5e76\u4e14\u8fd8\u8981\u5c3d\u53ef\u80fd\u7684\u8003\u8651\u53ef\u80fd\u5e26\u6765\u7684\u5176\u4ed6\u95ee\u9898\u3002<\/p>\n<p>\u800c Laravel \u7684\u6a21\u578b\u4e2d\u6070\u597d\u6709\u8fd9\u4e00\u7c7b\u4e0d\u540c\u65f6\u673a\u8c03\u7528\u7684\u65b9\u6cd5\uff0c\u90a3\u5c31\u662f\u6a21\u578b\u4e8b\u4ef6\u3002<\/p>\n<h4>\u9009\u62e9\u4e00\u4e2a\u5408\u9002\u7684\u6a21\u578b\u4e8b\u4ef6<\/h4>\n<p>\u6253\u5f00 Laravel \u6587\u6863\uff0c\u53ef\u4ee5\u770b\u5230\u6a21\u578b\u6709\u4ee5\u4e0b\u4e8b\u4ef6\u3002<\/p>\n<table>\n<thead>\n<tr>\n<th>\u4e8b\u4ef6\u540d\u79f0<\/th>\n<th>\u89e6\u53d1\u65f6\u673a<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>retrieved<\/code><\/td>\n<td>\u5f53\u6a21\u578b\u5b9e\u4f8b\u4ece\u6570\u636e\u5e93\u4e2d\u68c0\u7d22\u51fa\u6765\u65f6\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>creating<\/code><\/td>\n<td>\u5728\u4fdd\u5b58\u6a21\u578b\u4e4b\u524d\u89e6\u53d1\uff08\u521b\u5efa\u65b0\u8bb0\u5f55\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>created<\/code><\/td>\n<td>\u5728\u6a21\u578b\u6210\u529f\u4fdd\u5b58\u5230\u6570\u636e\u5e93\u540e\u89e6\u53d1\uff08\u65b0\u8bb0\u5f55\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>updating<\/code><\/td>\n<td>\u5728\u66f4\u65b0\u73b0\u6709\u6a21\u578b\u65f6\uff0c\u6570\u636e\u88ab\u63d0\u4ea4\u5230\u6570\u636e\u5e93\u4e4b\u524d\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>updated<\/code><\/td>\n<td>\u5728\u6a21\u578b\u6210\u529f\u66f4\u65b0\u540e\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>saving<\/code><\/td>\n<td>\u5728\u4fdd\u5b58\u6a21\u578b\u4e4b\u524d\u89e6\u53d1\uff08\u5305\u62ec\u521b\u5efa\u548c\u66f4\u65b0\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>saved<\/code><\/td>\n<td>\u5728\u6a21\u578b\u6210\u529f\u4fdd\u5b58\u540e\u89e6\u53d1\uff08\u5305\u62ec\u521b\u5efa\u548c\u66f4\u65b0\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>deleting<\/code><\/td>\n<td>\u5728\u5220\u9664\u6a21\u578b\u4e4b\u524d\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>deleted<\/code><\/td>\n<td>\u5728\u6a21\u578b\u6210\u529f\u5220\u9664\u540e\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>trashed<\/code><\/td>\n<td>\u5f53\u6a21\u578b\u88ab\u8f6f\u5220\u9664\uff08\u5373 <code>delete()<\/code>\uff09\u65f6\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>forceDeleting<\/code><\/td>\n<td>\u5728\u5f3a\u5236\u5220\u9664\uff08\u5373 <code>forceDelete()<\/code>\uff09\u4e4b\u524d\u89e6\u53d1\uff08\u8df3\u8fc7\u8f6f\u5220\u9664\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>forceDeleted<\/code><\/td>\n<td>\u5728\u5f3a\u5236\u5220\u9664\u540e\u89e6\u53d1\uff08\u8df3\u8fc7\u8f6f\u5220\u9664\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>restoring<\/code><\/td>\n<td>\u5728\u6062\u590d\u8f6f\u5220\u9664\u7684\u6a21\u578b\u65f6\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>restored<\/code><\/td>\n<td>\u5728\u6062\u590d\u8f6f\u5220\u9664\u7684\u6a21\u578b\u6210\u529f\u540e\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<tr>\n<td><code>replicating<\/code><\/td>\n<td>\u5728\u590d\u5236\u6a21\u578b\u5b9e\u4f8b\uff08\u4f7f\u7528 <code>replicate()<\/code>\uff09\u65f6\u89e6\u53d1\u3002<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u770b\u5230\u4ee5\u4e0a\u8868\u683c\uff0c\u4f60\u5e94\u8be5\u4e00\u773c\u5c31\u770b\u5230\u4e86 <code>retrieved<\/code> \u4e8b\u4ef6\uff0c\u662f\u7684\uff0c\u6ca1\u9519\uff0c\u6211\u4eec\u5c31\u9700\u8981\u5728\u6a21\u578b\u4ece\u6570\u636e\u5e93\u4e2d\u88ab\u68c0\u7d22\u51fa\u6765\u7684\u65f6\u5019\u53bb\u5904\u7406\uff0c\u73b0\u5728\u6539\u5199\u6211\u4eec\u7684 Comment \u6a21\u578b\u4ee3\u7801\u3002<\/p>\n<pre><code class=\"php\">&lt;?php\n\nnamespace App\/Models;\n\nuse Illuminate\/Database\/Eloquent\/Factories\/HasFactory;\nuse Illuminate\/Database\/Eloquent\/Model;\nuse Illuminate\/Database\/Eloquent\/Relations\/MorphTo;\n\nclass Comment extends Model\n{\n    use HasFactory;\n\n    protected static function booted()\n    {\n        parent::booted();\n\n        self::retrieved(function (Comment $comment) {\n            $comment-&gt;attributes['commentable_type_class'] = match ((int) $comment-&gt;commentable_type) {\n                1 =&gt; Post::class,\n                2 =&gt; Video::class,\n                default =&gt; $comment-&gt;commentable_type,\n            };\n\n            $comment-&gt;makeHidden(['commentable_type_class']);\n        });\n    }\n\n\n    public function commentable(): MorphTo\n    {\n        return $this-&gt;morphTo('commentable', 'commentable_type_class', 'commentable_id', 'id');\n    }\n\n}\n<\/code><\/pre>\n<p>\u9996\u5148\uff0c\u5148\u8986\u76d6\u6389 booted \u65b9\u6cd5\uff0c\u5e76\u8c03\u7528 <code>parent::booted()<\/code>\uff0c\u7136\u540e\u5f00\u59cb\u6211\u4eec\u7684\u903b\u8f91\u3002<\/p>\n<p>\u5728 <code>retrieved<\/code> \u65f6\uff0c\u6211\u4eec\u4fee\u6539\u4f20\u5165\u7684 Comment \u6a21\u578b\uff0c\u5411\u5176 <code>$attributes<\/code> \u4e0a\u6dfb\u52a0\u4e00\u4e2a <code>comment_type_class<\/code><\/p>\n<p>\u4e0e\u6b64\u540c\u65f6\uff0c\u56e0\u4e3a\u6211\u4eec\u5e76\u4e0d\u5e0c\u671b\u8fd9\u4e2a\u5b57\u6bb5\u8fd4\u56de\u5230\u6211\u4eec\u7684\u54cd\u5e94\u4e2d\uff0c\u6240\u4ee5\u6211\u4eec\u4f7f\u7528\u4e86 <code>makeHidden<\/code>\uff0c\u5c06\u5176\u9690\u85cf\u3002<\/p>\n<p>\u73b0\u5728\u8fd8\u6709\u4e00\u4e2a\u5c0f\u95ee\u9898\uff0c\u5c31\u662f\uff0c\u5982\u679c\u6211\u4eec\u7684 comment \u8bbe\u7f6e\u4e86 <code>$fillable<\/code> \u548c <code>$guarded<\/code> \u90fd\u662f <code>[]<\/code> \u7684\u65f6\u5019\uff0c\u5c31\u4f1a\u51fa\u95ee\u9898\u3002<\/p>\n<pre><code class=\"text\">SQLSTATE[HY000]: General error: 1 no such column: commentable_type_class (Connection: sqlite, SQL: update &quot;comments&quot; set &quot;commentable_type_class&quot; = App\/Models\/Post, &quot;updated_at&quot; = 2024-12-01 04:57:01 where &quot;id&quot; = 1)<\/code><\/pre>\n<p>\u8fd9\u4e2a\u95ee\u9898\u4e5f\u5f88\u597d\u89e3\u51b3\uff0c\u67e5\u770b\u4e0a\u9762\u7684\u4e8b\u4ef6\u8868\u683c\uff0c\u4f60\u4f1a\u53d1\u73b0\uff0csaving\uff0c\u4f1a\u5728\u521b\u5efa\u548c\u4fdd\u5b58\u524d\u6267\u884c\uff0c\u6240\u4ee5\u6211\u4eec\u53ea\u9700\u8981\u5728\u8fd9\u91cc\u518d unset \u6389\u521a\u521a\u6dfb\u52a0\u7684\u5c5e\u6027\uff0c\u5c31\u597d\u4e86\u3002<\/p>\n<pre><code class=\"php\">self::saving(function (Comment $comment) {\n    unset($comment-&gt;attributes['commentable_type_class']);\n});<\/code><\/pre>\n<p>\u81f3\u6b64\uff0c\u6211\u4eec\u7684\u76ee\u7684\u5df2\u7ecf\u8fbe\u6210\uff0c\u9996\u5148\uff0c\u6211\u4eec\u6ca1\u6709\u7834\u574f\u539f\u672c\u7684 <code>commentable_type<\/code>\u3001\u5176\u6b21\uff0c\u6211\u4eec\u4e5f\u6ca1\u6709\u7834\u574f Laravel \u5185\u90e8\u4efb\u4f55\u4e1c\u897f\uff0c\u751a\u81f3\uff0c\u5982\u679c\u4f60\u4e00\u4e2a\u6a21\u578b\u4e2d\u6709\u591a\u4e2a\u591a\u6001\uff0c\u4e5f\u53ef\u4ee5\u5982\u6b64\u70ae\u5236\u3002<\/p>\n<p>\u5b8c\u6574\u7684 Comment \u6a21\u578b\u5982\u4e0b\u3002<\/p>\n<pre><code class=\"php\">&lt;?php\n\nnamespace App\/Models;\n\nuse Illuminate\/Database\/Eloquent\/Factories\/HasFactory;\nuse Illuminate\/Database\/Eloquent\/Model;\nuse Illuminate\/Database\/Eloquent\/Relations\/MorphTo;\n\nclass Comment extends Model\n{\n    use HasFactory;\n\n    protected static function booted()\n    {\n        parent::booted();\n\n        self::retrieved(function (Comment $comment) {\n            $comment-&gt;attributes['commentable_type_class'] = match ((int) $comment-&gt;commentable_type) {\n                1 =&gt; Post::class,\n                2 =&gt; Video::class,\n                default =&gt; $comment-&gt;commentable_type,\n            };\n\n            $comment-&gt;makeHidden(['commentable_type_class']);\n        });\n\n        self::saving(function (Comment $comment) {\n            unset($comment-&gt;attributes['commentable_type_class']);\n        });\n    }\n\n\n    public function commentable(): MorphTo\n    {\n        return $this-&gt;morphTo('commentable', 'commentable_type_class', 'commentable_id', 'id');\n    }\n\n}<\/code><\/pre>\n<h3>\u7ed3\u675f<\/h3>\n<p>\u5176\u5b9e\uff0c\u8fd9\u4e2a\u5b9e\u73b0\u8fd8\u662f\u6709\u4e00\u4e9b\u5c0f\u95ee\u9898\uff0c\u56e0\u4e3a Laravel \u5185\u90e8\u591a\u6001\u8bbe\u8ba1\u7684\u539f\u56e0\uff0c\u5728\u4ee5\u4e0a\u7684\u89e3\u51b3\u65b9\u6848\u4e2d\uff0c\u4f60\u5c06\u65e0\u6cd5\u4f7f\u7528 <code>hasMorph <\/code> \u548c <code>whereHasMorph<\/code> \u7b49\u76f8\u5173\u65b9\u6cd5\uff0c\u8fd9\u8bf4\u8d77\u6765\u6709\u4e00\u4e9b\u590d\u6742\uff0c\u6240\u4ee5\uff0c\u5982\u679c\u4f60\u9700\u8981\u7528\u5230\u8fd9\u4e24\u4e2a\u65b9\u6cd5\uff0c\u90a3\u4e48\u5f88\u9057\u61be\uff0c\u8fd9\u4e2a\u65b9\u6848\u5e76\u4e0d\u9002\u7528\u4e8e\u4f60\uff0c\u4f60\u5e94\u8be5\u8003\u8651\u4ece\u65b0\u8c03\u6574\u6570\u636e\u5e93\u7684\u8bbe\u8ba1\uff0c\u4ee5\u9002\u914d Laravel \u7684\u591a\u6001\u5173\u8054\u3002<\/p>\n<p>\u5bf9\u6b64\uff0c\u5982\u679c\u4f60\u7684\u6570\u636e\u91cf\u4e0d\u662f\u5f88\u5927\uff0c\u6211\u8fd8\u662f\u5f88\u5efa\u8bae\u4f60\u5c3d\u65e9\u8c03\u6574\u4f60\u7684\u6570\u636e\u5e93\u8bbe\u8ba1\uff0c\u4f7f\u5176\u7b26\u5408 Laravel \u7684\u89c4\u8303\u8981\u6c42\uff0c\u800c\u4e0d\u662f\u50cf\u8fd9\u6837\u53bb\u5904\u7406\u5b83\uff0c\u6bd5\u7adf\u8fd9\u4e2a\u65b9\u6848\uff0c\u53ef\u80fd\u8fd8\u5b58\u5728\u4e00\u4e9b\u6211\u6ca1\u6709\u9884\u6599\u5230\u7684\u95ee\u9898\uff0c\u4f46\u662f\u6211\u5df2\u7ecf\u5c3d\u53ef\u80fd\u7684\u53bb\u9a8c\u8bc1\u4e86\u3002<\/p>\n<h3>\u6ce8\u8a00<\/h3>\n<p>\u6ce81\uff1a\u8fd9\u4e2a\u65b9\u6848\u5e94\u8be5\u9002\u7528\u4e8e Laravel 6.x\uff08\u542b\uff09\u4ee5\u540e\u7684\u7248\u672c\uff0c\u4f46\u6211\u672a\u4f5c\u8fc7\u591a\u7684\u6d4b\u8bd5<\/p>\n<p>\u56fe\u6ce8\uff1a\u4f60\u5e94\u8be5\u6ce8\u610f\u5230\u4e86\u91cc\u9762\u6709\u5f88\u591a\u7684\u56fe\u7247\u751f\u6210\uff0c\u8fd9\u4e9b\u90fd\u662f\u4f7f\u7528\u7684 Markdown \u7684 mermaid \u6269\u5c55\u4ee3\u7801\u5757\u6765\u6e32\u67d3\u7684\uff0c\u8fd9\u4e9b\u8c03\u7528\u6808\u90fd\u662f\u4f7f\u7528\u7684 PHPStorm \u7684 <code>Navigate<\/code> \u4e0b\u7684 <code>Call Hierarchy<\/code>\uff0c\u7136\u540e\u5bfc\u51fa\u6587\u672c\uff0c\u7136\u540e\u4ea4\u7ed9 ChatGPT \u6765\u751f\u6210\u5bf9\u5e94\u7684 mermaid \u56fe\u5f62\uff0c\u63d0\u793a\u8bcd\u5982\u4e0b\uff1a<\/p>\n<pre><code class=\"text\">1\u3001\u7cbe\u7b80\u4ee5\u4e0b\u6570\u636e\u5185\u5bb9\uff0c\u6bd4\u5982\u8fc7\u4e8e\u91cd\u590d\u7684\u8def\u5f84\u524d\u7f00\n2\u3001\u4f7f\u7528 markdown \u652f\u6301\u7684\u56fe\u5f62\u8bed\u6cd5\uff0c\u9009\u62e9\u5408\u9002\u7684\u56fe\u5f62\uff0c\u5e76\u751f\u6210\u539f\u59cb\u7684 markdown \u5185\u5bb9\u3002<\/code><\/pre>\n<p><img decoding=\"async\" width=\"723\" height=\"997\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVdfbpR\" alt=\"image.png\" title=\"image.png\" loading=\"lazy\"><\/p>\n<p>\u6ce82\uff1a\u3001\u4e0a\u9762\u7684\u6570\u636e\u5e93\u793a\u4f8b\u8868\u7ed3\u6784\uff0c\u4e5f\u662f\u7531 ChatGPT \u521b\u5efa\u7684\u8fc1\u79fb\u6a21\u578b\u6765\u5b9e\u73b0\u7684\uff0c\u4f46\u662f\u6570\u636e\u7684 Seeder \u662f\u7531 Laravel Idea \u751f\u6210\u7684\u3002<\/p>\n<h3>Creative Commons 4.0 \u6388\u6743\u534f\u8bae (CC BY 4.0)<\/h3>\n<p>\u6b64\u4f5c\u54c1\u91c7\u7528 <a href=\"https:\/\/link.segmentfault.com\/?enc=Gdvv%2FnNh28XZUbDTf8ZgcQ%3D%3D.UThEiAdnqC6fn50mgcm%2FXdrSkxBnufqhfpbJh%2FzfJN3ekYoundz9B3WV9fm%2BYKAmKK%2BREJked8k%2BeG5koBz3cQ%3D%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Creative Commons \u7f72\u540d 4.0 \u56fd\u9645\u8bb8\u53ef\u534f\u8bae<\/a> \u8fdb\u884c\u8bb8\u53ef\u3002<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000045525584\">https:\/\/segmentfault.com\/a\/1190000045525584<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Laravel \u591a\u6001\u5173\u8054\u7684\u6a21\u578b\u672c\u5730\u5316\u5957\u7528 \u524d\u8a00 \u5728\u9879\u76ee\u4e2d\uff0c\u4e00\u822c\u60c5\u51b5\u4e0b\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u5355\u4e2a\u5b57\u6bb5\u6765\u521b\u5efa\u4e00\u4e2a\u4e00\u5bf9\u4e00\u6216\u8005 [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10020430","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10020430","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10020430"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10020430\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10020430"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10020430"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10020430"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}