Мне нужно принять основополагающее решение о моем взаимодействии с базой данных / веб-сайтом, и мне не хватает знаний, чтобы найти подходящие условия поиска.
Я создаю семейный сайт, который поддерживает форум, генеалогическое древо, pvp-игры с ранжированием и более подробной информацией, все из datamodel. Технологии прямо сейчас: Php, MySQL, javascript в объектно-ориентированном виде.
В форуме datamodel обрабатывайте письменное сообщение как дополнение к новой теме форума (нить).
В моем текущем datamodel это подразумевало бы и обновляло бы по двум таблицам: «Почта» и «Тема». Мне нужно было бы вставить строку в таблицу тем, затем получить вновь сгенерированный topicId (последовательность), а затем использовать ее во вставке в столбец .
Я считаю, что это слишком много работы для того, что должно произойти, слишком много взаимодействия. Но это станет типичным требованием, если я придерживаюсь текущего подхода.
Вопрос:
В настоящее время таблицы имеют следующую структуру (свободно основанную на этом от erdiagrams.com)
ТЕМА : ('thread')
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.
Ad 1 и 2: Ваша модель данных в порядке. Использование внешних ключей здесь имеет решающее значение. Еще одна вещь, о которой вам нужно позаботиться, заключается в том, что база данных должна обеспечивать наличие записи TOPIC для каждого POST. Это делается путем установки атрибута POST.topic_id NOT NULL . Это достаточный защитный механизм на стороне БД, поскольку он гарантирует, что POST не останется без TOPIC. Независимо от того, что вы сейчас делаете с POST, вы обязаны предоставить ТЕМУ.
Объявление 3: Триггер с хранимой процедурой здесь не рекомендуется, так как у вас есть дополнительные данные в вашей таблице TOPIC (IsSticky, IsLocked и т. Д.), Которые вы можете захотеть предоставить при создании записи TOPIC. Кроме того, если такой триггер будет применим, проект базы данных будет подвержен денормализации.
Объявление 4: На стороне бизнес-логики вы можете теперь помочь себе, написав автоматизированный механизм для создания записи TOPIC каждый раз, когда создается новая запись 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 } } }
То, как я это понимаю: темы – это контейнеры сообщений.
Таблица тем будет довольно минимальной и, возможно, будет содержать только topic id (PK)
и topic title
.
Сами записи будут содержать post id (PK)
, topic id (FK)
, timestamps
, author id
, text
.
Я бы использовал InnoDB
и внешние ключи, поэтому удаляемая тема удалит все дочерние сообщения.
(edit 🙂 В этом ответе я разместил способ сделать это с помощью 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);