我的PDO图书数据库需要帮助

时间:2012-06-19 13:24:27

标签: php sql pdo

我正在开发一个小型的在线系统来对我的书进行排序,但是偶然发现了一个问题,我已经花了好几个小时才解决这个问题。

在我的数据库中,我有一个表格titles,其中包含图书信息(title_idtitleauthor ...)和第二张表title_relations字段为title_relation_idtitle_idto_title_idtitlerelation

当我打电话给一本书的信息时,有一个字段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();
}

2 个答案:

答案 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表来存储系列中每个标题的顺序。然后它只需要一个查询来查找相关的标题。