sql >> Base de Datos >  >> RDS >> Mysql

Interacción de 2 tablas:insertar, obtener resultado, insertar

Anuncio 1 y 2:Su modelo de datos está bien. El uso de claves externas es crucial aquí. Una cosa más que debe tener en cuenta es que la base de datos debe garantizar que haya un registro de TEMA para cada POST. Esto se hace configurando POST.topic_id NOT NULL atributo. Este es un mecanismo de seguridad suficiente en el lado de DB, ya que garantiza que ningún POST se quedará sin TEMA. No importa lo que haga ahora con su POST, está obligado a proporcionar un TEMA.

Anuncio 3:aquí no se recomienda un activador con procedimiento almacenado, ya que tiene datos adicionales en su tabla TOPIC (IsSticky, IsLocked, etc.), que quizás desee proporcionar al crear el registro TOPIC. Además, si tal disparador fuera aplicable, el diseño de la base de datos estaría sujeto a desnormalización.

Anuncio 4:En el lado de la lógica empresarial, ahora puede ayudarse escribiendo un mecanismo automatizado para crear el registro TOPIC cada vez que se crea un nuevo registro POST sin topic_id especificado. Recomiendo usar algún ORM para esto o aprovechar los modelos de datos disponibles en cualquier framework MVC. El plan para tales modelos se vería así:

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 buena práctica de MVC, esos modelos deberían ser el único lugar para operar directamente en las filas de la tabla. De lo contrario, obtendrá errores de SQL (pero el modelo de datos seguirá siendo coherente, por lo que no tiene que preocuparse de que algo se rompa).

Finalmente aprovecha tus modelos en el controlador capa:

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
        }
    }
}