По-хорошему, файл system/library/session/db.php должен быть таким:
<?php
/*
CREATE TABLE IF NOT EXISTS `session` (
`session_id` varchar(32) NOT NULL,
`data` mediumtext NOT NULL,
`expire` datetime NOT NULL,
PRIMARY KEY (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
*/
namespace Session;
final class DB {
public $expire = '';
public function __construct($registry) {
$this->db = $registry->get('db');
$this->expire = ini_get('session.gc_maxlifetime');
$this->gc();
}
public function read($session_id) {
$query = $this->db->query("SELECT `data` FROM `" . DB_PREFIX . "session` WHERE session_id = '" . $this->db->escape($session_id) . "' AND expire > now()");
if ($query->num_rows) {
return json_decode($query->row['data'], true);
} else {
return false;
}
}
public function write($session_id, $data) {
if ($session_id) {
$this->db->query("REPLACE INTO `" . DB_PREFIX . "session` SET session_id = '" . $this->db->escape($session_id) . "', `data` = '" . $this->db->escape(json_encode($data)) . "', expire = DATE_ADD(NOW(), INTERVAL " . $this->expire . " SECOND)");
}
return true;
}
public function destroy($session_id) {
$this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE session_id = '" . $this->db->escape($session_id) . "'");
return true;
}
public function gc() {
$this->db->query("DELETE FROM `" . DB_PREFIX . "session` WHERE expire <= now()");
return true;
}
}
Тут на самом деле три фикса:
Более правильная работа с полем expire, используя только возможности MySQL.
Для поля data следует использовать гораздо больше, чем 64Кб (т. е. вместо TEXT лучше юзать MEDIUMTEXT, чего вполне должно хватить на все случаи жизни). На практике у меня ломались сессии из-а того, что накапливалось около 1Мб сессионных данных и они тупо не сохранялись из-за чего в магазине происходила мистика.
В метод gc() нет необходимости передавать параметр.
Обратил внимание, что даже в master-ветке opencart-а на github-е, фиксы какие-то странные. Хотелось бы услышать критику по этим фиксам и может я что-то не учёл.