我正在开发一个小型的在线系统来对我的书进行排序,但是偶然发现了一个问题,我已经花了好几个小时才解决这个问题。
在我的数据库中,我有一个表格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
现在我正在调用 The Ring of Fellowship of the Ring 的信息,并希望显示 The Two Towers 和 The King of the Return的链接。我如何在那里获取这些信息?
我让它为一个标题关系工作,但不仅如此,我需要一个
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(); }
当前代码(正在工作!):</ p>
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 :(得分: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,这是基于你的代码,我不想在while循环中做出选择,我只会使用像上面版本那样的单个查询(或者它的变体)。
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的while中移动了最后一个查询
为了能够访问我创建(array)$series
的所有关系,您只需将最后一行存储在(string)$series
中。
答案 1 :(得分:1)
您需要能够双向遍历这些关系(前传/续集),因此您需要按to_title_id
以及title_id
进行搜索。
SELECT * FROM title_relations WHERE title_id = ? OR to_title_id = ?
要递归,并从戒指团契中看到王者归来,你最好的选择可能是运行第二个查询(如果你想要的话,还有第三个查询)更深入)然后使用memcache之类的东西将结果缓存在json数组/哈希结构中。但是,要为 Harry Potter 或 Foundation 系列执行此操作,递归会失控,更不用说如果您有任何星际迷航小说。
我已经从我自己的库项目中做了类似的事情,但是我使用了一个series
表和一个title_series
表来存储系列中每个标题的顺序。然后它只需要一个查询来查找相关的标题。