分析 Cookie
從 [Pipeline][Day07] 的分析,我們了解了 middleware 的執行流程,接下來我們來看與預設 middleware 相關的其中一個元件--Cookie。
類別圖
@startuml |
這次也跟 Config 一樣,是個單純的元件。比較特別的是,它跟 Symfony\Component\HttpFoundation\Cookie
的關係是建立 instance 的角色。
從 Contract 的名稱與定義的行為看起來,它是一個 queue。而行為提供了加元素、移除元素、以及取得所有元素的方法。
接下來分別看這三個方法做了哪些事:
queue()
queue()
的任務是加元素進這個 queue 物件。
public function queue(...$parameters) |
從程式碼裡可以知道,這個元件使用 array 實作 queue,因此取得元素與移除元素的時間複雜度將會是 O(1)。
make()
的任務是產生 Cookie 實例,所以可以確定 queue 裡面所有的元素將會都是 Cookie
public function make($name, $value, $minutes = 0, $path = null, $domain = null, $secure = null, $httpOnly = true, $raw = false, $sameSite = null) |
產生到期日使用 [Carbon][Decompose Day02] 實作,應該是好理解的,產生實例也沒有什麼大問題,getPathAndDomain()
的實作如下:
protected function getPathAndDomain($path, $domain, $secure = null, $sameSite = null) |
?:
這個寫法的意思是:$path
是 null
的話,就使用 $this->path
,其他依此類推。而 $this
相關的屬性並沒有初始化,但有一個公開方法 setDefaultPathAndDomain()
可以設定:
public function setDefaultPathAndDomain($path, $domain, $secure = false, $sameSite = null) |
因為 queue 使用 array 實作,所以 unqueue() 和 getQueuedCookies() 的實作自然就會非常簡單:
public function unqueue($name) |
雖然稱之為 queue,實作上比較像 hash table。
但到目前為止,並沒有任何 Cookie 的寫入與讀取,到底是哪裡實作的呢?答案就在 middleware AddQueuedCookiesToResponse 裡:
public function handle($request, Closure $next) |
就這樣,非常的簡單,這也是 Laravel 預設樣版會設定的 middleware。而平常使用,只要取得 CookieJar,然後把需要的 Cookie 加入 queue 即可。參考 CookieServiceProvider
要注意這裡的 domain 等設定是吃 config/session.php 裡面的設定。
public function register() |
可以得知,Container 的 key 是叫 cookie
,所以只要這樣寫就能取到單例的 CookieJar:
app('cookie')->queue('new_cookie', 'some-value', 10); |
Laravel 的程式碼可以這麼簡潔,有很大一部分也是歸工於 Symfony。
今日總結
Cookie 的處理是麻煩的,但 Laravel 與 Symfony 讓這一切處理都變得非常簡單。偶爾翻翻原始碼,才有辦法思考什麼樣的設計才能讓其他開發者覺得好用,