2012-06-19 5 views
1

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

В моей базе данных у меня есть таблица titles с информацией о книге (title_id, title, author ...) и второй таблицей title_relations с полями title_relation_id, title_id, to_title_id и titlerelation.

Когда я обращаюсь к информации о книге, есть поле related titles, которое должно перечислить все приквелы, сиквелы и побочные эффекты.

База данных выглядит следующим образом:

названия

title_id 1 
title  Lord of the Rings: The Fellowship of the Ring 
... 


title_id 2 
title  Lord of the Rings: The Two Towers 
... 


title_id 3 
title  Lord of the Rings: The Return of the King 
...

title_relations

title_relation_id 1 
title_id    1 
to_title_id   2 
titlerelation  prequel 

title_relation_id 1 
title_id    1 
to_title_id   3 
titlerelation  prequel 

Теперь я ВЫЗОВ информацию для Братство Кольца и хотите, чтобы были показаны ссылки на Две башни и Возвращение короля. Как мне получить информацию?

Я получил это работает для одного заголовка отношения, но больше, чем я был бы нужен

foreach($title_relations as $row) { 
} 

, в котором хранит информацию от title_relations в переменных ($to_title_id_1, $titlerelation_1, $to_title_id_2, $titlerelation_2, .. .), массив или что-то еще подобное.

Ничего не пробовал работать, поэтому любая предлагаемая помощь будет высоко оценена.

Я использую PDO для получения информации о базе данных.

Старый код (не работает):

try { 
$dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
$dbh->exec("SET CHARACTER SET utf8"); 

if($page == 'title'){ 
    #titles zuordnen 
    $titles = $dbh->prepare("SELECT * FROM titles WHERE title_id = $id"); 
    $titles->execute(); 

    while($row = $titles->fetch(PDO::FETCH_OBJ)) { 
     $title = $row->title; 
     /* deleted the other infos */ 
    } 

    #title_relations zuordnen 
    $title_relations = $dbh->prepare("SELECT * FROM title_relations WHERE title_id = $id"); 
    $title_relations->execute(); 

    while($row = $title_relations->fetch(PDO::FETCH_OBJ)) { 
     $to_title = $row->to_title_id; 
     $relation_type = $row->titlerelation; 
    } 

    #to_title Seriennamen zuordnen 
    $series_name = $dbh->prepare("SELECT * FROM titles WHERE title_id = $to_title"); 
    $series_name->execute(); 

    while($row = $series_name->fetch(PDO::FETCH_OBJ)) { 
     $series = $row->title; 
    } 
} 

#Datenbank schließen 
$dbh = null; } catch(PDOException $exceptionpdo){ 
echo 'ERROR: ' . $exceptionpdo->getMessage(); } 

Текущий код (работает!):

try { 
    $dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
    $dbh->exec("SET CHARACTER SET utf8"); 

    if($page == 'title'){ 
     // titles zuordnen 
     // Here I binded the $id in execute, not in prepare 
     $titles = $dbh->prepare("SELECT title FROM titles WHERE title_id = ?"); 
     $titles->bindParam(1, $id, PDO::PARAM_INT); 
     $titles->execute(); 

     // Here you are expecting a single row, I guess title_id is a primary key, so you don't needa loop 
     $row = $titles->fetch(PDO::FETCH_OBJ); 
     $title = $row->title; 

     // title_relations zuordnen 
     $title_relations = $dbh->prepare("SELECT title_relation_id, title_id, to_title_id, titlerelation FROM title_relations WHERE title_id = ?"); 
     $title_relations->bindParam(1, $id, PDO::PARAM_INT); 
     $title_relations->execute(); 

     $series = array(); // In this array we will store all the related titles 

     while($row = $title_relations->fetch(PDO::FETCH_OBJ)) { 
      // zu_title Serieninfo zuordnen 
      $series_info = $dbh->prepare("SELECT title_id, title FROM titles WHERE title_id = ?"); 
      $series_info->bindParam(1, $row->to_title_id, PDO::PARAM_INT); 
      $series_info->execute(); 

      while($row = $series_info->fetch(PDO::FETCH_OBJ)) { 
       $series[] = $row;   
      } 
     } 

    #Datenbank schließen 
    $dbh = null; 
} 

} catch(PDOException $exceptionpdo){ 
    echo 'ERROR: ' . $exceptionpdo->getMessage(); 
} 
+0

Можете ли вы показать, как вы его работали для одного титульного отношения, пожалуйста? – Ryan

+0

Пожалуйста, покажите свой запрос. Вы используете 'JOIN'? –

+0

Разве вы не должны хранить обратную связь где-нибудь? (Title_id = 2, to_title_id = 1, titlerelation = sequel) '? – Wrikken

ответ

1

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

// Your get this from whatever, $_GET ... etc ... 
$title_id = 1; // exemple id1 = Lord of the Rings: The Fellowship of the Ring 

$sth = $dbh->prepare('select t1.title, t2.title 
     from titles as t1 
     left join title_relations as trel on (t1.title_id=trel.title_id) 
     left join titles as t2 on (t2.title_id=trel.to_title_id) 
     where t1.title_id=?'); 
$sth->bindParam(1, $title_id, PDO::PARAM_INT); 
$sth->execute(); 
$result = $sth->fetchAll(); 

// original title 
echo $result[0]['title']; 

// related title 
foreach($results as $row) 
{ 
    echo "\t".$row['title']; 
} 

@update
на основе кода, рабочая версия будет:
@disclaimer, это зависит от вашего кода, я не recomanding сделать выбор в цикле в то время, я буду просто используйте один запрос, например, версию выше (или ее вариант).

try 
{ 
    $dbh = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); 
    $dbh->exec("SET CHARACTER SET utf8"); 

    if($page == 'title') 
    { 
     $series = array(); // In this array we will store all the related titles 

     // titles zuordnen 
     // Here I binded the $id in execute, not in prepare 
     $titles = $dbh->prepare("SELECT title_id, title, author /*put your other columns*/ FROM titles WHERE title_id = ?"); 
     $titles->bindParam(1, $id, PDO::PARAM_INT); 
     $titles->execute(); 

     // Here you are expecting a single row, I guess title_id is a primary key, so you don't needa loop 
     $row = $titles->fetch(PDO::FETCH_OBJ); 
     $title = $row->title; 
     /* deleted the other infos */ 

     // title_relations zuordnen 
     $title_relations = $dbh->prepare("SELECT title_relation_id, title_id, to_title_id, titlerelation FROM title_relations WHERE title_id = ?"); 
     $title_relations->bindParam(1, $id, PDO::PARAM_INT); 
     $title_relations->execute(); 

     while($row = $title_relations->fetch(PDO::FETCH_OBJ)) 
     { 
      // This is in a loop, it will store just the value from the last row ! 
      // $relation_type = $row->titlerelation; 

      // to_title Seriennamen zuordnen 
      $series_name = $dbh->prepare("SELECT title_id, title, author /*put your other columns*/ FROM titles WHERE title_id = ?"); 
      $series_name->bindParam(1, $row->to_title_id, PDO::PARAM_INT); 
      $series_name->execute();  

      while($row = $series_name->fetch(PDO::FETCH_OBJ)) 
      { 
       // $series = will store the values just from the last row, changed it to an array to store all relations 
       $series[$row->title_id] = $row->title; 
      } 
     } 
    } 

    // Datenbank schließen 
    $dbh = null; 
} catch(PDOException $exceptionpdo) 
{ 
    echo 'ERROR: ' . $exceptionpdo->getMessage(); 
} 

Ваш код возврата только одно отношение, потому что запрос-е изд только последняя строка, возвращенная из title_relations. Чтобы решить эту проблему (again in the context of your code), я переместил последний запрос во время title_relations.
Чтобы иметь доступ ко всем отношениям, я сделал (array)$series, вы просто сохраните последнюю строку в (string)$series.

+0

Я добавил соответствующий код к своему сообщению. Думал, что было бы лучше, чтобы не мешать вам, ребята, мысли. Кажется, я ошибался ^^ В вашем примере вы непосредственно выводите результаты, знаете ли вы способ сохранить их в переменных/массиве для последующего использования? – spiel

+0

@spiel: обновить рабочий код на основе исходного кода, если у вас есть какие-либо другие неясности, пожалуйста, спросите. –

+0

Вау, большое вам спасибо за это! Работает как прелесть с небольшим изменением: D Мне пришлось перемещать привязки так: '$ titles-> bindParam (1, $ id, PDO :: PARAM_INT);' потому что я получил следующее сообщение об ошибке 'Warning: PDOStatement :: execute() ожидает не более 1 параметра, 3 задается в xxx.php в строке 86'. Я поставил весь обновленный код в нижней части моего исходного вопроса. – spiel

1

Вам необходимо пройти эти отношения в обоих направлениях (prequel/sequel), чтобы вам нужно было искать по to_title_id, а также по title_id.

SELECT * FROM title_relations WHERE title_id = ? OR to_title_id = ?

Для рекурсии, и увидеть Возвращение короля из Братства Кольца ваш лучший выбор, вероятно, запускать второй запрос (и третий, если вы хотите пойти глубже) затем кешируйте результаты в структуре json array/hash, используя что-то вроде memcache. Тем не менее, чтобы сделать это для Гарри Поттер или Фонд серия рекурсия немного вышла из-под контроля, не говоря уже о том, что у вас есть Star Trek романов.

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

+0

Да, 'to_title_id' будет добавлен после того, как я получу первую часть работы :) Я даже не слышал о memcache, это потребует некоторого чтения: s – spiel

Смежные вопросы