建立 Eloquent
昨天在把 View 轉換成 Blade 時,會遇到一個重大的難題:我們沒有假資料建立方法可以方便地做自動化測試。
昨天在把 View 轉換成 Blade 時,會遇到一個重大的難題:我們沒有假資料建立方法可以方便地做自動化測試。
Handler 的繼承關係如下(使用 YAML 表示):
- HandlerInterface: |
洋洋灑灑列出一長串的 Class 名稱,大部分是單純實作服務的串接,有另一小部分的 Handler 是有特殊用途的,撿幾個來介紹。
這個 Handler 是設計用來做測試的,比方說:
$logger = new \Monolog\Logger('name'); |
這樣輸出的結果會是:
bool(false) |
它可以作為一個 spy,去確認寫到 Logger 的內容是正確的。
它的設計方法也很單純,在 write 去寫入一個陣列:
protected function write(array $record) |
而在 assertion 的方法去找陣列有沒有對應的值即可,非常厲害。
這可以把多個 Handler 集合成一個 Group,而對這個 Group 操作,就等於對全部的 Handler 操作。
它的說明很有趣:
Blackhole
所有的 Log 將會像是遇到無底洞一樣,全部被這個 Handler 吃光光。
這也是設計用來測試用的。
覺得 Monolog 不好,但有中意其他 PSR Logger。雖然傷心寂寞覺得冷,但還是可以考慮用 Monolog 的 PsrHandler 包裝其他 PSR Logger 哦。
指令套件 github.com/urfave/cli
算蠻好上手的。雖然好用,但似乎其他套件也不錯,如 Cobra 等。
昨天提到 AbstractHandler
會實作存在 Processor
的方法,但實質上 AbstractHandler
是不會使用 Processor
的。
Monolog 的設計是另外寫一個 AbstractProcessingHandler
來繼承 AbstractHandler
,在裡面處理 Processor
:
protected function processRecord(array $record) |
實作 AbstractProcessingHandler
只要實作 write
方法即可。
其他都是因實作功能需求,把迭代 Processor
的任務放到 handle 的開始、中間、或是後面。
比方說 BufferHandler
是把所有記錄全都放到記憶體裡,直到程序結束後,再一次性的往外送。這種情況下,就會需要在實際 Handler 裡,拿到真正的 record 後,才能跑 Processor,再存 buffer。
前面 25 天,我們已經成功寫出了一個 CLI App 以及 Web App,包括交付與部署都有實作,這次鐵人賽主題的基本要求已經算達標了。
昨天只是單純調整程式碼風格,今天開始要來改設計了!
昨天了解 Formatter
的運作方法了,而資料夾還有另一個角色 Processor
,今天來看看它到底裡面賣的是什麼藥。
Processor
有兩個地方可以使用,分別在 Logger
實作與 HandlerInterface
定義,都有 Processor 的影子。
先來看看 Logger
實作的介面:
class Logger implements LoggerInterface |
這裡可以看到,它跟 Handler 一樣是使用 Array Stack 實作儲存。而要成為 Processor
的一員條件是 is_callable
。
而 HandlerInterface
的定義也相差不遠:
interface HandlerInterface |
HandlerInterface
可以依需求實作不同的邏輯,所以我們先來看 Logger
已經寫好的實作。Logger
是這樣使用 Processor
的:
public function addRecord($level, $message, array $context = array()) |
而 Processor
只要實作 Magic Function __invoke
即可當成 callable 來用,比方說 Processor\MemoryUsageProcessor
的內容如下:
class MemoryUsageProcessor extends MemoryProcessor |
這樣我們就能動態為 $record
加上額外需要的系統資訊了。
而在 Logger 裡,是先跑 Processor
,才跑 Handler
的 handle
方法,因此在 Logger 的 Processor
,實際上會作用在全部的 Handler。
使用 IDE 可以簡單找得到,實作的地方在 AbstractHandler
與 HandlerWrapper
。後者是使用類似 Proxy Pattern 的方法在包裝其他的 Handler,所以本質上還是在使用 AbstractHandler
的實作。
AbstractHandler
的實作如下:
public function pushProcessor($callback) |
事實上與 Logger 完全一樣,重點會是在 $this->processors
如何被使用。不同的 Handler 的用法都有點不大一樣,我們留到明天再詳解吧。
雖然程式碼風格跟設計沒有關係,但是程式碼風格不一致,對理解程式是一個很大的阻礙。調整程式碼風格,是不會影響功能的,因此很適合拿來當重構的暖身。