Codeigniter, parte 7: CRUD

Bueno, ya sabemos que es un modelo, una vista y un controlador, pero si nunca has trabajado con esto, entonces supongo que aun estás algo perdido/a. No importa, en esta publicación veremos cómo trabajan en conjunto.

En la publicación pasada habíamos creado una base de datos, con una sola tabla:

CREATE TABLE informes(
 id int(10) unsigned not null auto_increment primary key,
 titulo varchar(50) not null,
 descripcion text not null,
 prioridad tinyint(1) not null
)ENGINE=innoDB;

También, habíamos dicho que cada modelo representaba a una tabla en la base de datos, por tanto, también habíamos creado un modelo dentro de nuestra carpeta application -> models con el nombre informe_model.php. El cual tenía el siguiente código:

<?php
class Informe_model extends CI_Model { 
   public function __construct() {
      parent::__construct();
   }
   public function guardar($titulo, $descripcion, $prioridad, $id=null){
      $data = array(
         'titulo' => $titulo,
         'descripcion' => $descripcion,
         'prioridad' => $prioridad
      );
      if($id){
         $this->db->where('id', $id);
         $this->db->update('informes', $data);
      }else{
         $this->db->insert('informes', $data);
      } 
   }
   public function eliminar($id){
      $this->db->where('id', $id);
      $this->db->delete('informes');
   }
   public function obtener_por_id($id){
      $this->db->select('id, titulo, descripcion, prioridad');
      $this->db->from('informes');
      $this->db->where('id', $id);
      $consulta = $this->db->get();
      $resultado = $consulta->row();
      return $resultado;
   }
   public function obtener_todos(){
      $this->db->select('id, titulo, descripcion, prioridad');
      $this->db->from('informes');
      $this->db->order_by('prioridad, titulo', 'asc');
      $consulta = $this->db->get();
      $resultado = $consulta->result();
      return $resultado;
   }
}

Bueno, sigamos repasando. El método guardar() nos permitía insertar o modificar un registro, un informe, dependiendo de si le pasábamos un id o no. Si tenía id, intentaba modificar con el mismo, de lo contrario insertaba. El método eliminar(), como su nombre lo indica, eliminaba un registro por su id. obtener_por_id() me devolvía un objeto por el id de un registro. Y por último obtener_todos() era un método que me listaba todos los registro, ordenados por su prioridad y nombre.

Listo, ya tenemos nuestro modelo, ahora solamente nos resta crear un controlador y vistas, que nos permite realizar estas tareas que programamos en nuestro controlador. Tendremos que tener la posibilidad de crear nuevos informes, listar todos, verlos individualmente, modificar y eliminar cada uno.

En primer lugar, antes de comenzar a crear nuestro controlador y sus vistas, vamos a necesitar dos cosas, una hoja de estilos, que nos permita darle algo de diseño a nuestra sitio y un javascript. Yo voy a utilizar Twitter Bootstrap como ya usé en varios ejemplos, para darle un diseño rápido, simple y agradable.

Podemos descargar la librería desde acá:

Descargar Twitter Bootstrap.

Y también Jquery:

Descargar Jquery

(Estas librerías no son necesarias, pero van a servir para decorar nuestro ejemplo)

En la raíz de nuestro proyecto vamos a crear dos carpetas, css y js, vamos a guardar la hoja de estilos de Twitter Bootstrap, bootstrap.css, y vamos a guardarla en la carpeta css. Y el archivo que descargamos de Jquery vamos a guardarlo dentro de la carpeta js.

 

Creando las vistas

Vamos dentro de la carpeta application -> views y creamos una carpeta con el nombre informes, aquí vamos a crear cinco archivos .php:

header.php:

<!DOCTYPE html>
<html lang="en">
 <head>
    <meta charset="utf-8" />
    <title> Informes </title>
    <link type="text/css" href="<?php echo base_url() ?>css/bootstrap.css" rel="stylesheet" />
    <script type="text/javascript" src="<?php echo base_url() ?>js/jquery-2.1.1.min.js"></script> 
 </head>
 <body>
   <div class="container">

footer.php:

   </div>
 </body>
</html>

En todas las páginas habrá etiquetas que se repiten como html, head o body. En estas vistas tendremos el código html que se repite, mientras que en las demás vistas sólo tendremos que ingresar la parte principal.

Lo bueno de esto es que no tendremos que repetir el mismo código en todas las vistas. Además si necesitamos agregar más hojas de estilos o archivos javascript, tendremos como modificar un solo archivo.

index.php:

<h1> Lista de informes </h1>
<p> <a class="btn btn-success" href="<?php echo base_url() ?>informes/guardar"> Crear nuevo informe </a> </p>
<?php if (count($informes)): ?>
 <table class="table tableborder">
    <thead>
       <tr>
          <th> Título </th>
          <th> Prioridad </th>
          <th> &nbsp; </th>
       </tr>
    </thead>
    <tbody>
       <?php foreach($informes as $item): ?>
          <tr>
             <td style="width: 35%"> <?php echo $item->titulo ?> </td>
             <td style="width: 35%"> <?php echo $item->prioridad ?> </td>
             <td> 
                <a class="btn btn-info" href="<?php echo base_url() ?>informes/ver/<?php echo $item->id ?>"> Ver </a>
                <a class="btn btn-info" href="<?php echo base_url() ?>informes/guardar/<?php echo $item->id ?>"> Editar </a>
                <a class="btn btn-danger eliminar_informe" href="<?php echo base_url() ?>informes/eliminar/<?php echo $item->id ?>"> Eliminar </a> 
             </td>
          </tr>
       <?php endforeach; ?>
    </tbody>
 </table>
<?php else: ?>
 <p> No hay informes </p>
<?php endif; ?>
<script type="text/javascript">
   $(".eliminar_informe").each(function() {
      var href = $(this).attr('href');
      $(this).attr('href', 'javascript:void(0)');
      $(this).click(function() {
         if (confirm("¿Seguro desea eliminar este informe?")) {
            location.href = href;
         }
      });
   });
</script>

Ésta será nuestra vista principal. Aquí se listarán todos los informes. Tendremos un enlace para agregar nuevos informes:

<p> <a href="<?php echo base_url() ?>informes/guardar"> Crear nuevo informe </a> </p>

Y en cada ítem listado tendremos la posibilidad de editar los que ya están creados:

<a href="<?php echo base_url() ?>informes/guardar/<?php echo $item->id ?>"> Editar </a>

Notar que ambos redirigen a la acción guardar, del controlador informes (controlador que aun no hemos creado) Lo que hay que tener en cuenta, es que si bien la acción es la misma en ambos casos, hay algo que los diferencia, si vamos a crear un nuevo informe omitimos el id en la url; si modificamos, entonces debemos pasar el id del informe.

También podemos ver cada uno de estos informes en detalle, en forma individual:

<a href="<?php echo base_url() ?>informes/ver/<?php echo $item->id ?>"> Ver </a>

O eliminarlos:

<a href="<?php echo base_url() ?>informes/eliminar/<?php echo $item->id ?>"> Eliminar </a>

En este enlace, que antes de redirigir, va a preguntarle al usuario si está seguro de querer eliminar el informe. Por eso las líneas con Javascript:

<script type="text/javascript">
   $(".eliminar_informe").each(function() {
      var href = $(this).attr('href');
      $(this).attr('href', 'javascript:void(0)');
      $(this).click(function() {
         if (confirm("¿Seguro desea eliminar este informe?")) {
            location.href = href;
         }
      });
   });
</script>

 

ver.php:

<h1> <?php echo $informe->titulo ?> (Nivel : <?php echo $informe->prioridad; ?>) </h1>
<div> <?php echo nl2br($informe->descripcion) ?> </div>
<br />
<div> <a class="btn btn-info" href="<?php echo base_url() ?>informes"> Volver atrás </a> </div>

Aquí simplemente mostraremos los datos del informe. Para la descripción usamos la función nativa de PHP nl2br(), por si el mismo tiene saltos de línea.

guardar.php:

<h1> Guardar informe </h1>
<form method="post" action="<?php echo base_url() ?>informes/guardar_post/<?php echo $id ?>">
    <div class="row">
       <label> Título </label>
       <input type="text" name="titulo" required="required" value="<?php echo $titulo ?>" />
    </div>
    <div class="row">
       <label> Descripción </label>
       <textarea name="descripcion" cols="100" rows="10" required="required" style="width: 100%;"><?php echo $descripcion; ?></textarea>
    </div>
    <div class="row">
       <label> Prioridad </label>
       <input type="number" min="1" max="5" name="prioridad" required="required" value="<?php echo $prioridad; ?>" />
    </div>
    <div class="row">
       <input type="submit" class="btn btn-success" value="Guardar" />
       <a class="btn btn-danger" href="<?php echo base_url() ?>informes"> Cancelar </a>
    </div>
</form>

Aquí tendremos un formulario que nos servirá tanto para crear un nuevo informe, como editar uno existente. Las variables dentro de los campos tendrán un valor o serán null, dependiendo de si viene un dato cargado o no.

 

Creando el controlador

Ya tenemos nuestros modelos y nuestras vistas, ahora sólo necesitamos un puente que una a ambos, que se comunique con los modelos para hacer consultas a la base de datos, y con las vistas para mostrar estos datos al cliente.

Para ello vamos a application -> controllers y creamos un archivo con el nombre: informes.php. Éste tendrá el siguiente código:

<?php
if (!defined('BASEPATH'))
   exit('No direct script access allowed');
class Informes extends CI_Controller {
   public function __construct() {
      parent::__construct();
   }
   public function index() {
      $data = array();
      $this->load->model('informe_model');
      $data['informes'] = $this->informe_model->obtener_todos();
      $this->load->view('informes/header');
      $this->load->view('informes/index', $data);
      $this->load->view('informes/footer');
   }
   public function ver($id){
      $data = array();
      $this->load->model('informe_model');
      $informe = $this->informe_model->obtener_por_id($id);
      $data['informe'] = $informe;
      $this->load->view('informes/header');
      $this->load->view('informes/ver', $data);
      $this->load->view('informes/footer');
   }
   public function guardar($id=null){
      $data = array(); 
      $this->load->model('informe_model');
      if($id){
         $informe = $this->informe_model->obtener_por_id($id); 
         $data['id'] = $informe->id;
         $data['titulo'] = $informe->titulo;
         $data['descripcion'] = $informe->descripcion;
         $data['prioridad'] = $informe->prioridad;
      }else{
         $data['id'] = null;
         $data['titulo'] = null;
         $data['descripcion'] = null;
         $data['prioridad'] = null;
      }
      $this->load->view('informes/header');
      $this->load->view('informes/guardar', $data);
      $this->load->view('informes/footer');
   }
   public function guardar_post($id=null){
      if($this->input->post()){
         $titulo = $this->input->post('titulo');
         $descripcion = $this->input->post('descripcion');
         $prioridad = $this->input->post('prioridad');
         $this->load->model('informe_model');
         $this->informe_model->guardar($titulo, $descripcion, $prioridad, $id);
         redirect('informes');
      }else{
         $this->guardar();
      } 
   }
   public function eliminar($id){
      $this->load->model('informe_model');
      $this->informe_model->eliminar($id);
      redirect('informes');
   }
}

La acción index(), como dijimos antes, va a recuperar la lista de los informes:

$data['informes'] = $this->informe_model->obtener_todos();

Y luego va a cargar la vista correspondiente, a la que le va a pasar ese array:

$this->load->view('informes/ver', $data);

Algo similar haremos para mostrar el informe en forma individual, el cual será cargado:

$informe = $this->informe_model->obtener_por_id($id);

Para finalmente pasarlo a la vista:

$this->load->view('informes/ver', $data);

La acción guardar(), recibirá un id como parámetro, el cual será opcional. Como dijimos antes, de existir ese id, intentará cargar un informe. Si el informe existe, pasará los valores de dicho informe, sino pasará valores nulos.

$informe = $this->informe_model->obtener_por_id($id);

Y cargará la vista:

$this->load->view('informes/guardar', $data);

Además desde esta acción guardar(), habrá un formulario que va a enviar esos datos una acción llamada guardar_post(). Ésta recibirá estos datos mediante el objeto input y su método post().

$titulo = $this->input->post('titulo');
$descripcion = $this->input->post('descripcion');
$prioridad = $this->input->post('prioridad');

Finalmente guardará este registro:

$this->informe_model->guardar($titulo, $descripcion, $prioridad, $id);

Dependiendo de si hay o no un id definido, este método se encargará de insertar o modificar un registro.

Notar que en Codeigniter la forma de redireccionar desde una acción a otra, es mediante la función redirect():

redirect('informes');

Y finalmente la acción eliminar(), será como su nombre lo indica, la que elimina el registro en la base de datos. Recibirá como parámetro el id del registro a eliminar:

$this->informe_model->eliminar($id);

Y también va a redireccionar.

Bueno, con esto tenemos nuestro primer ejemplo de cómo trabaja el MVC en conjunto.

Descargar ejemplo

 

Anterior: Codeigniter, parte 6: Modelos

Siguiente: Codeigniter, parte 8: Validaciones

 


16 Respuestas a “Codeigniter, parte 7: CRUD”

  1. Lo vengo siguiendo y probando todo, es excelente, gran trabajo che!
    Una duda, no me doy cuenta por ej, cuando trato de guardar sin titulo y aparece la advertencia «Completa este campo» de donde sale? es solo una duda….creo a un proyecto que tengo guardado y dejado lo tratare de llevar a codeing…..debo checarlo bien pulirlo y migrarlo a POO xD…es que yo programo por hobbi xD

    1. Lo de “Completa este campo” en realidad es nativo de HTML5, no es que lo valida Javascript, fijate que el campo tiene un atributo required=»required»

      Suerte, con eso.

      Saludos!

  2. tengo el siguiente problema quiero enviar el resultado de dos consultas en una sola vista:

    function MostrarEESS(){
    $data1[‘eess’]=$this->mostrar_model->Mostrar_EESS();
    $data2[‘usuarios’]=$this->mostrar_model->Mostrar_Usuarios();

    $this->load->view(‘front_end/RegistroUsuario’,$data1,$data2);

    }
    enviAR RSPUESTA A MI CORREO … graciAS DE ANTEMANO

    1. El tema es que la variable que guarda tanto los datos como ‘eess’ y ‘usuarios’ debería ser la misma, osea el mismo array.

      Tu código debería quedar así:

      function MostrarEESS(){
      $data = array();
      $data[‘eess’]=$this->mostrar_model->Mostrar_EESS();
      $data[‘usuarios’]=$this->mostrar_model->Mostrar_Usuarios();

      $this->load->view(‘front_end/RegistroUsuario’,$data;

      }

      Saludos!

  3. Interesante, ya voy entendiendo los conceptos, al principio cuesta xD.
    Ahora mismo se me surge muchas formas de hacer un CRUD, pero hasta día de hoy con «Datatables» que es como lo he hecho en PDO me ha encantado, me imagino que existirá alguna forma de poder combinarlo.

    Ah y una pregunta, será fácil poder hacer, en el ejemplo que has puesto, cuando se crea el informe, realizarlo en una ventana modal(como podría ser con bootstrap modal) o es muy complicado.

    Muchas gracias Ferchu, estoy aprendiendo con su tutorial.

    1. mmm… no, eso no es así. Vos tenés un modelo llamado informe_model, lo cual significa que vos no vas a acceder a tu modelo desde la url, sino que vos vas a acceder a un controlador desde la url, y ése es quien va a llamar al modelo. Te recomiendo que repases el modelo vista controlador, de la forma en que lo plantea codeigniter.

      Saludos!

  4. gracias por tu apoyo la verdad es un buen ejemplo

    disculpa una duda conforme al script de validación la querer eliminar en mi caso no lo manda me podrías apoyar por favor y gracias excelente trabajo.

  5. Hola, Ante todo felicitarte por el muy buen tutorial, he visto varios pero este me ha ayudado mucho para lo que el CRUD. Muchas Gracias.

    Ahora paso a la molestia, a ver si me puedes ayudar, me sucede que en VER, y EDITAR me da errores y no puedo pillar cual es., te dejo el error que me da y donde se produce, he efectuado varias pruebas sin pillar el porque se produce, ya que hice un cambio, pero no debiera ser eso, cambie el header y el footer por plantilla, todo lo demás funciona bien.

    Esto sucede al pulsar el boton VER
    A PHP Error was encountered
    Severity: Notice
    Message: Undefined variable: informe
    Filename: controllers/Informes.php
    Line Number: 33
    Backtrace:
    File: /home/claudio/www/fmw-ci-boot/application/controllers/Informes.php
    Line: 33
    Function: _error_handler

    Informes Controller.
    public function ver($id){
    $data = array();
    $data[‘title’] = ‘Ver informe’;
    $data[‘contenido’] = ‘informes/ver’;
    $data[‘informe’] = $this->informe_model->obtener_por_id($id);
    LINEA 33 $data[‘informe’] = $informe;
    $this->load->view(‘plantilla’, $data);
    }

    Esto sucede al pulsar el boton EDITAR
    A PHP Error was encountered

    Severity: Notice

    Message: Undefined variable: informe

    Filename: controllers/Informes.php

    Line Number: 41

    Backtrace:

    File: /home/claudio/www/fmw-ci-boot/application/controllers/Informes.php
    Line: 41
    Function: _error_handler
    y serepite para la linea 42, 43 y 44
    public function guardar($id = null){
    $data = array();
    if($id){
    $data[‘informes’] = $this->informe_model->obtener_por_id($id);
    Linea 41 $data[‘id’] = $informe->id;
    Linea 42 $data[‘titulo’] = $informe->titulo;
    Linea 43 $data[‘descripcion’] = $informe->descripcion;
    Linea 44 $data[‘prioridad’] = $informe->prioridad;
    }else{

    Ojalá me puedas ayudar, quedare muy agradecido

    Un Cordial Saludo

    1. mmm… la parte donde pusiste:

      $data[‘informe’] = $this->informe_model->obtener_por_id($id);
      $data[‘informe’] = $informe;

      No debería ser:

      $informe = $this->informe_model->obtener_por_id($id);
      $data[‘informe’] = $informe;

      O bien:

      $data[‘informe’] = $this->informe_model->obtener_por_id($id);

      Fijate eso, por favor. Creo que ahí es donde rompe.

      Cambialo y me avisas.

      Saludos!

  6. Gracias por tu ayuda, solucionado con tus consejos

    quedo de la siguiente forma

    $informe = $this->informe_model->obtener_por_id($id);
    $data[‘informe’] = $informe;

    Un Cordial Saludo

    1. Si querés enviame el código por correo, porque la verdad no sé, puede ser cualquier cosa: fernando.g.gaitan(gmail)

      Saludos!