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

Spear

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

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

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

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

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

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

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

Подскажите пожалуйста!
 

Духовность™

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

может хранить соответствия статья|ид_пользователя|право_на_чтение?
 

prolis

Новичок
На примере предпоследнего случая (определенным друзьям):
задействованы две сущности: Новости 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
 

dimagolov

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

prolis

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

dimagolov

Новичок
prolis, ты бы лучше нормально оформлял свой код в постах, для "простоты понятия" и не отстаивал глупости. потому что для новичков абсолютно не очевидно, что подзапрос в where выполниться столько раз, сколько строк тестируется в основном запросе, а не 1 раз. это потому, что подзапрос может включать поля из основного запроса. а приучившись так писать они потом на раз-два опускают сервера, когда всего лишь в основном и вложенном запросе where по паре тысяч записей (что реально децил и достигается на раз).
 
Сверху