{"id":2511,"date":"2015-06-20T11:45:41","date_gmt":"2015-06-20T03:45:41","guid":{"rendered":"http:\/\/blog.turn.tw\/?p=2511"},"modified":"2015-06-20T11:45:41","modified_gmt":"2015-06-20T03:45:41","slug":"%e8%83%96%e8%83%96-model-%e7%9a%84%e6%b8%9b%e9%87%8d%e6%96%b9%e6%b3%95%ef%bc%9apresenter","status":"publish","type":"post","link":"https:\/\/blog.turn.tw\/?p=2511","title":{"rendered":"\u80d6\u80d6 Model \u7684\u6e1b\u91cd\u65b9\u6cd5\uff1aPresenter"},"content":{"rendered":"<p>\u958b\u767capplication\u6642\uff0c\u5e38\u5e38\u6703\u6709\u5927\u91cf\u7684\u5448\u73fe\uff08presentation\uff09\u908f\u8f2f\u3002<\/p>\n<p>\u50cf\u662f\u65e5\u671f\u683c\u5f0f\u3001\u91d1\u984d\u683c\u5f0f\uff08\u662f\u5426\u7a7f\u63d2\u9017\u865f\uff09\u3001\u540d\u7a31\uff08\u662f\u5426\u9700\u8981\u5927\u5beb\uff09\u7b49\u7b49\u3002<\/p>\n<p>\u628a\u9019\u4e9blogic\u5beb\u5728model\u7684\u8a71\uff0c\u5f88\u5bb9\u6613\u5c31\u6703\u5c0e\u81f4model\u904e\u80d6\u3002<\/p>\n<p>\u8209\u4f8b\u4f86\u8aaa\uff0c\u5982\u679c\u6587\u7ae0model\u5728\u4e0d\u540c\u5730\u65b9\u9700\u8981\u5448\u73fe\u65e5\u671f\u3001\u65e5\u671f\u6642\u9593\u3001\u897f\u65b9\u683c\u5f0f\u3001\u53f0\u7063\u683c\u5f0f\uff0c<\/p>\n<p>model\u5c31\u6703\u9577\u9019\u6a23\uff08\u4ee5Laravel Eloquent\u8209\u4f8b\uff09\uff1a<\/p>\n<pre>\r\nclass Article extends Eloquent\r\n{\r\n    public function getDate(){\/*...*\/}\r\n\r\n    \/\/ \u5448\u73fe\u7d66\u53f0\u7063\u5730\u5340\u7684\u6642\u9593\u683c\u5f0f\r\n    public function getTaiwaneseDateTime(){\/*...*\/}\r\n\r\n    \/\/ \u5448\u73fe\u7d66\u6b50\u7f8e\u5730\u5340\u7684\u6642\u9593\u683c\u5f0f\r\n    public function getWesternDateTime(){\/*...*\/}\r\n\r\n    public function getTaiwaneseDate(){\/*...*\/}\r\n\r\n    public function getWesternDate(){\/*...*\/}\r\n}\r\n<\/pre>\n<p>\u8981\u5c07\u9019\u985epresentation logic\u62bd\u51fa\u4f86\uff0c\u8a31\u591a\u6846\u67b6\u63a1\u7528\u4e86\u300chelper function\u300d\u7684\u4f5c\u6cd5\uff0c<\/p>\n<p>\u4e5f\u5c31\u662f\u5b9a\u7fa9\u597d\u5e7e\u500bfunctions\u7528\u4f86\u8655\u7406\u5448\u73fe\u908f\u8f2f\u3002<\/p>\n<p>\u9664\u4e86helpers\u7684\u4f5c\u6cd5\u4e4b\u5916\uff0c\u9084\u6709\u4e00\u500b\u975e\u5e38\u7c21\u55ae\u6709\u6548\u7684\u65b9\u6cd5\u3002<\/p>\n<p>\u4e5f\u5c31\u662f\u4f7f\u7528Decorator pattern\u4f86\u5c01\u88dd\u51fapresenter\uff0c\u50cf\u9019\u6a23\uff1a<\/p>\n<pre>\r\nclass ArticlePresenter\r\n{\r\n    protected $article;\r\n\r\n    public function __construct(Article $article)\r\n    {\r\n        $this->article = $article;\r\n    }\r\n\r\n    \/\/ \u5448\u73fe\u7d66\u53f0\u7063\u5730\u5340\u7684\u6642\u9593\u683c\u5f0f\r\n    public function getTaiwaneseDateTime(){\r\n        return date('Y-m-d', $this->article->created_at);\r\n    }\r\n\r\n    \/\/ \u5448\u73fe\u7d66\u6b50\u7f8e\u5730\u5340\u7684\u6642\u9593\u683c\u5f0f\r\n    public function getWesternDateTime(){\/*...*\/}\r\n\r\n    public function getTaiwaneseDate(){\/*...*\/}\r\n\r\n    public function getWesternDate(){\/*...*\/}\r\n}\r\n<\/pre>\n<p>\u6982\u5ff5\u4e0a\u53ea\u662f\u628a\u539f\u672c\u7684model\u5f9econstructor\u50b3\u9032\u53bb\uff0c\u539f\u672c\u7684function\u642c\u904e\u53bb\uff0c<\/p>\n<p>\u628a$this\u6539\u5beb\u6210$this->article\u5373\u53ef\u3002<\/p>\n<p>\u7136\u800c\uff0c\u9019\u6a23\u6703\u5c0e\u81f4view\u88e1\u9762\u9700\u8981\u521d\u59cb\u5316\u7269\u4ef6\uff1a<\/p>\n<pre>\r\n@foreach($articles as $article)\r\n    <?php $presenter = new ArticlePresenter($article); ?>\r\n    \u767c\u6587\u65e5\u671f\uff1a{{ $presenter->getTaiwaneseDate() }}\r\n\uff20endforeach\r\n<\/pre>\n<p>\u5728view\u88e1\u9762\u505a\u9019\u7a2e\u4e8b\uff0c\u600e\u9ebc\u770b\u90fd\u662f\u5f88\u919c\u7684\u3002<\/p>\n<p>\u591a\u5beb\u4e00\u500bfunction\u5373\u53ef\u6539\u5584\uff1a<\/p>\n<pre>\r\nclass Article extends Eloquent\r\n{\r\n    public function present()\r\n    {\r\n        return new ArticlePresenter($this);\r\n    }\r\n}\r\n<\/pre>\n<p>view\u5167\u6703\u8b8a\u6210\u9019\u6a23\uff1a<\/p>\n<pre>\r\n@foreach($articles as $article)\r\n    \u767c\u6587\u65e5\u671f\uff1a{{ $article->present()->getTaiwaneseDate() }}\r\n\uff20endforeach\r\n<\/pre>\n<p>\u65b0\u7684\u554f\u984c\u4f86\u4e86\uff1a\u591a\u6b21\u547c\u53ebpresent\u6703\u6d6a\u8cbb\u8a18\u61b6\u9ad4\u3002<\/p>\n<p>\u53ef\u4ee5\u9019\u6a23\u6539\u5584\uff1a<\/p>\n<pre>\r\nclass Article extends Eloquent\r\n{\r\n\tprotected $presenterInstance;\r\n\r\n\tpublic function present()\r\n\t{\r\n\t\tif ( ! $this->presenterInstance)\r\n\t\t{\r\n\t\t\t$this->presenterInstance = new ArticlePresenter($this);\r\n\t\t}\r\n\r\n\t\treturn $this->presenterInstance;\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>\u591a\u500bmodel\u90fd\u4f7f\u7528presenter\u7684\u8a71\uff0c\u9019\u6bb5code\u6703\u91cd\u8907\u3002\u5584\u7528PHP trait\u53ef\u4ee5\u89e3\u6c7a\u9019\u500b\u554f\u984c\uff1a<\/p>\n<pre>\r\ntrait PresentableTrait {\r\n\r\n\tprotected $presenterInstance;\r\n\r\n\tpublic function present()\r\n\t{\r\n                \/\/ ...\r\n\r\n\t\tif ( ! $this->presenterInstance)\r\n\t\t{\r\n\t\t\t$this->presenterInstance = new $this->presenter($this);\r\n\t\t}\r\n\r\n\t\treturn $this->presenterInstance;\r\n\t}\r\n\r\n} \r\n<\/pre>\n<p>Laravel\u793e\u7fa4\u81f3\u5c11\u67093\u5957\u6210\u719f\u7684presenter\u5be6\u4f5c\uff1a<\/p>\n<p><a href=\"https:\/\/github.com\/laracasts\/Presenter\">https:\/\/github.com\/laracasts\/Presenter<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/robclancy\/presenter\">https:\/\/github.com\/robclancy\/presenter<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/laravel-auto-presenter\/laravel-auto-presenter\">https:\/\/github.com\/laravel-auto-presenter\/laravel-auto-presenter<\/a><\/p>\n<p>\u6709\u7684\u529f\u80fd\u8c50\u5bcc\u3001\u6709\u7684\u6bd4\u8f03\u967d\u6625\uff0c\u4f46\u662f\u6982\u5ff5\u4e0a\u4e00\u6a23\uff0c\u90fd\u662fdecorator pattern\u7684\u61c9\u7528\u3002<\/p>\n<p>\u4e0b\u6b21\u4f60\u7684application\u5305\u542b\u5927\u91cfpresentation logic\u6642\uff0c\u4e0d\u59a8\u8a66\u8a66\u770b\u9019\u500b\u4f5c\u6cd5\u3002<\/p>\n<p>(Photo via <a href=\"https:\/\/www.flickr.com\/photos\/infomastern\/\">Susanne Nilsson<\/a>, CC licensed)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u958b\u767capplication\u6642\uff0c\u5e38\u5e38\u6703\u6709\u5927\u91cf\u7684\u5448\u73fe\uff08presentation\uff09\u908f\u8f2f\u3002 \u50cf\u662f\u65e5\u671f\u683c\u5f0f\u3001\u91d1\u984d\u683c\u5f0f\uff08\u662f &hellip; <a href=\"https:\/\/blog.turn.tw\/?p=2511\" class=\"more-link\">\u7e7c\u7e8c\u95b1\u8b80 <span class=\"screen-reader-text\">\u80d6\u80d6 Model \u7684\u6e1b\u91cd\u65b9\u6cd5\uff1aPresenter<\/span> <span class=\"meta-nav\">&rarr;<\/span> <\/a><\/p>\n","protected":false},"author":1,"featured_media":2514,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false},"categories":[2],"tags":[8,19],"_links":{"self":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts\/2511"}],"collection":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2511"}],"version-history":[{"count":7,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts\/2511\/revisions"}],"predecessor-version":[{"id":2519,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/posts\/2511\/revisions\/2519"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/media\/2514"}],"wp:attachment":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2511"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2511"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2511"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}