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

Из поваренной книги Symfony 2: Понимание сериализации и способа сохранения пользователя в сеансе:

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

и

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

Почему необходимо, чтобы Symfony извлекал объект User из базы данных по каждому запросу?

В каких обстоятельствах сериализованный объект User, который хранится в данных сеанса, не совпадает с объектом User, полученным из базы данных? Разумеется, Symfony знает, когда объект User изменяется, и может просто обновить данные сеанса, когда это произойдет?

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

Ответ 1

Отказ от ответственности: я не знаю Symfony специально, так что это написано из общих знаний PHP и нескольких допущений.

Сессия PHP обычно не поддается манипулированию со стороны - это всего лишь сериализованная капля данных в хранилище файлов или памяти. Единственный способ изменить его - десериализировать его, внести изменения и повторно выполнить все это, что обычно делается только тогда, когда вы находитесь в этой сессии.

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

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


Как сказал haltabush в комментарии: если пользователь извлекается по каждому запросу, зачем его сериализовать вообще?

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

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

Ответ 2

При каких обстоятельствах сериализованный объект User, который хранится в данных сеанса, не совпадает с объектом User, полученным из базы данных?

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

Несомненно, Symfony знает, когда изменяется объект User, и может просто обновить данные сеанса, когда это произойдет?

Нет, если это изменение не связано с сеансом пользователя, как это имеет место в вышеупомянутом сценарии.