Расширенные настройки доступа к стате. Как правильно делать выборку?

  • Автор темы Автор темы Spear
  • Дата начала Дата начала

Spear

почемучка
Расширенные настройки доступа к стате. Как правильно делать выборку?

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

Собственно, если бы небыло последних 3 пунктов то сделать это несложно: в таблице просто поле privacy_level. Потом, например:
select * from news where privacy_leve = '2' // если пользователь зарегистрировался

но как правильно делать выборку, если опубликованный материал могут просматривать только определенные пользователи? НапримеР, пользователи с айдишником 50 и 80?

Пока что вариант есть только очень "тяжелый" в плане производительности - выбираю все статьи из бд, пишу в массив. а потом прохожу по массиву и делаю unset() тех, на которые нет прав просмотра.

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

Использовать громоздкие опенсорцные (если такие есть) системы для контроля доступа не представляет возможности, т.к. они, собсно, громоздкие. Мне нужно понять как правильно это делается и сделать самому, по максимуму минимизировав ненужные "фичи", которые могут предлагать опенсорцные проекты (если таковые имеются).

Подскажите пожалуйста!
 
но как правильно делать выборку, если опубликованный материал могут просматривать только определенные пользователи?
госспади, а зачем это нужно?

может хранить соответствия статья|ид_пользователя|право_на_чтение?
 
На примере предпоследнего случая (определенным друзьям):
задействованы две сущности: Новости news (ID - newsId, автор- userId) и Юзеры_имеющие_связь_с_новостью news_users (newsId,userId)
далее перед формированием запроса для всех зарегистрированных пользователей
//Сначала все доступные зарегистрированным и авторские
$where="privacy_leve < 3";
$where.=" or userId='$userId'";// $userId- авторизационные данные
//Затем добавляем условия просто друзей из friends (userId1,userId2)
$where.=" or (privacy_level=3 and userId in
(select if($userId=userId1,userId2,userId1)* from friends where $userId in (userId1,userId2))
)";
*я не помню, как там точно в mysql
//Затем добаляем условия предпоследнего случая
$where.=" or newsId in (select newsId from news_users where userid=$userId)";

Ну и:
select * from news where $where
 
prolis, запомни, если есть подзапрос в WHERE, то он исполняется для каждой строки основной таблицы запроса. такое надо через JOIN делать и по индексированным полям. потом лишнее группировать - в итоге один только раз временную таблицу будем строить при группировке, но уже для малого (по сравнению с исходной таблицей) кол-ва строк
 
dimagolov
дабы не флеймить, соглашусь с оговоркой, что это правильно не во всех случаях (объемах данных). Вопрос оптимизации в вопросе не стоит, а простота понятия подхода налицо.
 
prolis, ты бы лучше нормально оформлял свой код в постах, для "простоты понятия" и не отстаивал глупости. потому что для новичков абсолютно не очевидно, что подзапрос в where выполниться столько раз, сколько строк тестируется в основном запросе, а не 1 раз. это потому, что подзапрос может включать поля из основного запроса. а приучившись так писать они потом на раз-два опускают сервера, когда всего лишь в основном и вложенном запросе where по паре тысяч записей (что реально децил и достигается на раз).
 
Сверху