Mysql
 sql >> Database >  >> RDS >> Mysql

Interazione a 2 tabelle:inserisci, ottieni risultato, inserisci

Annuncio 1 e 2:il tuo modello di dati va bene. L'uso di chiavi esterne è fondamentale qui. Un'altra cosa di cui devi occuparti è che il database dovrebbe garantire che ci sia un record TOPIC per ogni POST. Questo viene fatto impostando POST.topic_id NON NULL attributo. Questo è un meccanismo di sicurezza sufficiente sul lato DB, in quanto garantisce che nessun POST venga lasciato senza TOPIC. Non importa cosa fai ora con il tuo POST, sei obbligato a fornire un ARGOMENTO.

Annuncio 3:un trigger con stored procedure non è consigliato qui poiché nella tabella TOPIC sono presenti dati aggiuntivi (IsSticky, IsLocked, ecc.), che potresti voler fornire durante la creazione del record TOPIC. Inoltre, se tale trigger fosse applicabile, il design del database sarebbe soggetto a denormalizzazione.

Annuncio 4:Dal lato della logica aziendale ora puoi aiutarti scrivendo un meccanismo automatizzato per creare il record TOPIC ogni volta che viene creato un nuovo record POST senza topic_id specificato. Consiglio di utilizzare alcuni ORM per questo o di sfruttare i modelli di dati disponibili in qualsiasi framework MVC. Il progetto per tali modelli sarebbe simile a questo:

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:come buona pratica MVC, quei modelli dovrebbero essere l'unico posto in cui operare direttamente sulle righe della tabella. Altrimenti finirai per ricevere errori SQL (ma il modello dati rimarrà coerente, quindi non devi preoccuparti che qualcosa si rompa).

Finalmente sfrutta i tuoi modelli nel controller livello:

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