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

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

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

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


Edit:

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

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

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

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

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

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

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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