Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Interação de 2 tabelas:inserir, obter resultado, inserir


Anúncio 1 e 2:seu modelo de dados está bom. Usar chaves estrangeiras é crucial aqui. Mais uma coisa que você precisa cuidar é que o banco de dados deve garantir que haja um registro TOPIC para cada POST. Isso é feito definindo POST.topic_id NOT NULL atributo. Este é um mecanismo de segurança suficiente no lado do banco de dados, pois garante que nenhum POST fique sem TOPIC. Não importa o que você faça agora com seu POST, você é obrigado a fornecer um TÓPICO.

Anúncio 3:Um gatilho com procedimento armazenado não é recomendado aqui, pois você tem dados adicionais em sua tabela TOPIC (IsSticky, IsLocked etc.), que você pode fornecer na criação do registro TOPIC. Além disso, se tal gatilho fosse aplicável, o design do banco de dados estaria sujeito à desnormalização.

Anúncio 4:No lado da lógica de negócios, agora você pode se ajudar escrevendo um mecanismo automatizado para criar o registro TOPIC toda vez que um novo registro POST for criado sem o topic_id especificado. Recomendo usar algum ORM para isso ou aproveitar os modelos de dados disponíveis em qualquer framework MVC. O modelo para esses modelos ficaria assim:
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;
    }

    // ...
}

Nota:como uma boa prática de MVC, esses modelos devem ser o único local para operar diretamente nas linhas da tabela. Caso contrário, você acabará recebendo erros de SQL (mas o modelo de dados permanecerá coerente, então você não precisa se preocupar com a quebra de algo).

Por fim, aproveite seus modelos no controlador camada:
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
        }
    }
}