Мои таблицы структурированы следующим образом:
TAGS (больше категории): id, имя тега, описание, slug
POSTS: id, title, url …
POSTSTAGS: id, idPost, idTag
ПОЛЬЗОВАТЕЛИ: id, username, userSlug …
ГОЛОСОВ: id, idPost, idUser
У каждого сообщения может быть до пяти тегов, и каждый пользователь может голосовать только один раз. В настоящее время, поскольку теги еще не реализованы, я извлекаю свой разбитый на результат набор результатов со следующим запросом:
SELECT p.*, u.username, u.userSlug, u.id as userId, exists (select 1 from votes v where v.idUser=$id AND p.userId=v.idUser AND p.url = v.url) as voted FROM posts p JOIN users u ON u.id=p.userId ORDER BY p.created DESC LIMIT 10 OFFSET :offset
Запрос запускается через PDO и возвращается в формате JSON в angularjs ng-repeat
. Идентификатор $id
является зарегистрированным идентификатором пользователя. Я использую его в exists
подзапросе, чтобы серые кнопки голосования в моем угловом виде (есть также проверка на стороне сервера). Если кто-то щелкнет имя пользователя в представлении, он будет отправлен на страницу с подробной информацией, где будут показаны все сообщения пользователя ( userSlug
для спасения).
Следующий шаг – включить теги в список результатов, и здесь я заикался. Каждое сообщение в списке должно содержать все связанные теги (tagName, description, slug), и каждый тег должен перейти на страницу сведений, где показаны все связанные записи для этого конкретного тега.
Первое решение, которое приходило на ум, заключалось в том, чтобы выполнить свой первый шаг после выполнения ранее упомянутого запроса:
foreach ($postsResult as &$post) { $sql ="SELECT t.* FROM tags t JOIN poststags pt ON t.id=pt.idTag WHERE pt.idPost=$post->id"; $stmt=$db->prepare($sql); $stmt->execute(); $tagsResult=$stmt->fetchAll(PDO::FETCH_OBJ); $post->tags = $tagsResult; } $response->write(json_encode($postsResult));
Готово, легко peasy! Лоты запросов, которые будут создавать огромную нагрузку на сервер. И мы не хотим этого делать.
Второе решение состояло в том, чтобы запустить другой запрос, который извлекает все теги, связанные с postsResult (s), а затем вставляет соответствующие теги в каждое сообщение, позволяя PHP выполнять грязную работу.
$sql = " SELECT t.*, pt.idPost FROM tags t JOIN poststags pt ON t.id=pt.idTag WHERE pt.idPost IN (array of post ids) "; $stmt=$db->prepare($sql); $stmt->execute(); $tagsResult = $stmt->fetchAll(PDO::FETCH_OBJ); foreach ($postsResult as &$post) { $arr = array(); foreach ($tagsResult as $tag) { if ($post->id==$tag->idPost) { $arr[]=$tag; } } $post->tags = $arr; } $response->write(json_encode($postsResult));
Есть ли лучший или более быстрый способ сделать это?