Т.е к примеру я авторизую пользователя на сайте, создаю сессию и ее ID записываю в куку.
Далее, у пользователя есть куча данных, его логин, ID, ID всех городов, стран и областей проживания, его почта, теелфон и т.д. Все это может хранится в нескольких таблицах. Доступ к этим данным необходим если не на каждой странице то очень часто и везде дергать MySQL выбирая нужные данные, пускай и универсально, не очень хочется.
Возникает вопрос, стоит ли хранить всю пачку данные привязывая их к сессиям и как это сделать универсальнее, дабы потом легко эти данные выдергивать.
То есть дублировать данные в БД, реализовав собственный механзим сохранения сессионных данных? Имхо, не стоит, если нет каких-то очень специфических требований — или дёргайте БД при каждом запросе или дёргайте её только при аутентификации и пользуйтесь стандартными средствами сессий для сохранения полученных из БД данных для дальнейшего использования
1. Данные сессии — временные, отталкивайтесь от этого.
2. В вопросе, судя по всему, речь идет о постоянных данных — их хранить в профилях пользователей в базе.
3. Если не хотите каждый раз дергать базу, хотя в этом нет ничего плохого, делайте кеширование.
4. В PHP есть встроенный механизм сессий, свой изобретать не нужно. Бекэнды могут быть разные — файлы, БД, memcached, можно реализовать свой.
>3. Если не хотите каждый раз дергать базу, хотя в этом нет ничего плохого, делайте кеширование.
Хранение в сессии копии часто запрашиваемых (и обычно ассоциированных с конкретным клиентом) данных по сути и есть кэширование (по умолчанию через файлы) запросов к БД на получение этих данных. И в каких-то ситуациях это может быть самым простым и даже самым эффективным способом такое кэширование организовать (а в каких-то и заморачиваться не стоит)
просто зачем дергать базу при каждом рефреше страницы, при серфинге сайта, если данные можно закэшировать? а если пользователь, скажем, в своих настройках что-то поменял, то кэш убивается и записывается заново.
Зачем? Если, я почти уверен, эти же данные хранятся в таблице рядом. Храните только информацию которая позволит узнать пользователя и его незавершенную сессию, а как следствие и восстановить данные в $_SESSION Вашего приложении.
Не очень хочется — не всегда правильно. Например, разбейте пользовательские данные на классы-хранилища внутри объекта пользователя и подгружайте по надобности.
Думаете вы в верном направлении, вот только с сессией чуток ошиблись.
Почему забыли?
Давай-те вспомним причинно-следственную связь: Сессия — это объект кого-то конкретного пользователя (ранее аутентифицированого), соответственно сохраняя данные о пользователе в сессии вы нарушаете причину и следствие.
Предлогаю использовать следующее:
Создать статический класс (думаю это возможно в PHP. В .NET за это отвечает System.Threading.Thread.CurrentPrincipal). И данные текущего пользователя складывать именно в значение свойства статического класса. (Да, есть возможность не санкционированной подмены данных, но с другой стороны можно проводить имперсонализацию (impersonation). А само значение организовать ввиде структуры, которая бы могла быть сериализирована.
Сериализация этой структуры нужно для того, что бы после этого результат шифровать (там есть свои нюансы) и ввиде ОТДЕЛЬНОЙ Cookie складывать на сторону пользователя. А при запросе проверять значение cookie, и востанавливать значение свойства вышеозначеного статического класса.
Подобный подход упростит вам аутентификацию пользователя после перезапуска приложения (ведь сессия — это объект в памяти).
Важные моменты:
1. Не корректное использование шифрования, может привезти к проблемам с безопасностью (значение зашифрованых данных можно сохранить и вторично использовать)
2. Не забыть про синхронизацию данных и учитывать момент того, что во время работы могут быть моменты когда данные рассинхронизированы
(Кто-то в базе уже поменял, а пользователь всё ещё использует старый набор данных. Лечить можно login/logout, если «влоб»).
В PHP сессии первичны по отношению к аутентификации. Данные об аутентификации, например ID пользователя, хранятся в сессиях. И это не обязательно объект в памяти, могут быть персистентные хранилища.
Сначала пользовательских данных в сессии нет, но сама сессия есть (т. н. анонимная), затем пользователь аутентифицируется и его id сохраняется в сессии (может в той же, может стартовать новая). Можно сохранить не только id, но и набор любых других данных, включая, например, объекты User и UserProfile, ведь по сути сессия — ассоциированый массив любых сериализуемых данных, связанный с кукой (или другим параметром http запроса). Сохранение сессии между http запросами обеспечивается прозрачно для программиста средствами транслятора (то есть это свойство языка, а не библиотека или враппер/мидлваре, как во многих других языках) и по умолчанию реализовано на файлах (а не в памяти). Хранить какие-то, тем более закрытые, данные приложения в отдельных куках (если срок их хранения не больше времени жизни сессии), как правило, смысла нет; там хранить нужно данные, которые должны переживать сессию (например настройки логина, такие как «запомнить меня»)
Опять-таки, сначало появляется анонимный пользователь, а потом сессия.
После вторичной аутентификации, сессия начинает принадлежать аутентифицированом пользователю (пусть даже и косвенно, через ID).
Соглашусь с вами только в специфики реализации, что в PHP сессия создаётся (физически раньше), но с точки зрения работы — сначало аутентификация, потом сессия. Кстати, вариант который есть в PHP (если я не ошибаюсь) весьма странный, т.к. SESSION_ID ОБЩАЯ как для анонимного пользователя, так и аутентифицированого. Это может приводить к «грязным данным» оставшихся после предыдущего пользователя.
И вообще сессия — это механизм сохранения СОСТОЯНИЯ в stateless запросах (коим является HTTP Request). Но уж ни как для хранения данных об аутентификации/авторизации.
Да, 99% всех реализаций используют сессию как им нравится, но это не совсем корректно с точки зрения назначения сессии.
>Опять-таки, сначало появляется анонимный пользователь, а потом сессия.
Ну если исходить из того, что сначала клиент отправляет запрос к серверу, то да :)
>Кстати, вариант который есть в PHP (если я не ошибаюсь) весьма странный, т.к. SESSION_ID ОБЩАЯ как для анонимного пользователя, так и аутентифицированого. Это может приводить к «грязным данным» оставшихся после предыдущего пользователя.
В PHP вообще нет понятия «пользователь» как такового (как и во многих, по-моему, языках). Разработчик может сам управлять логикой создания и самой сессии, и её Id. Часто при действиях типа login/logoff разработчики меняют sid (хотя мне это кажется излишеством или паранойей :) — имхо, достаточно сбросить данные сессии.
>И вообще сессия — это механизм сохранения СОСТОЯНИЯ в stateless запросах (коим является HTTP Request). Но уж ни как для хранения данных об аутентификации/авторизации.
А данные об аутентификации разве не являются как раз состоянием? Без них пользователю бы пришлось аутентифицироваться при каждом запросе. Использовать при их хранении в сессии связи/отношения (хранить только user_id) или композицию/агрегацию (хранить «развёрнутый» объект User) вопрос даже не архитектуры, по-моему, а достаточно низкоуровневой реализации, которую часто абстрагируют.
Примерно об этом я и говорю. Т.е пользователь авторизуется, кладется информация о нем в сессию, затем проверяется, сессия пустая или нет, если нет — данные берутся из нее, если да то перезаписывается данными из БД.
Вопрос в другом, каким образом лучше организовать харнение. Записать в сессию класс, записать сериализованный масив в базу и т.д.
так делать не стоит, потому что нельзя влиять на эти данные потому что они в сессии.
вот допустим, есть статус актив/бан, юзер авторизовался, дернули из бд статус актив, потом его забанили (статус бан), но в сессии-то все равно актив…
Это поможет, если пользователь сам себя забанил :) Либо нужно глубоко (вплоть до бинарной правки данных в памяти/файле/бд) вмешиваться в работу механизма сессии, а обычно скрипт имеет доступ только к своей сессии.