Я только что понял, что на самом деле могу хранить объекты в $ _SESSION, и нахожу это довольно крутым, потому что, когда я перехожу на другую страницу, у меня все еще есть объект. Теперь, прежде чем я начну использовать этот подход, я хотел бы узнать, действительно ли это такая хорошая идея, или в ней задействован потенциальные ловушки.
Я знаю, что если бы у меня была единственная точка входа, мне бы не пришлось этого делать, но я еще не там, поэтому у меня нет единой точки входа, и я действительно хотел бы сохранить свой объект, потому что я этого не делаю. Я так не потеряю свое состояние. (Теперь я также прочитал, что мне следует программировать сайты без сохранения состояния, но я еще не понимаю эту концепцию.)
Итак, Суммируя: Можно ли хранить объекты в сеансе, есть ли с этим проблемы?
Редактировать:
Временное резюме: Сейчас я понимаю, что это, вероятно, объект лучше воссоздать, даже если он включает повторный запрос к базе данных.
Дальнейшие ответы могли бы, возможно, немного больше уточнить этот аспект!
но полезный вопрос к таким глупцам, как мы в 2014 году: D
Очень хорошие вопросы, которые вы задали Маркусу .. :) Я прочитал это сегодня;)
Ты не был дураком! Вы спросили, о чем я собирался спросить, и сделали мне твердый ответ 10 лет спустя!
ну я догадался, что вы только что спасли меня от глупого вопроса в 2019 году
Чтобы добавить к этому - я столкнулся со ВСЕМИ ВИДАМИ странных проблем с PHP 7.1, сохраняющим мой полный объект $ user в сеансе ... в конце концов, было легко просто отслеживать идентификатор пользователя и воссоздавать объект при загрузке страницы. .. и бум все мои баги исчезли.






все в порядке, если к моменту вызова session_start () объявление / определение класса уже обнаружено PHP или может быть найдено уже установленным автозагрузчиком. в противном случае он не сможет десериализовать объект из хранилища сеансов.
Спасибо! Это исправило ошибку для меня: D
Я предполагаю, что этой проблемы можно было бы избежать, если бы у вас была правильная функция __autoload().
При десериализации сериализованного объекта мы должны добавить определение класса ??? Во время сериализации объекта ему требуется определение класса, с чем я согласен, но должен ли я добавить определение класса также в файл, где я должен десериализовать сериализованный объект ???
HTTP не зря является протоколом без сохранения состояния. Сессии связывают состояние с HTTP. Как правило, избегайте использования состояния сеанса.
ОБНОВИТЬ: На уровне HTTP нет концепции сеанса; серверы предоставляют это, предоставляя клиенту уникальный идентификатор и сообщая клиенту, что он должен повторно отправлять его при каждом запросе. Затем сервер использует этот идентификатор в качестве ключа в большой хеш-таблице объектов сеанса. Всякий раз, когда сервер получает запрос, он ищет информацию о сеансе из своей хэш-таблицы объектов сеанса на основе идентификатора, отправленного клиентом с запросом. Вся эта дополнительная работа наносит двойной удар по масштабируемости (главная причина, по которой HTTP не имеет состояния).
Учитывая все это, чем больше информации вы вводите в сеанс, тем больше влияние на производительность (как указывает Винко). Также, как указывает Винко, если ваш объект не сериализуем, сеанс будет вести себя неправильно. Итак, как правило, старайтесь не вкладывать в сеанс больше, чем это абсолютно необходимо.
@Vinko Обычно вы можете обойтись без состояния хранилища сервера, встраивая данные, которые вы отслеживаете, в ответ, который вы отправляете, и заставляя клиента повторно отправлять их, например, отправляя данные в скрытом вводе. Если вам В самом деле требуется отслеживание состояния на стороне сервера, он, вероятно, должен быть в вашем резервном хранилище данных.
(Винко добавляет: PHP может использовать базу данных для хранения информации о сеансе, и если клиент повторно отправляет данные каждый раз, это может решить потенциальные проблемы масштабируемости, но открывает большую банку проблем безопасности, на которые вы должны обратить внимание теперь, когда клиент контролирует все ваше состояние)
сварить? что ты имеешь в виду? Можете ли вы объяснить свою точку зрения более подробно, и почему это практическое правило?
На уровне HTTP нет концепции сеанса; серверы предоставляют это, предоставляя клиенту уникальный идентификатор и сообщая клиенту, что он должен повторно отправлять его при каждом запросе. Затем сервер использует этот идентификатор в качестве ключа в большой хеш-таблице объектов сеанса. Продолжение следует…
Всякий раз, когда сервер получает запрос, он ищет информацию о сеансе из своей хэш-таблицы объектов сеанса на основе идентификатора, отправленного клиентом с запросом. Вся эта дополнительная работа наносит двойной удар по масштабируемости (главная причина, по которой HTTP не имеет состояния). Продолжение следует…
Интересно, как бы вы реализовали сложные приложения через HTTP без состояния сварки?
Whammy One: сокращает объем работы, которую может выполнять один сервер. Whammy Two: это затрудняет масштабирование, потому что теперь вы не можете просто направить запрос на любой старый сервер - у них не у всех одинаковый сеанс. Продолжение следует…
Вы можете закрепить все запросы с данным идентификатором сеанса на одном сервере. Это непросто, и это единственная точка отказа. Или вы можете совместно использовать хранилище сеанса на всех серверах в кластере, но теперь у вас есть более сложная задача: подключенная к сети память, автономный сервер сеанса и т. д. TBC ...
Учитывая все это, чем больше информации вы вводите в сеанс, тем больше влияние на производительность (как указывает Винко). Также, как указывает Винко, если ваш объект не сериализуем, сеанс будет вести себя неправильно. Итак, как правило, старайтесь не вкладывать в сеанс больше, чем это абсолютно необходимо. TBC…
@Vinko Обычно вы можете обойтись без состояния хранилища сервера, встраивая данные, которые вы отслеживаете, в ответ, который вы отправляете, и заставляя клиента повторно отправить, например, скрытый ввод. Если вам В самом деле требуется отслеживание состояния на стороне сервера, он, вероятно, должен быть в вашем резервном хранилище данных.
отредактируйте свой ответ, включив в него все эти комментарии. его легче читать и лучше для вики, и в любом случае я не могу выбрать ваш ответ как принятый, если все важное находится в комментариях. Благодарность!
Вы говорите так, будто сеансы - это корень всего злого кода, но это не так. На больших динамических сайтах сложно не использовать сеансы. Не уверен, что его хорошо использовать для объектов, хотя
Ваше «резервное хранилище данных» (если вы не используете сеансы) и «память, подключенная к сети» (для хранения сеансов), могут легко быть одной и той же службой, например используя MySQL в качестве хранилища сеансов. В этом случае для использования сессий нет недостатков.
"whammy one" Хотел бы я проголосовать против этого больше. Знайте свое время. Обращение к памяти стоит 100 наносекунд или 0,0001 мс. Таким образом, поиск в хеш-таблице, которая хранится в основной памяти, буквально не требует затрат времени. O(1) вам что-то говорит? @whammy two: просто не перенаправлять все запросы случайным образом на случайные серверы? выполнить циклический перебор и продолжить маршрутизацию на тот же сервер от одного и того же пользователя. Это вау, супер очевидно. Вы должны вернуться к своим книгам вместе со всеми 30+ голосами за
"Whammy Two" отменяется, если вы сохраняете сеансы в базе данных. В PHP есть метод, который делает это чрезвычайно простым (session_set_save_handler ()).
@Toskan "whammy one" не о процессоре, а о памяти. Люди неизбежно получают на сеансе много больше материала, чем они думают; это так просто. С точки зрения ЦП / времени единственная «медленная» вещь в версии сеанса на основе хеш-таблицы - это когда он должен расти: как только он станет достаточно большим, может возникнуть проблема внезапного выделения такого гигантского фрагмента непрерывной памяти. (потому что у вас может быть не так много, и вдруг сборщик мусора / среда выполнения должна переставить «свободные» страницы, компактный мусор и т. д.).
@HankGay, где я сказал, что это про процессор? Что-то, что не принадлежит сеансу, не принадлежит ему, да.
@Toskan По моему опыту, единственный способ не допустить «чего-то, что не принадлежит сеансу» - это предположить, что ничто не принадлежит сеансу, пока вы не убедите остальную команду, что это так. Даже в этом случае рекомендуется вернуться и просмотреть, потому что кто-то может случайно добавить свойство (потенциально интенсивно использующее память) к какому-либо объекту, который сериализуется в сеанс каким-либо другим фрагментом кода, и внезапно вы ' нам приходится запускать больше серверов из-за какой-то загадочной «утечки памяти». Я не возражаю, что у сеанса есть свои применения; Я просто считаю, что им злоупотребляют.
Предупреждение для всех, кто прислушивается к этому совету: да, с помощью PHP легко хранить данные сеанса в базе данных, но будьте осторожны с производительностью на загруженных серверах. Если вы выполняете более пары десятков запросов в секунду, вы увидите значительное снижение производительности. Система сеансов на основе файлов по умолчанию намного быстрее, чем база данных. Если вам нужно масштабировать несколько серверов, вы всегда можете сегментировать данные и назначить каждого пользователя определенному серверу, чтобы они никогда не теряли сеанс.
Кроме этого я не видел никаких проблем.
Вы должны помнить, что типы ресурсов (такие как соединения с базами данных или указатели файлов) не сохраняются между загрузками страницы, и вам нужно будет незаметно воссоздать их.
Также учитывайте размер сеанса, в зависимости от того, как он хранится, у вас могут быть ограничения по размеру или проблемы с задержкой.
Я бы посоветовал не использовать состояние, если оно вам абсолютно не нужно. Если вы можете перестроить объект без использования сессий, сделайте это. Наличие состояний в вашем веб-приложении делает приложение более сложным для построения, для каждого запроса вы должны видеть, в каком состоянии находится пользователь. Конечно, бывают случаи, когда вы не можете избежать использования сеанса (пример: пользователь должен сохранять логин во время его сеанса на веб-приложение). Наконец, я бы посоветовал сделать объект сеанса как можно меньшим, поскольку это влияет на производительность при сериализации и десериализации больших объектов.
Итак, не лучше ли перестроить объект, включая повторное выполнение всех запросов к базе данных? Потому что одна из моих мыслей по поводу этого заключалась в том, что мне не нужно снова запрашивать в БД то же самое.
Если для вас важно, чтобы он больше не запрашивал базу данных, используйте кеширование вместо сохранения в сеансе. Но, пожалуйста, прежде чем делать что-либо вроде кэширования, проверьте, действительно ли это снижает производительность.
Спасибо, я вообще-то думаю, что это не так. Я должен просто запросить еще раз.
По моему опыту, ничего более сложного, чем StdClass с некоторыми свойствами, обычно не стоит. Стоимость десериализации всегда была больше, чем воссоздание из базы данных с использованием идентификатора, хранящегося в сеансе. Вроде круто, но (как всегда) ключевым моментом является профилирование.
Любые комментарии по производительности между запросом таблицы данных 5x2 при каждом запросе и кешированием результата в сеансе и его использованием?
Я знаю, что эта тема устарела, но эта проблема продолжает появляться и не была решена, чтобы я был удовлетворен:
Независимо от того, сохраняете ли вы объекты в $ _SESSION или реконструируете их целиком на основе данных, хранящихся в скрытых полях формы, или повторно запрашиваете их из БД каждый раз, вы используете состояние. HTTP не имеет состояния (более или менее; но см. GET vs. PUT), но почти все, что кто-то хочет сделать с веб-приложением, требует, чтобы состояние где-то сохранялось. Совершенно неправильно вести себя так, как будто загонять государство в укромные уголки и закоулки - это своего рода теоретическая победа. Состояние есть состояние. Если вы используете состояние, вы теряете различные технические преимущества, полученные от безгражданства. Это не то, из-за чего можно потерять сон, если вы заранее не знаете, что вам следует потерять сон из-за этого.
Меня особенно сбивает с толку благословение, полученное от аргументов «двойной удар», выдвинутых Хэнком Гаем. Создает ли OP распределенную и сбалансированную систему электронной коммерции? Думаю, нет; и далее я буду утверждать, что сериализация его класса $ User или чего-то еще не нанесет непоправимый урон его серверу. Мой совет: используйте подходящие для вашего приложения методы. С объектами в $ _SESSION все в порядке, при условии соблюдения здравого смысла. Если ваше приложение внезапно превратится во что-то, что может конкурировать с Amazon по обслуживаемому трафику, вам нужно будет заново адаптироваться. Это жизнь.
Хороший ответ, включающий в себя множество моих собственных мыслей, пока я читал это. Современное состояние Интернета потребности. В то время как некоторым приложениям не требуется состояние и имеет смысл создавать без отслеживания состояния, современный Интернет полагается на слишком много систем, основанных на состоянии (также известные как логины!), Чтобы просто отказаться от них! Великие боги Интернета в течение многих лет даже включали эту базовую концепцию в виде файлов cookie, а на базовом уровне они добавили ее в виде локального хранилища в HTML. Возможно, имеет смысл избегать чрезмерного использования состояния в приложениях немного, но некоторые! = Все!
Что ж, когда я задал этот вопрос вскоре после того, как человек изобрел огонь, я не знал многого из того, что знаю сегодня ... что тоже хорошо. А пока я бы сказал, что может быть несколько хороших вариантов использования, но в целом я сначала поищу другие решения. Все еще помечаю это как новый принятый ответ, потому что другой ответ категорический.
Очень немногие ответы заставляют меня смеяться вслух. Этот сделал. Браво +1
Я бы также упомянул при обновлении программных библиотек - мы обновили наше программное обеспечение, и в старой версии были объекты в сеансе с именами классов программного обеспечения V1, новое программное обеспечение вылетало, когда оно пыталось построить объекты, которые были в сеансе - как V2 программное обеспечение больше не использовало те же классы, оно не могло их найти. Нам пришлось добавить код исправления, чтобы обнаруживать объекты сеанса, удалять сеанс, если он найден, перезагружать страницу. Самая большая неприятность, которую вы изначально представляли, заключалась в том, что вы воссоздали эту ошибку, когда о ней впервые было сообщено (слишком знакомо, «ну, это работает для меня» :), поскольку она затрагивала только людей, которые в последнее время вводили и выключали старые и новые системы - тем не менее, хорошо работу, которую мы нашли перед запуском, так как все наши пользователи наверняка имели бы старые переменные сеанса в своих сеансах и потенциально потерпели бы сбой для всех, это был бы ужасный запуск :)
В любом случае, как вы предлагаете в своей поправке, я также считаю, что лучше воссоздать объект. Так что, возможно, лучше / безопаснее просто хранить идентификатор, а затем при каждом запросе извлекать объект из базы данных.
Каким «глупым» я был в 2008 году :-)