我需要做一个基本的决定,我的数据库/网络互动,我错过了知识,甚至找到适当的搜索条件。
背景:
我正在建立一个家庭网站,支持一个论坛,家谱,pvp游戏与排名和更多的细节,所有从一个数据模型。现在的技术: Php,MySQL,javascript,面向对象的方式。
要求:
在论坛数据模型中,处理一个书面文章作为一个新的论坛主题(线程)。
现行办法:
在我当前的数据模型中,这将意味着在两个表上进行更新: Post和Topic。我需要在表中插入一行,然后获取新生成的topicId(序列),然后在post表的插入中使用该行。
问题:
-我觉得这是太多的工作,需要发生的事情,太多的互动。但是,如果我坚持目前的方法,这将成为一个典型的要求。
问题:
目前,表具有如下结构(松散地基于来自这一个的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 threadPOST
id
topic_id(FK)
person_id(FK)
subject
message
timestamp
replyto然后,我有一个视图,收集每个主题的最后一篇文章,并在触发器Tc_post_id上显示一些信息(例如,最后一张海报图片)。
发布于 2012-12-18 04:13:04
广告1和2:你的数据模型很好。在这里使用外键是很关键的。您还需要注意的另一件事是,数据库应该确保每个帖子都有一个主题记录。这是通过设置POST.topic_id NULL属性来完成的。在DB端,这是足够的安全机制,因为它确保不会有任何帖子没有主题。无论你现在如何处理你的帖子,你都有义务提供一个主题。
广告3:此处不建议使用带有存储过程的触发器,因为主题表(IsSticky、IsLocked等)中有其他数据,您可能希望在创建主题记录时提供这些数据。此外,如果这种触发器适用,数据库设计将受到非正规化的影响。
广告4:在业务逻辑方面,您现在可以通过编写一种自动机制来帮助自己,每次创建新的POST记录时都不需要指定的topic_id,就可以创建主题记录。我建议为此使用一些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-16 20:58:14
我的理解是:主题是帖子的容器。
主题表将非常小,并且可能只包含topic id (PK)和topic title。
这些帖子本身将包含post id (PK)、topic id (FK)、timestamps、author id、text。
我会使用InnoDB和外键,这样一个被删除的主题就可以删除它的所有子帖子。
发布于 2012-12-16 22:53:22
(编辑:)在这个答案中,我发布了一种使用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
https://stackoverflow.com/questions/13905381
复制相似问题