広告1と2:データモデルは問題ありません。ここでは、外部キーを使用することが重要です。もう1つ注意する必要があるのは、データベースが各POSTにTOPICレコードがあることを確認する必要があるということです。これは、POST.topic_id NOT NULLを設定することによって行われます。 属性。これは、TOPICなしでPOSTが残されないことを保証するため、DB側で十分な安全メカニズムです。 POSTで現在何をしていても、トピックを提供する義務があります。
広告3:トピックテーブルの作成時に提供する可能性のある追加データ(IsSticky、IsLockedなど)があるため、ここではストアドプロシージャを使用したトリガーはお勧めしません。また、そのようなトリガーが適用できる場合、データベース設計は非正規化の対象になります。
広告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
}
}
}