Pull to refresh

php: Хранение объектов в сессии

Reading time3 min
Views6.5K
На недавно отпиареном здесь ресурсе наткнулся на вопрос о хранении в сессии php созданных в скрипте объектов.

Насколько плохой практикой является в принципе хранение объектов в сессии, я обсуждать не буду, а просто покажу, как надо работать с такими объектами. Впрочем, если специалисты уже нашли рецепт на php.net, и считают, что все тривиально, я с ними полностью соглашусь. Однако если вы немного не в курсе…

Итак, мы задались целью положить в сессию объект, скажем, некоего пользователя.

Примерно наши файлы будут выглядеть так:

myclass.php:
<?php
class MyClass
{
    public $user;
}


index.php:
<?php
session_start();
require 'myclass.php';
header("content-type: text/plain");
if (!isset($_SESSION['classTst'])) {
    $myclass = new MyClass();
    $myclass->user = 'me';
    $_SESSION['classTst'] = $myclass;
    echo "Class is into session array now";
}
else {
    echo "\$_SESSION['classTst'] dump: \n\n";
    var_dump($_SESSION['classTst']);
}




А теперь разберёмся, что мы делаем.

В первый запуск скрипта index.php мы создаем объект класса myclass и помещаем его в сессию. В любом последующем случае (пока мы не уничтожим сессию или не уничтожим на неё «ссылку» — в виде куки в браузере, например) мы загружаем сессию, в которой уже есть наш объект. Однако вместо того, чтобы быть экземпляром класса MyClass, var_dump() нас «радует» классом "__PHP_Incomplete_Class":

$_SESSION['classTst'] dump: 

object(__PHP_Incomplete_Class)#1 (2) {
  ["__PHP_Incomplete_Class_Name"]=>
  string(7) "MyClass"
  ["user"]=>
  string(2) "me"
}


Всё очень просто. При инициализации сессии php натыкается на факт, что у него в $_SESSION['classTst'] лежит экземпляр класса MyClass (желающие могут посмотреть на содержимое файла (если у вас сессии в файлах) сессии и убедиться, что там будет лежать наш сериализованный объект, с описанием, экземпляром какого класса он является). Но (сюрприз!), как видно из скрипта, php на момент старта сессии НИЧЕГО не знает о существовании класса MyClass. Посему вполне логичный интерпретатор воспринимает далее этот объект именно как объект некоего __PHP_Incomplete_Class.

Но стоит нам поменять порядок старта сессии и загрузки класса:
<?php
require 'myclass.php';
session_start();
header("content-type: text/plain");
if (!isset($_SESSION['classTst'])) {
    $myclass = new MyClass();
    $myclass->user = 'me';
    $_SESSION['classTst'] = $myclass;
    echo "Class is into session array now";
}
else {
    echo "\$_SESSION['classTst'] dump: \n\n";
    var_dump($_SESSION['classTst']);
}

,

как, вуаля, мы получаем то, что и хотели:

$_SESSION['classTst'] dump: 

object(MyClass)#1 (1) {
  ["user"]=>
  string(2) "me"
}


В общем, всё действительно просто: все объекты, которые вы хотите хранить в сессии, должны стать известны интерпретатору ДО того, как вы будете стартовать сессию.

Таким образом, например, если у вас стандартом является session.auto_start On, хранить в сессии объекты вам не судьба. Также, если вы полагаетесь на фреймворки, авторы которых за вас решили, где и когда какие объекты подгружать (и вы всецело полагаетесь на авторов), хранение каких-то определённых объектов в сессии может стать просто смертельным номером (в случае объекта с другими вложенными объектами, вызываемыми «по требованию» где-то перед исполнением, скажем, уже контроллера, когда сессия давно стартовала). В случае составного объекта (содержащего в себе 2-3 служебных объекта в свойствах, например) может возникнуть резонный вопрос: что «дешевле» — кинуть всё в сессию, или получить заново объект одним-двумя запросами из БД (или кэша БД)?

Так что хранить или не хранить в сессии объекты, и как это делать исходя из реалий вашего проекта — решать всё равно вам :)
Tags:
Hubs:
Total votes 10: ↑7 and ↓3+4
Comments15

Articles