2016-11-15 3 views
2

У меня есть сайт, заполненный статьями, и я хотел был бы иметь возможность заказать их по тегам. Каждая статья имеет несколько связанных тегов.MySQL не показывает данные

Я использую 3 таблицы:

Medias (Подставка для статей)

+----+--------+-----+ 
| id | title | ... | 
+----+--------+-----+ 
| 1 | hello | ... | 
| 2 | hi  | ... | 
+----+--------+-----+ 

теги

+----+------+-----+ 
| id | name | ... | 
+----+------+-----+ 
| 1 | red | ... | 
| 2 |square| ... | 
+----+------+-----+ 

medias_tags (Для того, чтобы связать теги & СМИ вместе)

+----+----------+--------+ 
| id | media_id | tag_id | 
+----+----------+--------+ 
| 1 |  1 |  1 | 
| 2 |  1 |  2 | 
| 3 |  2 |  2 | 
+----+----------+--------+ 

До сих пор я использую этот MySQL/PHP код заказа статей по тегам, который работает (я намеренно удалены условия для нумерации страниц лучшего понимания):

$ BDD

try{ 
    $bdd = new PDO('mysql:host=localhost;dbname=DB;charset=utf8', 'username', 'pass');}catch(Exception $e) { die('Erreur : '.$e->getMessage()); 
} 



if(isset($_GET['tag'])){ 
    $tag_name_1 = htmlspecialchars($_GET['tag']); 
    $req_tag = $bdd->prepare('SELECT * FROM tags WHERE name = ?'); 
    $req_tag->execute(array($tag_name_1)); 
    $data_tag = $req_tag->fetch(); 
    $ttag_id = $data_tag['id'];  

    $q = 'SELECT * 
      FROM medias 
      JOIN medias_tags 
      ON medias.id=medias_tags.media_id 
      WHERE medias_tags.tag_id ='.$ttag_id.' 
      ORDER BY date DESC 
      LIMIT '.$start.','.$limit;  
    } 

    $req_mda_list = $bdd->query($q); 

Проблема в том, когда я хочу отобразить все теги, связанные с этой статьей. $ mda_tags_list пусто.

while ($data_mda = $req_mda_list->fetch()){ 

    $mda_id = $data_mda['id']; 
    $mda_title = $data_mda['title']; 

    #Get media tags 
    $req_mda_tags = $bdd->prepare('SELECT * FROM medias_tags WHERE media_id = ?'); 
    $req_mda_tags->execute(array($mda_id));  

    $mda_tags_list = null; 

    while ($data_mda_tags = $req_mda_tags->fetch()){ 
     $tag_id = $data_mda_tags['tag_id']; 

     $req_tag_name = $bdd->prepare('SELECT * FROM tags WHERE id = ?'); 
     $req_tag_name->execute(array($tag_id)); 
     $data_tag_name = $req_tag_name->fetch(); 

     $mda_tags_list .= '<a href="http://www.website.com/tags/'.$data_tag_name['name'].'">'.$data_tag_name['name'].'</a> '; 
} 

    echo $mda_title.' - '.$mda_tags_list; 

} 

То, что я на самом деле получить:

Order by tag -> Square 

Title1 - Tag : 
Title5 - Tag : 
Title6 - Tag : 

То, что я пытаюсь получить:

Order by tag -> Square 

Title1 - Tag : Square, Red, Thank 
Title5 - Tag : Yellow, Square, You 
Title6 - Tag : Square, Blue, Stackoverflow 
+0

Вы уверены, что ваши переплетные работы? Странно, что вы используете переменные в своем первом выборе напрямую, а во втором и третьем вы используете привязку параметров. Что такое $ bbd? Вы используете PDO напрямую, слой абстракции библиотеки или собственный уровень абстракции? –

+1

Почему бы не объединить ваши два запроса в тег 'SELECT * FROM 'WHERE id IN (SELECT tag_id FROM medias_tags WHERE media_id =?)'? Таким образом, вам не нужно будет так часто обращаться к базе данных. Я согласен, что что-то кажется неправильным; вы можете посмотреть ошибки PDO с помощью метода '' errorInfo' (http://php.net/manual/en/pdo.errorinfo.php). –

+0

@ R.Chappell Я редактировал свой вопрос с помощью $ bdd (db). Причина, по которой я использую переменные в моем первом выборе и ожидании во второй, заключается в том, что я в значительной степени копирую/вставляю свой сценарий разбивки на страницы. Однако я не думаю, что это может быть проблемой? – casusbelli

ответ

1

Что я сделал упрощен код, Я уменьшил свой SQL вниз на одно выступление, и я добавил некоторые основные проверки ошибок:

$tagName = htmlspecialchars($_GET['tag']); 

$sql = "SELECT 
     medias.*, 
     GROUP_CONCAT(tags2.name) AS allTags 
    FROM 
     medias 
     -- Get the media tags 
     JOIN medias_tags ON medias.id = medias_tags.media_id 
     -- Join on the tags so we can add a where condition 
     JOIN tags ON medias_tags.tag_id = tags.id 
     -- Rejoin tags again, this won't be used as a condition hence the left 
     LEFT JOIN tags AS tags2 ON medias_tags.tag_id = tags2.id 
    WHERE 
     -- Only get medias where it has a matching tag name 
     tag.name = :name 
    GROUP BY 
     medias.id 
    ORDER BY 
     date DESC 
    LIMIT 
     :offset, :limit"; 

$sth = $bdd->prepare($sql); 

// Did it prepare ok? 
if (!$sth) { 
    echo "\nPDO::errorInfo():\n"; 
    print_r($dbh->errorInfo()); 
    exit; 
} 

$err = $sth->execute(array(':name' => $tagName, ':offset' => $start, ':limit' => $limit)); 

// Did it execute ok? 
if (!$sth) { 
    echo "\nPDO::errorInfo():\n"; 
    print_r($dbh->errorInfo()); 
    exit; 
} 

foreach ($sth->fetchAll() as $row) { 
    $tags = explode(',', $row['allTags']); 

    echo $row['title'] . ' - '; 

    foreach ($tags as $tag) { 
     echo '<a href="http://www.website.com/tags/' . $tag . '">' . $tag . '</a> '; 
    } 
} 

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

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

+0

Обнаружили, что ошибка исходила из medias_tags ['id'], которая испортилась с помощью medias ['id']. Теперь работает. Благодаря :) – casusbelli

1

для медиа, чтобы получить все теги, вы можете использовать запрос ниже:

SELECT medias.id,medias.title,GROUP_CONCAT(tags.name) as tag 
FROM medias 
JOIN medias_tags ON medias.id = medias_tags.media_id 
JOIN tags ON medias_tags.tag_id = tags.id 
GROUP BY medias.id 

Чтобы получить все медикаменты вместе с тегами, если avai Lable еще пустой, то можно использовать следующий запрос:

SELECT medias.id,medias.title,GROUP_CONCAT(tags.name) as tag 
FROM medias 
LEFT JOIN medias_tags ON medias.id = medias_tags.media_id 
LEFT JOIN tags ON medias_tags.tag_id = tags.id 
GROUP BY medias.id