miércoles, 24 de julio de 2013

Codeigniter 2: cómo insertar multiples filas en una tabla

Insertar múltiples filas en CodeIgniter 2, útil para manejadores como MySQL y PostgreSQL

Este artículo lo tomé de http://codefury.net/2009/12/insert-multiple-rows-into-a-database-with-codeigniter/, pero lo he adaptado para funcionar con CI2

Paso 1: Extender la clase Model.php

En la carpeta application/core/ crear la clase MY_Model.php, el prefijo MY_ debe ser el mismo que se encuentra establecido en el archivo config.php en el elemento 'subclass_prefix'

<?php

/**
 * @link http://codefury.net/2009/12/insert-multiple-rows-into-a-database-with-codeigniter/ Hacer multiples inserts
 * @author KENNY KATZGRAU
 */
class MY_Model extends CI_Model
{

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * A method to facilitate easy bulk inserts into a given table.
     * @param string $table_name
     * @param array $column_names A basic array containing the column names of the data we'll be inserting
     * @param array $rows A two dimensional array of rows to insert into the database.
     * @param bool $escape Whether or not to escape data that will be inserted. Default = true. Para otros drivers diferentes a MySQl, habría que poner FALSE
     * @author Kenny Katzgrau 
     */
    public function insert_rows($table_name, $column_names, $rows, $escape = true)
    {
        /* Build a list of column names */
        $columns = array_walk($column_names, array($this, 'prepare_column_name'));
        $columns = implode(',', $column_names);

        /* Escape each value of the array for insertion into the SQL string */
        if ($escape){
            array_walk_recursive($rows, array($this, 'escape_value'));
        }
        
        # asignar un table-prefix si está definido en el archivo database.php
        $table_name = $this->db->dbprefix($table_name);

        /* Collapse each rows of values into a single string */
        $length = count($rows);
        for ($i = 0; $i < $length; $i++){
            $rows[$i] = implode(',', $rows[$i]);
        }

        /* Collapse all the rows into something that looks like
         *  (r1_val_1, r1_val_2, ..., r1_val_n),
         *  (r2_val_1, r2_val_2, ..., r2_val_n),
         *  ...
         *  (rx_val_1, rx_val_2, ..., rx_val_n)
         * Stored in $values
         */
        $values = "(" . implode('),(', $rows) . ")";

        $sql = "INSERT INTO {$table_name} ({$columns}) VALUES {$values}";
        
        /*
        $querie_file = PATH_APP_DEBUGS . 'queries_' . date('Y-m-d') . '.log';
        file_put_contents($querie_file, $sql, FILE_APPEND);
         * 
         */

        return $this->db->simple_query($sql);
    }

    public function escape_value(& $value)
    {
        if (is_string($value)) {
            $value = "'" . mysql_real_escape_string($value) . "'";
        }
    }

    public function prepare_column_name(& $name)
    {
        $name = "`$name`";
    }

}

Paso 2: Ejemplo A

He aquí un ejemplo para probar la inserción de varias filas en un mismo query:

class Messages extends MY_Model 
{   
  /* Code .. */   
  function insert_test_data()   
  {     
    /* Prepare some fake data (10000 rows, 40,000 values total) */
    $rows = array_fill(0, 10000, array(34239, 102438, "Test Message!", '2009-12-12'));
    $columns = array('to_user_id', 'from_user_id', 'message', 'created');
    $this->insert_rows('messages', $columns, $rows); 
  }
}

Paso 1: Ejemplo B

Otro ejemplo, de cómo se usaría en un método típico de un modelo en CodeIgniter:

<?php

class M_usuarios extends MY_Model
{

    private $_enc_key;
    protected $_usuario_id;

    public function asignar_permisos()
    {
        $this->_usuario_id = (int) $this->input->post('sel_campo01');
        $this->db
                ->where('usuario_id', $this->_usuario_id)
        ;
        try {
            $this->db->trans_start();

            $this->db->query('LOCK TABLES t_ci_sessions LOW_PRIORITY WRITE');
            $this->db->query('LOCK TABLES t_usuarios_t_submenus LOW_PRIORITY WRITE');

            # primero, eliminar todos los permisos asignados
            $delete = $this->db->delete('usuarios_t_submenus');

            # segundo, insertar todos los permisos recién asignados
            $a_columns = array('usuario_id', 'submenu_id');
            $a_rows = $this->_preparar_datos_permisos($this->_usuario_id, $this->input->post('sel_campo02'));

            # método insert_rows() que nosotros definimos en la clase MY_Model.php
            $insert = $this->insert_rows('usuarios_t_submenus', $a_columns, $a_rows);
            
            $this->db->query('UNLOCK TABLES');
            $this->db->trans_complete();
            
            return array('insert' => TRUE, 'mensaje' => '');
        } catch (Exception $e) {
            $this->db->query('UNLOCK TABLES');
            $this->db->trans_complete();

            return array('insert' => FALSE, 'mensaje' => $e->getMessage());
        }
    }

    private function _preparar_datos_permisos($usuario_id, $permisos)
    {
        $filas = array();
        foreach ($permisos as $_submenu_id){
            $filas[] = array($usuario_id, $_submenu_id);
        }
        
        return $filas;
    }
}

Eso es todo, espero que les sea de utilidad.

No hay comentarios:

Publicar un comentario

Datos personales

Mi foto
Podrás encontrar códigos recursos y artículos sobre PHP, JavaScript, jQuery, MooTools, Ajax, CSS, HTML, UML, RUP, AUP, XP (eXtreme Programming), Six-Sigma, CMMI, FrameWorks, Zend Framework, Magento, CodeIgniter, CakePHP, Joomla 1.5, Doctrine, Active Record, ORM, POO, MVC, MySql, PostgreSql. Este espacio está destinado a ayudar y compartir un poco de lo mucho que he recibido de la comunidad en la Red.