PHP: сохранение «объектов» внутри $ _SESSION

Я просто понял, что могу фактически хранить объекты в $ _SESSION, и я нахожу это довольно крутым, потому что, когда я перехожу на другую страницу, у меня все еще есть мой объект. Теперь, прежде чем я начну использовать этот подход, я хотел бы узнать, действительно ли это такая хорошая идея или если есть потенциальные проблемы .

Я знаю, что если бы у меня была одна точка входа, мне бы не пришлось это делать, но я еще не там, поэтому у меня нет ни одной точки входа, и я действительно хотел бы сохранить свой объект, потому что я не знаю, Я теряю свое состояние. (Теперь я также прочитал, что я должен программировать сайты без гражданства, но пока не понимаю эту концепцию).

Короче говоря : нормально ли хранить объекты в сеансе, есть ли проблемы с ним?


Редактировать:

Временное резюме . К настоящему моменту я понимаю, что, вероятно, лучше воссоздать объект, даже если он включает запрос к базе данных снова.

Дальнейшие ответы могут, возможно, более подробно рассмотреть этот аспект !

Я знаю, что эта тема старая, но эта проблема продолжает расти и не была удовлетворена моим удовлетворением:

Сохраняете ли вы объекты в $ _SESSION или восстанавливаете их всю ткань на основе данных, скрытых в скрытых формах, или повторно запрашиваете их из БД каждый раз, вы используете состояние. HTTP является апатридом (более или менее, но см. GET vs. PUT), но почти все, что нужно делать с веб-приложением, требуют сохранения состояния где-то. Действовать так, как будто продвижение государства в укромные уголки и трещины составляет некоторую теоретическую победу, это просто неправильно. Государство – государство. Если вы используете состояние, вы теряете различные технические преимущества, получаемые за счет отсутствия гражданства. Это не то, чтобы потерять сон, если вы заранее не узнаете, что вам следует потерять сон над ним.

Меня особенно смущает благословение, полученное «двойными ударными» аргументами, выдвинутыми Хэнком Гей. Является ли здание ОП распределенной и сбалансированной по нагрузке системой электронной коммерции? Я думаю, что нет; и я также буду утверждать, что сериализация его класса $ User или что-то еще не приведет к тому, что его сервер не будет поврежден. Мой совет: используйте методы, которые разумны для вашего приложения. Объекты в $ _SESSION в порядке, при условии соблюдения правил здравого смысла. Если ваше приложение внезапно превращается в нечто, конкурирующее с Amazon в обслуживаемом трафике, вам нужно будет снова адаптироваться. Такова жизнь.

это нормально, если ко времени вызова session_start (), декларация / определение класса уже встречается с помощью PHP или может быть найдена уже установленным автозагрузчиком. в противном случае он не сможет десериализовать объект из хранилища сеансов.

HTTP – это протокол без гражданства по какой-либо причине. Сессии сваривают состояние HTTP. Как правило, избегайте использования состояния сеанса.

UPDATE: нет концепции сеанса на уровне HTTP; серверы предоставляют это, предоставляя клиенту уникальный идентификатор и сообщая клиенту повторно отправить его по каждому запросу. Затем сервер использует этот идентификатор в качестве ключа в большой хэш-таблице объектов сеанса. Всякий раз, когда сервер получает запрос, он просматривает информацию сеанса из своей хэш-таблицы объектов сеанса на основе идентификатора клиента, отправленного с запросом. Вся эта дополнительная работа – это двойная атака по масштабируемости (большая причина, по которой HTTP не имеет гражданства).

  • Whammy One: он уменьшает работу, которую может выполнять один сервер.
  • Whammy Two: Это затрудняет масштабирование, потому что теперь вы не можете просто перенаправить запрос на любой старый сервер – у них не все одинаковые сеансы. Вы можете привязать все запросы с заданным идентификатором сеанса к тому же серверу. Это непросто, и это единственная точка отказа (не для системы в целом, а для больших кусков ваших пользователей). Или вы можете поделиться хранилищем сеансов на всех серверах в кластере, но теперь у вас больше сложности: сетевая память, автономный сервер сеансов и т. Д.

Учитывая все это, чем больше информации вы вводите в сеанс, тем больше влияние на производительность (как указывает Винко). Также, как указывает Винко, если ваш объект не сериализуется, сеанс будет неверным. Поэтому, как правило, избегайте вносить больше, чем абсолютно необходимо в сеанс.

@Vinko Обычно вы можете работать с состоянием хранилища серверов, вставляя данные, которые вы отслеживаете, в ответ, который вы отправляете обратно, и повторно отправляете его клиенту, например, отправляя данные вниз на скрытый ввод. Если вам действительно нужно отслеживать состояние на стороне сервера, вероятно, это должно быть в вашем хранилище данных резервного копирования.

(Vinko добавляет: PHP может использовать базу данных для хранения информации о сеансе, и когда клиент повторно передает данные, каждый раз может решить потенциальные проблемы с масштабируемостью, но открывает большую проблему безопасности, на которую вы должны обратить внимание сейчас, когда клиент контролирует все ваше государство)

  • Объекты, которые не могут быть сериализованы (или которые содержат несериализуемые члены), не будут выходить из $ _SESSION, как вы ожидали бы
  • Огромные сеансы накладывают нагрузку на сервер (сериализация и десериализация меганов каждый раз стоит дорого)

Помимо этого я не видел проблем.

По моему опыту, обычно это не стоит ничего сложнее, чем StdClass с некоторыми свойствами. Стоимость unserializing всегда была больше, чем воссоздание из базы данных с учетом сохраненного сеансом идентификатора. Это кажется здоровым, но (как всегда) профилирование – это ключ.

Я бы посоветовал не использовать государство, если он вам не нужен. Если вы можете перестроить объект, не используя сеансы, сделайте это. Наличие состояний вашего веб-приложения делает приложение более сложным для сборки, для каждого запроса вы должны видеть, в каком состоянии находится пользователь. Конечно, есть моменты, когда вы не можете избежать использования сеанса (например: пользователь должен быть включен в систему во время сеанса веб-приложение). Последнее, что я хотел бы предложить сохранить объект сеанса как можно меньше, так как он влияет на производительность для сериализации и несериализации больших объектов.

Вы должны будете помнить, что типы ресурсов (например, соединения db или указатели файлов) не будут сохраняться между загрузками страниц, и вам необходимо будет их незаметно воссоздать.

Также рассмотрите размер сеанса, в зависимости от того, как он хранится, вы можете иметь ограничения по размеру или проблемы с задержкой.

Я бы также поднял при обновлении программных библиотек – мы обновили наше программное обеспечение, а у старой версии были объекты в сеансе с именами классов программного обеспечения V1, новое программное обеспечение терпело крах, когда пыталось построить объекты, которые были в сеансе, – поскольку V2 программное обеспечение не использовало те же самые классы больше, оно не могло их найти. Нам нужно было установить код исправления для обнаружения объектов сеанса, удалить сеанс, если он найден, перезагрузить страницу. Самая большая боль, изначально напоминающая вас, – это воссоздание этой ошибки, когда она была впервые сообщена (все слишком знакомы, «хорошо, это работает для меня» :), поскольку это затрагивало только тех, кто недавно входил в старые и новые системы, мы находили его перед запуском, так как все наши пользователи наверняка имели бы старые переменные сеанса в своих сеансах и могли бы потенциально потерпеть крах для всех, было бы ужасным запуском 🙂

В любом случае, как вы предлагаете в своей поправке, я также думаю, что лучше воссоздать объект. Поэтому возможно просто сохранить идентификатор, а затем по каждому запросу, потянув объект из базы данных, лучше / безопаснее.