1

我正在开发一个小型在线系统来对我的书籍进行分类,但是现在我已经尝试了几个小时来解决一个问题,但没有任何运气。

在我的数据库中,我有一个titles包含书籍信息(title_id、、title... author)的表和另一个包含title_relations字段title_relation_id、、title_id和。to_title_idtitlerelation

当我调用一本书的信息时,有一个字段related titles应该列出所有前传、续集和衍生产品。

数据库如下所示:

标题

标题 ID 1
指环王:魔戒联谊会
...


标题 ID 2
标题指环王:两座塔楼
...


标题 ID 3
指环王:王者归来
...

标题关系

title_relation_id 1
标题 ID 1
to_title_id 2
标题关系前传

title_relation_id 1
标题 ID 1
to_title_id 3
标题关系前传

现在我正在调用“魔戒联谊会”的信息,并希望显示“两座塔楼”和“王​​者归来”的链接。我该如何去那里获取这些信息?

我让它适用于一个标题关系,但除此之外,我还需要一个

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();
}
4

2 回答 2

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 中。
为了能够访问我创建的所有关系(array)$series,您只需将最后一行存储在(string)$series.

于 2012-06-19T13:57:59.600 回答
1

您需要能够在两个方向(前传/续集)上遍历这些关系,因此您需要搜索 byto_title_id以及 by title_id

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

递归,看看The Return of the King from the Fellowship of the Ring你最好的选择可能是运行第二个查询(如果你想更深入,第三个)然后使用一些东西将结果缓存在 json 数组/哈希结构中像内存缓存。但是,要为哈利波特基金会系列执行此操作,递归有点失控,更不用说如果您有任何星际迷航小说。

我在自己的图书馆项目中做过类似的事情,但我使用了一个series表格和一个title_series表格来存储每个标题在系列中的顺序。然后只需一次查询即可找到相关标题。

于 2012-06-19T13:58:22.083 回答