Почему это не работает?
по умолчанию сеансы сохраняются в локальных файлах на сервере, расположение которых указано в session.save_path
файла php.ini, например session.save_path = /var/lib/php/sessions
, если запущены app.example.com и help.app.example.com на 2 разных серверах с их собственной файловой системой, или даже если она работает в одной и той же файловой системе, но имеет разные директивы session.save_path
в php.ini, они не будут использовать одну и ту же переменную $ _SESSION.
если вы хотите, чтобы 2 разных сервера использовали один и тот же $ _SESSION, возможные решения включают в себя создание базы данных общего хранилища сеансов с session_set_save_handler()
(как приходит на ум MongoDB или MySQL) или создание сетевой файловой системы и установите session.save_path = /path/to/networked/filesystem/mountpoint
в php.ini, но оба эти метода могут привести к значительному снижению производительности.
... поскольку файл cookie используется в обоих доменах, session_id()
вернет одинаковое значение с обеих сторон, которое можно использовать в качестве идентификатора для базы данных сеанса, взгляните на http://php.net/manual/en/class.sessionhandlerinterface.php
(я бы написал пример класса, если бы у меня было больше времени, но у меня нет времени)
переключиться на хранилище сеансов с поддержкой sql-db (например, MariaDB, MySQL или PostgreSQL), например:
схема:
CREATE TABLE sessions (
id VARCHAR(255) ,
atime BIGINT ,
data BLOB
)
Реализация SessionHandlerInterface:
class MySqlSessionHandler implements SessionHandlerInterface
{
protected $db;
public function __construct(string $dsn, string $username, string $password)
{
$this->db = new PDO($dsn, $username, $password, array(
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
}
protected function a(string $id) : bool
{
$ret = $this->db->query("UPDATE sessions SET atime = " . (time()) . " WHERE id = " . $this->db->quote($id));
return ($ret->rowCount() > 0);
}
public function close() : bool
{
// TODO: implement locking/race-condition-free session handling?
return true;
}
public function destroy(string $id) : bool
{
$this->db->query("DELETE FROM sessions WHERE id = " . $db->quote($id));
return true;
}
public function gc(int $maxlifetime) : int
{
$this->db->query("DELETE FROM sessions WHERE atime < " . (time() - $maxlifetime));
return 1; // ??? not sure what this return int is supposed to contain, docs doesn't say either
}
public function open(string $save_path, string $session_name) : bool
{
if (!$this->a($session_name)) {
$stm = $this->db->prepare("INSERT INTO sessions (id,atime,data) VALUES(?,?,?);");
$stm->execute(array($session_name, time(), serialize(null)));
}
return true;
}
public function read(string $session_id) : string
{
if (!$this->a($session_id)) {
throw new \InvalidArgumentException("supplied session id does not exist.");
}
return $this->db->query("SELECT data FROM sessions WHERE id = " . $this->db->quote($session_id))->fetch(PDO::FETCH_ASSOC)['data'];
}
public function write(string $session_id, string $session_data) : bool
{
// optimization note: this function can be optimized to do everything in a single query, instead of using a() (which also use a query)
if (!$this->a($session_id)) {
throw new \InvalidArgumentException("supplied session id does not exist.");
}
$stm = $this->db->prepare("UPDATE sessions SET data = ? WHERE id = ?");
$stm->execute(array($session_data, $session_id));
return true;
}
}
использование:
// for DSN documentation, check http://php.net/manual/en/ref.pdo-mysql.connection.php
$handler = new MySqlSessionHandler ('mysql:host=mydb.foo.com;dbname=sessions;charset=utf8mb4','MySqlUsername','MySqlPassword');
session_set_save_handler($handler, true);
session_start();
- теперь они обязательно должны делиться сессиями ..
- предупреждение: не проверено на момент написания, но это должно работать в теории.