1

私は自分の本を分類するための小さなオンライン システムに取り組んでいますが、何時間も解決しようとしている問題に出くわしました。

私のデータベースにはtitles、本の情報 ( title_idtitleauthor...) を持つテーブルtitle_relationsと、フィールドtitle_relation_idtitle_id、を持つ 2 番目のテーブルがto_title_idありますtitlerelation

本の情報を呼び出すと、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
タイトル関係 前日譚

今、私は指輪の交わりの情報を呼び出しており、 2 つの塔王の帰還へのリンクを表示したいと考えています。そこにある情報を入手するにはどうすればよいですか?

1 つのタイトル関係で機能するようになりましたが、それ以上の場合は

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

この回答をよりよく理解し、特定のニーズに適合させるために、クエリを提供する必要があります。
私が考えることができる最も単純な例がなければ、基本的には、左結合を使用した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から返された最後の行だけをクエリしたため、コードは1つのリレーションのみを返します。これを解決するために(again in the context of your code)title_relationsのwhileの最後のクエリを移動しました。
私が作成したすべての関係にアクセスできるようにするには(array)$series、最後の行をに格納するだけです(string)$series

于 2012-06-19T13:57:59.600 に答える
1

これらの関係を両方向(前編/後編)でトラバースできる必要があるため、で検索する必要がありto_title_idますtitle_id

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

再帰して、The Fellowship oftheRingからのTheReturnof the Kingを確認するには、おそらく2番目のクエリ(さらに深く知りたい場合は3番目のクエリ)を実行してから、何かを使用して結果をjson配列/ハッシュ構造にキャッシュすることです。 memcacheのように。ただし、ハリーポッターまたはファンデーションシリーズでこれを行うには、スタートレックの小説がある場合は言うまでもなく、再帰が少し手に負えなくなります。

私は自分の図書館プロジェクトから似たようなことをしましたが、シリーズの各タイトルの順序を格納seriesするテーブルとテーブルを使用しました。title_series次に、関連するタイトルを見つけるために1つのクエリを実行するだけです。

于 2012-06-19T13:58:22.083 に答える