既然已經決定要以 Simple Cache (簡易快取機制) 來做為這次的實戰題目,原則上在 PHP 社群中有建議的規範就按照規範走,沒有就自由發揮。剛好 PSR-16 建議規範的對象就是為快取套件定義出統一的介面。


PSR-16 快取介面

CacheInterface

CacheInterface 介面一共有六個公開方法。(為了節省版面已將註解移除唷!)

<?php

namespace Psr\SimpleCache;

interface CacheInterface
{
    public function set($key, $value, $ttl = null);
    public function delete($key);
    public function clear();
    public function getMultiple($keys, $default = null);
    public function setMultiple($values, $ttl = null);
    public function deleteMultiple($keys);
    public function has($key);
}

方法 (Methods)

介面中各方法的說明如下:

方法 說明
set 設定快取。
delete 刪除快取。
clear 刪除所有快取。
getMultiple 一次取得多個快取的值,以可遍歷的陣列回傳。
setMultiple 以可遍歷的陣列一次設定多個快取。
deleteMultiple 以可遍歷的陣列一次刪除多個快取
has 檢查是否有該鍵值的快取存在。

參數 (Arguments)

介面中各方法的參數說明如下:

變數 型別 說明
$key string 快取資料的鍵名。
$value mixed 快取資料的值。
$ttl int, DateInterva, null 快取資料的有效時間,過期後快取資料會被刪除。
$default mixed 預設值,取不到該鍵名的資料,則回傳預設的值。
$keys iterable 可遍歷的陣列結構,鍵值的集合。
$values iterable key => value 可遍歷的陣列結構

異常處理介面

PSR-16 定義兩個異常處理介面。

CacheException

<?php

namespace Psr\SimpleCache;

interface CacheException
{
}

一般情況下關於快取機制產生錯誤的情況,丟出此異常錯誤。

InvalidArgumentException

<?php

namespace Psr\SimpleCache;

interface InvalidArgumentException extends CacheException
{
}

參數有錯誤的情況,丟出此異常錯誤。


目錄結構規劃

先初步規劃出此專案作品的目錄結構,不過最後的完成品有可能會再修改唷!

.
├── README.md
├── composer.json
├── composer.lock
├── vendor
├── src
│   └── SimpleCache
│       ├── Cache.php
│       ├── CacheProvider.php
│       ├── Driver
│       │   ├── File.php
│       │   ├── Mysql.php
│       │   ├── Redis.php
│       │   └── Sqlite.php
│       └── Exception
│           ├── CacheArgumentException.php
│           └── CacheException.php
└── tests
    └── SimpleCache
        ├── CacheTest.php
        └── CacheTestCase.php

結構說明

名稱 性質 說明
README.md 檔案 這個檔案是進入專案 GitHub 儲存庫的首頁說明檔,以 Markdown 格式編寫。
composer.json 檔案 套件的設定檔。
composer.lock 檔案 執行 composer install 後自動產生的檔案。(應加入 .gitignore 從版控中略過)
vender 目錄 Composer 的套件目錄。以本例,裡頭裝了單元測試套用 PHP UNIT 的套件(及其依賴套件)、PSR-16 的介面。(應加入 .gitignore 從版控中略過)
src 目錄 這個專案作品的原始檔目錄,但筆者的規劃是命名空間的基本目錄是從 src/SimpleCache 開始。這只是個人的習慣,因為筆者想要它和單元測試用的 tests 目錄對稱。
tests 目錄 單元測試用目錄,在這一層會放初始化的檔案,以及單元測試完自動產生的報表資料夾等等。筆者不想檔案都混在一起,所以測試的 .php 都會在 tests/SimpleCache

PSR-16 的兩個異常處理介面,會放在 src/SimpleCache/Exception 這個目錄。而 CacheInterface 會先實作在 CacheProvider.php 中。

各個不同類型的資料存取媒介,放在 src/SimpleCache/Driver 目錄中。


介面實作

CacheInterface

CacheInterface 介面實作於 CacheProvider 抽像類別中。這個抽像類別將實作一般情況下處理 Cache 資料的邏輯。

範例:/day-16/src/SimpleCache/CacheProvider.php

<?php

declare(strict_types=1);

namespace Shieldon\SimpleCache;

use Psr\SimpleCache\CacheInterface;

abstract class CacheProvider implements CacheInterface
{
    public function get($key, $default = null)
    {

    }

    public function set($key, $value, $ttl = null)
    {

    }

    public function delete($key)
    {

    }

    public function clear()
    {

    }

    public function has($key)
    {

    }

    public function getMultiple($keys, $default = null)
    {

    }

    public function setMultiple($values, $ttl = null)
    {

    }

    public function deleteMultiple($keys)
    {

    }
}

InvalidArgumentException

範例:/day-16/src/SimpleCache/Exception/CacheArgumentException.php

<?php

declare(strict_types=1);

namespace Shieldon\SimpleCache\Exception;

use Psr\SimpleCache\InvalidArgumentException as InvalidArgumentExceptionInterface;
use InvalidArgumentException;

class CacheArgumentException extends InvalidArgumentException implements InvalidArgumentExceptionInterface
{

}

CacheArgumentException 這個類別繼承了 InvalidArgumentException 並實作了 Psr\SimpleCache\InvalidArgumentException 介面。

CacheException

範例:/day-16/src/SimpleCache/Exception/CacheException.php

<?php

declare(strict_types=1);

namespace Shieldon\SimpleCache\Exception;

use Psr\SimpleCache\CacheException as CacheExceptionInterface;
use Exception;

class CacheException extends Exception implements CacheExceptionInterface
{

}

CacheException 這個類別繼承了 Exception 並實作了 Psr\SimpleCache\CacheException 介面。因為撞名了會有錯誤,所以用 as 關鍵字換成別名。

或許讀者們會疑惑,為什麼要實作兩個介面但內容是卻是空的類別。

雖然目前還不需要改寫繼承的類別中方法或屬性,這是為了讓其它依賴的類別在往後這兩個異常處理類別需要改寫繼承類別的方法或屬性的時候,能一致性地套用到其它依賴的類別中。

總結

今天的進度是先把介面實作出來,把檔案架構定出來,就像建築工地要蓋房子前要先搭好鷹架,一層一層往上蓋。一個空殼出來了,接下來後幾天就是把它做出來。

本篇原始碼可在此瀏覽。我們明天見囉。

最後修改日期: 2022-02-06

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。