2

データベースと Web のやり取りについて基本的な決定を下す必要がありますが、適切な検索用語を見つけるための知識さえありません。

バックグラウンド:

私は、フォーラム、家系図、ランキングなどの詳細を含む pvp ゲームをすべてデータモデルからサポートする家族の Web サイトを構築しています。現在のテクノロジー: Php、MySQL、オブジェクト指向の JavaScript。

要件:

フォーラム データモデルでは、書き込み投稿を新しいフォーラム トピック (スレッド) の追加として処理します。

現在のアプローチ:

私の現在のデータモデルでは、これは Post と Topic の 2 つのテーブルを意味し、更新します。トピック テーブルに行を挿入し、新しく生成された topicId(sequence) を取得してから、それをポスト テーブルへの挿入に使用する必要があります

問題:

これは、必要なことに対してあまりにも多くの作業が必要であり、相互作用が多すぎると感じています。しかし、現在のアプローチに固執すれば、それは典型的な要件になります。

質問:

  1. とにかく私は正しい軌道に乗っていますか、それともすべきですか
  2. データモデルを再構築するか、
  3. データベースとやり取りする別の方法を選択する (例: ストアド プロシージャ)
  4. 方法論/フレームワーク xyz を使用する典型的な例に直面していますか?

現在、テーブルの構造は次のとおりです ( erdiagrams.comのこの構造に大まかに基づいています)。

トピック: (「スレッド」)

id
Forum_ID (FK)
Person_ID (FK)(threadcreator)
IsLocked
IsSticky
Subject
ViewCount
DateCreated
Tc_post_id  - trigger to last post_id in this thread

役職

id
topic_id(FK)
person_id(FK)
subject
message
timestamp
replyto

次に、各トピックの最後の投稿を収集し、それに関する情報 (最後のポスター画像など) をトリガー Tc_post_id に表示するビューを作成します。

4

3 に答える 3

1

広告 1 と 2: データ モデルは問題ありません。ここでは、外部キーを使用することが重要です。もう 1 つ気を付けなければならないことは、データベースが POST ごとに TOPIC レコードがあることを確認する必要があるということです。これは、POST.topic_id NOT NULL属性を設定することによって行われます。これは DB 側で十分な安全メカニズムであり、TOPIC なしで POST が残されることはありません。POST で何をするにしても、TOPIC を提供する義務があります。

広告 3: TOPIC テーブルに追加のデータ (IsSticky、IsLocked など) があるため、ここではストアド プロシージャを使用したトリガーはお勧めしません。これは、TOPIC レコードの作成時に提供する必要がある場合があります。また、そのようなトリガーが適用される場合、データベース設計は非正規化の対象になります。

広告 4: ビジネス ロジック側では、topic_id を指定せずに新しい POST レコードが作成されるたびに TOPIC レコードを作成する自動メカニズムを作成することで、自分自身を助けることができます。これには ORM を使用するか、任意の MVC フレームワークで利用可能なデータ モデルを利用することをお勧めします。このようなモデルの設計図は次のようになります。

abstract class AModel // this class should be provided by ORM or framework
{
    /**
     * @var PDO
     */
    protected $_db_driver;

    public function getLastInsertId()
    {
        $stmt = $this->_db_driver->prepare('SELECT LAST_INSERT_ID() AS id');
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_OBJ)->id;
    }

    public abstract function getFieldList();
}

class ForumTopicModel extends AModel
{
    public function insert(array $data)
    {
        $sql = 'INSERT INTO topic VALUES (:id, :forum_id, :person_id, :is_locked, ...)';
        $stmt = $this->_db_driver->prepare($sql);
        return $stmt->execute($data);
    }

    public function getFieldList()
    {
        return array('id', 'forum_id', 'person_id', 'is_locked', /*...*/);
    }

    // ...
}

class ForumPostModel extends AModel
{
    public function insert(array $data)
    {
        $sql = 'INSERT INTO post VALUES (:id, :topic_id, :person_id, :subject, ...)';
        $stmt = $this->_db_driver->prepare($sql);
        return $stmt->execute($data);
    }

    public function getFieldList()
    {
        return array('id', 'topic_id', 'person_id', 'subject', /*...*/);
    }

    public function insertInitialTopicPost(array $form_data)
    {
        $this->_db_driver->beginTransaction();

        $result = true;

        if ( empty($form_data['topic_id']) ) {
            // no topic_id provided, so create new one:
            $topic = new ForumTopicModel();
            $topic_data = array_intersect_key(
                $form_data, array_flip($topic->getFieldList())
            );
            $result = $topic->insert($topic_data);
            $form_data['topic_id'] = $topic->getLastInsertId();
        }

        if ( $result ) {
            $forum_post_data = array_intersect_key(
                $form_data, array_flip($this->getFieldList())
            );
            $result = $this->insert($forum_post_data);
        }

        if ( $result ) {
            $this->_db_driver->commit();
        }
        else {
            $this->_db_driver->rollBack();
        }

        return $result;
    }

    // ...
}

注: 優れた MVC プラクティスとして、これらのモデルは、テーブルの行を直接操作する唯一の場所である必要があります。そうしないと、SQL エラーが発生することになります (ただし、データ モデルは一貫したままであるため、何かが壊れる心配はありません)。

最後に、コントローラーレイヤーでモデルを利用します。

class ForumPostController extends AController
{
    public function createInitialTopicPostAction()
    {
        $form_data = $this->getRequest()->getPost(); /* wrapper for getting
            the $_POST array */

        // (...) validate and filter $form_data here

        $forumPost = new ForumPostModel();
        $result = $forumPost->insertInitialTopicPost($form_data);

        if ( $result ) {
            // display success message
        }
        else {
            // display failure message
        }
    }
}
于 2012-12-18T04:13:04.313 に答える
0

(編集:) この回答では、 mysql_insert_id()を使用してそれを行う方法を投稿しましたが、これは技術的に正しい解決策です (間違っている場合は修正してください)。

ただし、代わりに、私が推測する PDO ラッパーを使用します。また、これは一般的なモデリング/アプローチの質問に対する回答ではありません。

それでも、次の方法でそれを行うことができます。

$sql = "INSERT INTO topic VALUES (NULL,'$forumId',<more parameters>)";
$result = mysql_query($sql);

#  get the generated id  
$topicId = mysql_insert_id();

#  and insert into the post table
$sql = "INSERT INTO post VALUES (NULL,'$topicId',<more parameters>)";
$result = mysql_query($sql);
mysql_free_result($result);

ソース: http://www.desilva.biz/mysql/insertid.html

于 2012-12-16T22:53:22.167 に答える
0

私の理解では、トピックは投稿のコンテナです。

トピック テーブルはかなり最小限で、おそらく と のみが含まれtopic id (PK)ますtopic title

投稿自体には、、、、、が含まpost id (PK)れます。topic id (FK)timestampsauthor idtext

外部キーを利用するInnoDBので、削除されたトピックはその子投稿をすべて削除する可能性があります。

于 2012-12-16T20:58:14.690 に答える