Все ответы здесь, кажется, говорят использовать методы сеанса таким образом, чтобы они явно не предназначались для использования ... а именно для вызова session_start()
более одного раза.
Веб-сайт PHP предлагает пример реализации SessionHandlerInterface, который будет работать так же, как и существующие сеансы, но без блокировки файла. Просто реализуя свой примерный интерфейс, я исправил проблему с блокировкой, чтобы разрешить одновременные соединения на одном сеансе, не ограничивая возможность добавления vars в сеанс. Чтобы предотвратить некоторые условия гонки, поскольку сеанс приложения не является полностью безгосударственным, мне пришлось сделать способ сохранить средний запрос сеанса, не закрывая его, чтобы важные изменения могли сэкономить сразу после изменения, а менее важные сеансовые вары могли просто сохранить в конце запроса. Смотрите ниже пример использования:
Session::start();
echo("<pre>Vars Stored in Session Were:\n");print_r($_SESSION);echo("</pre>");
$_SESSION['one'] = 'one';
$_SESSION['two'] = 'two';
//save won't close session and subsequent request will show 'three'
Session::save();
$_SESSION['three'] = 'three';
Если вы замените, что Session::start()
с session_start()
и Session::save()
с session_write_close()
, вы заметите, что последующие запросы никогда не будут печатать третьей переменной ... она будет потеряна. Однако, используя SessionHandler (ниже), данные не теряются.
Для реализации OOP требуется PHP 5.4+. Тем не менее, вы можете предоставить отдельные методы обратного вызова в старых версиях PHP. See docs.
namespace {
class Session implements SessionHandlerInterface {
/** @var Session */
private static $_instance;
private $savePath;
public static function start() {
if(empty(self::$_instance)) {
self::$_instance = new self();
session_set_save_handler(self::$_instance,true);
session_start();
}
}
public static function save() {
if(empty(self::$_instance)) {
throw new \Exception("You cannot save a session before starting the session");
}
self::$_instance->write(session_id(),session_encode());
}
public function open($savePath, $sessionName) {
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}
return true;
}
public function close() {
return true;
}
public function read($id) {
return (string)@file_get_contents("$this->savePath/sess_$id");
}
public function write($id, $data) {
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
public function destroy($id) {
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
}
return true;
}
public function gc($maxlifetime) {
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}
return true;
}
}
запозданием, для будущих читателей, я предлагаю вам использовать 'session_set_save_handler()' как более передовой практики, поскольку она не предполагает каких-либо обходных, но модифицирует сессии в качестве авторов PHP казалось, предназначались. Я опубликовал пример того, как это сделать ниже. –