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

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

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

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


Edit:

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

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

8 ответов


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

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

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


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


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

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

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

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

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

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


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

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


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


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


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

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


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

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