Вопрос

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

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

Так суммируя:Можно ли хранить объекты в сессии, есть ли с этим проблемы?


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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

В остальном проблем не увидел.

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top