2

我需要对我的数据库/网络交互做出基本决定,我什至缺少找到合适搜索词的知识。

背景:

我正在建立一个家庭网站,它支持论坛、家谱、带有排名和更多细节的 pvp 游戏,所有这些都来自数据模型。现在的技术:面向对象的 PHP、MySQL、javascript。

要求:

在论坛数据模型中,将书面帖子处理为添加新论坛主题(线程)。

目前的做法:

在我当前的数据模型中,这将暗示并更新两个表:帖子和主题。我需要在主题表中插入一行,然后获取新生成的 topicId(sequence),然后在插入到 post 表中使用它

问题:

我觉得这对于需要发生的事情来说工作量太大,互动太多。但如果我坚持目前的方法,它将成为一个典型的要求。

问题:

  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:您的数据模型很好。在这里使用外键至关重要。您需要注意的另一件事是数据库应确保每个 POST 都有一个 TOPIC 记录。这是通过设置 POST.topic_id NOT NULL属性来完成的。这在 DB 端是足够的安全机制,因为它确保不会留下没有 TOPIC 的任何 POST。无论您现在对 POST 做什么,您都有义务提供一个主题。

广告 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

我理解它的方式:主题是帖子的容器。

主题表会相当小,可能只包含一个topic id (PK)and topic title

帖子本身将包含post id (PK), topic id (FK), timestamps, author id, text

我会使用InnoDB和外键,因此删除的主题可能会删除其所有子帖子。

于 2012-12-16T20:58:14.690 回答
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 回答