diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c67f576..31d5d7db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,13 @@ All notable changes to this project will be documented in this file, in reverse ### Fixed -- Nothing. +- [#107](https://github.com/zendframework/zend-session/pull/107) fixes an error + raised by `ini_set()` within `SessionConfig::setStorageOption()` that occurs + for certain INI values that cannot be set if the session is active. When this + situation occurs, the class performs a `session_write_close()`, sets the new + INI value, and then restarts the session. As such, we recommend that you + either set production INI values in your production `php.ini`, and/or always + pass your fully configured session manager to container instances you create. ## 2.8.3 - 2017-12-01 diff --git a/src/Config/SessionConfig.php b/src/Config/SessionConfig.php index dc5d3ff3..f260f7f7 100644 --- a/src/Config/SessionConfig.php +++ b/src/Config/SessionConfig.php @@ -133,7 +133,24 @@ public function setStorageOption($storageName, $storageValue) break; } - $result = ini_set($key, (string) $storageValue); + $iniGet = ini_get($key); + $storageValue = (string) $storageValue; + if (false !== $iniGet && (string) $iniGet === $storageValue) { + return $this; + } + + $sessionRequiresRestart = false; + if (session_status() == PHP_SESSION_ACTIVE) { + session_write_close(); + $sessionRequiresRestart = true; + } + + $result = ini_set($key, $storageValue); + + if ($sessionRequiresRestart) { + session_start(); + } + if (false === $result) { throw new Exception\InvalidArgumentException( "'{$key}' is not a valid sessions-related ini setting." diff --git a/test/Config/SessionConfigTest.php b/test/Config/SessionConfigTest.php index 5486238c..9244b1a3 100644 --- a/test/Config/SessionConfigTest.php +++ b/test/Config/SessionConfigTest.php @@ -96,6 +96,23 @@ public function testNameAltersIniSetting() $this->assertEquals('FOOBAR', ini_get('session.name')); } + public function testNameAltersIniSettingAfterSessionStart() + { + session_start(); + + $this->config->setName('FOOBAR'); + $this->assertEquals('FOOBAR', ini_get('session.name')); + } + + public function testIdempotentNameAltersIniSettingWithSameValueAfterSessionStart() + { + $this->config->setName('FOOBAR'); + session_start(); + + $this->config->setName('FOOBAR'); + $this->assertEquals('FOOBAR', ini_get('session.name')); + } + // session.save_handler public function testSaveHandlerDefaultsToIniSettings()