摘要:在這篇文章,我們將探尋如何使用集合提升編碼效率代碼的易讀行,及編寫(xiě)出更精簡(jiǎn)的編碼。還沒(méi)有進(jìn)入正題好吧,讓我們回顧一個(gè)簡(jiǎn)單的代碼片段,來(lái)看看我們?nèi)绾问褂眉暇帉?xiě)粗快猛的代碼吧。
本文首發(fā)于 如何使用 Laravel Collections 類(lèi)編寫(xiě)神級(jí)代碼,轉(zhuǎn)載請(qǐng)注明出處。
Laravel 提供了一些超贊的組件,在我看來(lái),它是目前所有 Web 框架中提供組件支持最好的一個(gè)。它不僅提供了開(kāi)箱即用的視圖(views)、身份認(rèn)證(authentication)、會(huì)話(huà)(sessions)、緩存(caching)、Eloquent、隊(duì)列(queues)、數(shù)據(jù)校驗(yàn)(data validation)等組件。甚至還提供了開(kāi)發(fā)工具(Valet 和 Homestead)。
但是,這個(gè)框架功能中最強(qiáng)大的一個(gè)特性常常被萌新們視而不見(jiàn) - Collection(集合) 類(lèi)。在這篇文章,我們將探尋如何使用集合提升編碼效率、代碼的易讀行,及編寫(xiě)出更精簡(jiǎn)的編碼。
預(yù)覽最初接觸到使用集合的場(chǎng)景來(lái)自于研發(fā)人員使用 Eloquent 執(zhí)行數(shù)據(jù)庫(kù)查詢(xún),并從返回?cái)?shù)據(jù)中使用 foreach 語(yǔ)句遍歷獲取模型集合。
不過(guò),初學(xué)者可能并沒(méi)有注意到,集合提供了超過(guò) 90 個(gè)以上的方法來(lái)操作底層數(shù)據(jù)。更妙的是幾乎所有的方法都支持鏈?zhǔn)讲僮鳎軌蜃屇愕拇a讀起來(lái)就像一篇散文一樣。這樣使得你的代碼更易閱讀,無(wú)論是你還是其他使用者都是如此。
還沒(méi)有進(jìn)入正題?好吧,讓我們回顧一個(gè)簡(jiǎn)單的代碼片段,來(lái)看看我們?nèi)绾问褂眉暇帉?xiě)粗、快、猛的代碼吧。
代碼示例讓我們構(gòu)建一個(gè)真實(shí)的世界。假設(shè)我們查詢(xún)某些 API 接口并獲取到如下以數(shù)組保存的結(jié)果集:
"John", "last_name" => "Doe", "age" => "twenties"], ["first_name" => "Fred", "last_name" => "Ali", "age" => "thirties"], ["first_name" => "Alex", "last_name" => "Cho", "age" => "thirties"], ];
我們看到數(shù)組包含名字(first name)、姓氏(last name) 和年齡(age)范圍。現(xiàn)在,我們假設(shè)從記錄中獲取一名 年齡(age) 為 30 歲(thirties) 的用戶(hù),然后依據(jù) 姓氏(last name) 進(jìn)行 排序(sort)。最后,我們還希望返回的結(jié)果為 一個(gè)字符串(single string),這樣每個(gè)用戶(hù)獨(dú)占 一行(new line)。最后,我們還希望返回的結(jié)果為
這個(gè)需求看起來(lái)不難實(shí)現(xiàn),現(xiàn)在讓我們看看使用 PHP 如何實(shí)現(xiàn)這一功能:
// 依據(jù)姓氏排序 usort($data, function ($item1, $item2) { return $item1["last_name"] <=> $item2["last_name"]; }); // 依據(jù)年齡范圍分組 $new_data = []; foreach ($data as $key => $item) { $new_data[$item["age"]][$key] = $item; } ksort($new_data, SORT_NUMERIC); // 從年齡為 30 歲組里獲取用戶(hù)全名 $result = array_map(function($item) { return $item["first_name"]." ".$item["last_name"]; }, $new_data["thirties"]); // 將數(shù)組轉(zhuǎn)換為字符串并以行分隔符分隔 $final = implode(" ", $result); // 譯注:原文是 $final = implode($results, " "); implode函數(shù)接收兩種順序的參數(shù),為了保持與文檔一致所以我這邊做了調(diào)整。
我們的實(shí)現(xiàn)代碼超過(guò) 20 行,并且很不優(yōu)雅。移除掉注釋及換行相關(guān)代碼,這段代碼會(huì)變得難以閱讀。再者,我們還需要借助臨時(shí)變量以及 PHP 中內(nèi)置的不友好的 sort 方法。
現(xiàn)在,讓我們看下借助 Collection 類(lèi)實(shí)現(xiàn)起來(lái)是多么簡(jiǎn)單吧:
collection($data)->where("age", "thirties") ->sortBy("last_name") ->map(function($item){ return $item["first_name"]." ".$item["last_name"]; }) ->implode(" ");
哇哦!我們的代碼從 20 行變成了 6 行。現(xiàn)在的代碼不僅順暢不少,并且在方法實(shí)現(xiàn)時(shí)無(wú)需借助注釋告訴我們它們?cè)谔幚硎裁磫?wèn)題。
不過(guò),還存在一個(gè)問(wèn)題阻止我們的代碼不如完美階段... 就是用于比較 first name 和 last name 的 map 方法。坦白說(shuō),這真的不是什么大問(wèn)題,但是它為我們探索 macro(宏) 概念提供了動(dòng)力。
擴(kuò)展集合(Extending Collections)Collection 類(lèi),同其它 Laravel 組件一樣,支持宏(macroable),就是說(shuō)你可以給它添加方法隨后使用。
提示: 如果你希望新方法隨處可用,你應(yīng)該將它們添加到服務(wù)提供中。我喜歡創(chuàng)建一個(gè) MacroServiceProvider 實(shí)先這個(gè)功能,對(duì)于你來(lái)說(shuō)隨你喜歡就好。
讓我們添加一個(gè)方法它會(huì)連接由數(shù)組提供的任意數(shù)量的字段并返回字符串結(jié)果:
Collection::macro("toConcatenatedString", function ($fields = [], $separator = " ") { return $this->map(function($item) use ($fields, $separator) { return implode($separator, array_map(function ($el) use ($item) { return $item[$el]; }, $fields) ); })->implode(" "); });
添加完這個(gè)方法后,我們的代碼基本上就完美了:
collect($data)->where("age", "thirties") ->sortBy("last_name") ->toConcatenatedString(["first_name", "last_name"]);
我們的代碼從混亂的 20 多行精簡(jiǎn)到了 3 行,代碼干凈整潔功能清晰任何人都可以立馬理解。
又一個(gè)示例現(xiàn)在讓我們看下第二個(gè)示例,假設(shè)我們一個(gè)用戶(hù)列表,我們需要基于角色(role)過(guò)濾出來(lái),然后進(jìn)一步如果他們的注冊(cè)時(shí)間為 5 年或以上且 last name 以字母 A-M 開(kāi)始的僅獲取第一個(gè)用戶(hù)。
數(shù)據(jù)類(lèi)似如下:
"John Doe", "role" => "vip", "years" => 7], ["name" => "Fred Ali", "role" => "vip", "years" => 3], ["name" => "Alex Cho", "role" => "user", "years" => 9], ];
如果我們使用的是 PHP 實(shí)現(xiàn),我們的代碼看下來(lái)如下:
$subset = []; foreach ($users as $user) { if ($user["role"] === "vip" && $user["years"] >= 5) { if (preg_match("/s[A-Z]/", $user["name"])) { $subset[] = $user; } } } return reset($subset)
注意: 你可以將第二個(gè) if 語(yǔ)句移至第一個(gè)里面,但是我個(gè)人喜歡在單個(gè) if 語(yǔ)句中使用不超過(guò)兩個(gè)條件語(yǔ)句,因?yàn)槲艺J(rèn)為超過(guò) 2 個(gè)條件語(yǔ)句回事代碼難以閱讀。
這段代碼不至于太糟糕,但是我們依然需要使用臨時(shí)變量,我們還需要使用 reset 函數(shù)將指針重置到第一個(gè)用戶(hù)。我們的代碼還有四層縮進(jìn),這使得代碼解析變得更有挑戰(zhàn)性。
相反,我們來(lái)看看集合是如何處理這個(gè)問(wèn)題的:
collect($users)->where("role", "vip") ->map(function($user) { return preg_match("/s[A-Z]/", $user["name"]); }) ->firstWhere("years", ">=", "5");
我們將代碼簡(jiǎn)化到了之前的一般左右,每一步過(guò)濾處理清晰明了,并且我們不需要引入臨時(shí)變量。
遺憾的是目前集合還不支持正則匹配,所以我們使用 map 方法,不過(guò)我們可以為這個(gè)功能創(chuàng)建一個(gè)宏:
Collection::macro("whereRegex", function($expression, $field) { return $this->map(function ($item) use ($expression, $field) { return preg_match($expression, $item[$field]); }) });
得益于宏方法,我們的代碼現(xiàn)在看起來(lái)如下:
collect($users) -> where("role", "vip") -> whereRegex("/s[A-Z]/", "name") -> firstWhere("years", ">=", 5);
注意: 為了簡(jiǎn)單起見(jiàn),我們的紅僅僅適用于數(shù)組集合。如果你計(jì)劃讓它們可以在 Eloquent 集合上使用,你需要在此場(chǎng)景下做相應(yīng)的代碼處理才行。不同的視角
我們可以繼續(xù)列出無(wú)數(shù)的示例,但仍然無(wú)法涵蓋所有可用的集合方法,并且這從來(lái)都不是本文的真正目的。
需要注意的是,通過(guò)使用 Collection 類(lèi),您不僅可以獲得一個(gè)方法庫(kù)來(lái)簡(jiǎn)化編程工作,還可以選擇一種從根本上改善代碼的方法。
你會(huì)情不自禁的將你的代碼結(jié)構(gòu)從代碼塊重構(gòu)簡(jiǎn)化成一行,同時(shí)減少代碼的縮進(jìn),臨時(shí)變量的使用和技巧性方法,另外你還可以使用鏈?zhǔn)骄幊谭椒ǎ@讓你的代碼更加便于閱讀和解析,此外最重要的是減少了編碼工作!
查看官方文檔獲取更多這個(gè)迷人的類(lèi)庫(kù)的使用細(xì)節(jié):https://laravel.com/docs/coll...
提示: 你還可以獲取這個(gè) Collection 類(lèi)獨(dú)立安裝包,在使用非 laravel 項(xiàng)目是會(huì)非常有幫助。感謝 Tighten Co 團(tuán)隊(duì)做出的努力 https://github.com/tightenco/...。
感謝閱讀,快樂(lè)編碼!
如果你有興趣,可以 follow 我 @mattkingshott
原文How Laravel Collections lead to Zen Code
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/29013.html
摘要:經(jīng)常我們看見(jiàn)評(píng)論顯示形式有很多,比如某某,又或者像知乎的收縮式的評(píng)論,又或者是嵌套式的評(píng)論,那么最一開(kāi)始也是最常見(jiàn)的就是嵌套式評(píng)論,因?yàn)檫@個(gè)更加醒目準(zhǔn)備工作設(shè)計(jì)三張表,表結(jié)構(gòu)如下層文件一篇文章有 經(jīng)常我們看見(jiàn)評(píng)論顯示形式有很多,比如@某某,又或者像知乎的收縮式的評(píng)論,又或者是嵌套式的評(píng)論,那么最一開(kāi)始也是最常見(jiàn)的就是嵌套式評(píng)論,因?yàn)檫@個(gè)更加醒目. 準(zhǔn)備工作1.設(shè)計(jì)三張表users,po...
摘要:注本文是翻譯寫(xiě)的關(guān)于調(diào)試技巧,讀完以后很實(shí)用,分享給大家閱讀過(guò)程中,翻譯有錯(cuò)誤的希望大家指正原文鏈接最近我一直在使用的,如果你還不了解,我簡(jiǎn)單說(shuō)下一個(gè)集合就是一個(gè)功能強(qiáng)大的數(shù)組有很多強(qiáng)大處理其內(nèi)部數(shù)據(jù)的函數(shù)但是唯一讓我頭疼的地方是如何調(diào)試的 注:本文是翻譯Freek Van der Herten寫(xiě)的關(guān)于Collection調(diào)試技巧,,讀完以后很實(shí)用,分享給大家.閱讀過(guò)程中,翻譯有錯(cuò)誤的...
摘要:是我開(kāi)發(fā)的一個(gè)收藏文章的擴(kuò)展,借鑒于,我也有幸參加了社區(qū)對(duì)該擴(kuò)展的外文翻譯文章為你的模型添加喜歡和討厭功能。但是對(duì)于想學(xué)習(xí)開(kāi)發(fā)擴(kuò)展包的同學(xué)還是不錯(cuò)的。最近發(fā)現(xiàn)已經(jīng)有人使用我的擴(kuò)展包到項(xiàng)目里,我更有動(dòng)力不斷更新完善。 Laravel Collect 是我開(kāi)發(fā)的一個(gè)收藏文章的擴(kuò)展,借鑒于 cybercog/laravel-love ,我也有幸參加了社區(qū)對(duì)該擴(kuò)展的外文翻譯文章 為你的 Elo...
摘要:本文翻譯改編自的十八個(gè)最佳實(shí)踐這篇文章并不是什么由改編的原則模式等。只是為了讓你注意你在現(xiàn)實(shí)生活的項(xiàng)目中最常忽略的內(nèi)容。單一職責(zé)原則正在幫助你避免重復(fù)。當(dāng)然,這也包括了模板的范圍等。此外,也擁有很棒的內(nèi)置工具,比如軟刪除事件范圍等。 showImg(https://segmentfault.com/img/remote/1460000015166532); 本文翻譯改編自 Larave...
閱讀 594·2021-11-18 13:12
閱讀 1314·2021-11-15 11:39
閱讀 2473·2021-09-23 11:22
閱讀 6194·2021-09-22 15:15
閱讀 3655·2021-09-02 09:54
閱讀 2310·2019-08-30 11:10
閱讀 3245·2019-08-29 14:13
閱讀 2913·2019-08-29 12:49