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.