自動目錄
Codeignitor4(以下全稱為ci4) 自帶提供memcache,設置上非常方便,其實ci3上就有memcache,但是因為 selinux的關係,我一直試不成功,所以放棄。
memcache是使用記憶體當空間給session或cache使用,7版以前的php使用的是Memcache類別,8版使用 Memcached類別,除了名稱多了一個 d以外,裡面的方法都不一樣。
ci4上設置有兩個部分,一是修改cache另一個是修改session的設置,兩者可擇一設置,session的部分如果要使用memcache的話,需安裝 php-memcached 這個模組並開啟。
以下文章中 memcache 指的是這個服務,memcached 是這個服務的程式,名稱上常常會混用,要注意看,雖然我也很困擾。
程式碼來源於[1],有小部分修改。
此次異動的檔案有二個,在app/目錄下
├── Config
│ ├── Cache.php <== Cacha的設定
│ └── Session.php <== Session的設定
├── Controller
│ └── TestSession.php <== 測試用,非必要
└── .env <==設定顯示錯誤
Config/Cache.php
修改兩個地方即可[1] :
// public string $handler = 'file'; <== 註解原本的,加上下面這行
public string $handler ='memcached';
...
public array $memcached = [
'host' => 'memcache', //'127.0.0.1', <== 改成ip或是container的service name
'port' => 11211,
'weight' => 1,
'raw' => false,
];
其餘不必動
Config/Session.php
修改或新增以下兩行
public string $driver = 'CodeIgniter\Session\Handlers\MemcachedHandler';
...
// public string $savePath = WRITEPATH . 'session'; <== 註解這行
public string $savePath = 'memcache:11211';
其中 $savepath 的 memcahce 改成ip即可。
讓你的php支援 php-memcached
在session中使用memcached得安裝 php-memcached 並啟用。
安裝 php memcached 模組
# yum install php-pecl-memcache
重啟後請檢查
# php -m
mbstring
memcached <== 需要有這個模組
mysqli
...
Docker中安裝 php-memcached
預設docker php:8.2-fpm 中並無安裝此模組,要自行建立,請在 Dockerfile 中加入[4]
...
apt-get install -y libmemcached-dev zlib1g-dev libssl-dev && \
yes '' | pecl install -f memcached-3.2.0 && docker-php-ext-enable memcached && \
...
測試及除錯
使用的memcache如果無法連線,大概率會得到這樣的錯誤:
codeignitor4 Fatal error: Uncaught ErrorException: session_write_close(): Failed to write session data using user defined save handler. memcached
這樣的錯誤無法清楚的知道是怎樣的問題,所以可以使用下面兩種方式先確定你的memcache伺服器是正常的。
使用php原生的方式測試 [5]
$m= new MemCached(); $m->addServer('memcached', 11211); $m->set('int', 99); $m->set('string', 'a simple string'); $m->set('array', array(11, 12)); /* expire 'object' key in 5 minutes */ $m->set('object', new stdClass, time() + 300); print $m->get('int'); var_dump($m->get('int')); var_dump($m->get('string')); var_dump($m->get('array')); var_dump($m->get('object'));
結果:
string(15) "a simple string"
array(2) {
[0]=>
int(11)
[1]=>
int(12)
}
object(stdClass)#2 (0) {
}
CI4中叫用測試
session原則上和原本使用的方式一樣,不必特別改變習慣
Controller 中session叫用測試:
$session = session(); $session->set('cachename', 'My Memcache'); print $session->get('cachename'); //or print $session->cachename;
結果:
My MemcacheMy Memcache
備註,CI4出現 whoops! 怎麼辦
如果出現 whoops!,到 ci4的根目錄下[3]:
修改.env 把
CI_ENVIRONMENT = production
換成這個
CI_ENVIRONMENT = development
預設使用session library
如果要預設載入 session的library,修改 BaseController.php [2]
public $session; public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { // Do Not Edit This Line parent::initController($request, $response, $logger); // Preload any models, libraries, etc, here. $this->session = \Config\Services::session(); }
其它controller 直接使用 $this->session 即可
參考資料
[1] https://codeigniter.com/user_guide/libraries/caching.html#memcached-caching
[2] https://forum.codeigniter.com/showthread.php?tid=72170
[3] https://stackoverflow.com/questions/60558157/why-whoops-error-showing-in-codeigniter-4
[5] https://www.php.net/manual/en/memcached.set.php