Codeigniter, parte 4: Controladores

Aunque ya hemos visto cómo crear controladores y por medio de estos, acciones, es importante tener bien claro su funcionamiento. En primer lugar, debemos entender una cosa, en una aplicación web tradicional, creamos archivos .php por donde pasarán cada una de las acciones de nuestro sitio, así podremos tener páginas como index.php, contacto.php, info.php, etc; sin embargo en Codeigniter todas las acciones pasan por el archivo index.php, el cual dependiendo de la ruta a la cuál se acceda buscará un controlador y su respectiva acción.

(Nota: el hecho que en una publicación pasada quitamos index.php de la url, no significa que ese archivo no se siga llamando, sólo permanece oculto en la url)

Así por ejemplo, cuando ingresamos a la url principal de nuestro sitio. Por ejemplo:

https://mipagina.com

Codeigniter buscará cuál es el controlador y la acción de la página principal. Algo que ya vimos en la publicación pasada. Pero si en cambio accedemos a la url mediante un path, Codeigniter buscará primero el controlador y luego la acción de éste:

https://mipagina.com/controlador/accion

Si no ingresamos la acción en la url, buscará por defecto la acción index().

Si seguiste mis anteriores publicaciones ya deberías saber esto, aunque no está mal repasarlo.

Ahora bien, ¿cómo definir un controlador?, ¿qué significa un controlador?

Una aplicación web, ya sea chica, mediana o grande, debería estar compuesto por módulos. Por ejemplo, una tienda online podría tener un catálogo con páginas para ver un listado de productos o un producto en particular; o por ejemplo módulo de contacto para llenar un formulario o mostrar direcciones, etc. Cada uno de estos módulos debería ser representado por un controlador y sus páginas deberían ser las acciones.

Para ello vamos a crear un nuevo controlador, pero esta vez vamos a detenernos en algunos detalles de éste.

Vamos a a application -> controllers y creamos un controlador llamado instrumentos.php, el cual tendrá dos acciones, uno para mostrar una lista de instrumentos musicales y otro para mostrar uno en particular:

<?php
if (!defined('BASEPATH'))
   exit('No direct script access allowed');
class Instrumentos extends CI_Controller { 
   //Acá va el código.
}

Como todavía no hemos visto modelos vamos a simular una base de datos mediante un array. Dentro de este controlador agregamos una propiedad con el siguiente aspecto:

private $lista = array(
   array('id' => 1, 'nombre' => 'Guitarra', 'descripcion' => 'Instrumento de cuerda.'),
   array('id' => 2, 'nombre' => 'Bajo', 'descripcion' => 'Instrumento de cuerda.'),
   array('id' => 3, 'nombre' => 'Batería', 'descripcion' => 'Instrumento de percusión.'),
);

Vamos a agregar una acción para mostrar este listado, así que creamos un método con el siguiente código:

public function ver_lista(){
   echo '<ul>';
   foreach($this->lista as $item){
      echo '<li> '.$item['nombre'].' </li>';
   }
   echo '</ul>';
}

Y ahora para acceder a esta acción:

https://localhost/ci/instrumentos/ver_lista

Algo que hay que tener presente es que las acciones de un controlador en Codeigniter deben ser métodos públicos, ya que el Framework al detectar la acción a la cuál se está accediendo, creará un objeto del controlador y luego va a llamar al método desde ese objeto. Si el método no es público se romperá el script.

Esto no significa que en Codeigniter las clases que son los controladores sólo puedan tener métodos públicos, ya que como cualquier clase, puede tener métodos privados o protegidos, que serán útiles para ser invocados dentro de la clase. Por ejemplo podríamos crear un método que busca un id en la lista:

private function buscar_instrumento_por_id($id){
   foreach($this->lista as $item){
      if($item['id'] == $id){
         return $item;
      }
   }
   return false;
}

Ahora bien, cómo no podemos llamar a este método porque es privado, y el cuál sólo va a devolvernos la posición del instrumento buscado por su id (de no encontrarlo devolverá false) tendríamos que crear un método nuevo y público, que invoque a éste.

 

Pasar valores dinámicos por url

En una aplicación web, muchas veces necesitamos recuperar un valor en forma dinámica, el cual es obtenido desde la url, para ello son las variables $_GET. Sin embargo Codeigniter no utiliza este tipo de variables, aunque se puede configurar para que sí lo haga.

Para crear la acción que recupera un instrumento por su id, nosotros deberíamos pasar el valor por url, para ello crearemos una acción de la siguiente forma:

public function ver_instrumento($id){
   $instrumento = $this->buscar_instrumento_por_id($id);
   if($instrumento){
      echo '<h1> '.$instrumento['nombre'].' </h1>';
      echo '<p> '.$instrumento['descripcion'].' </p>';
   }else{
      echo 'Instrumento no encontrado.';
   }
}

Notar que este método recibe un parámetro, que es justamente el id del instrumento:

ver_instrumento($id)

Por tanto para acceder por url, debemos agregar el controlador la acción y finalmente el valor dinámico de la siguiente forma:

https://localhost/ci/instrumentos/ver_instrumento/1

(1 se entiende como el valor dinámico, puede ser cualquier cosa)

Si quisiéramos pasar más valores dinámicos por url, simplemente deberíamos agregar más parámetros:

public function accion($parametro1, $parametro2, $parametro3)

Y luego desde la url:

https://sitio/controlador/accion/valor1/valor2/valor3

Una cosa que hay que tener en cuenta es que al ingresar parámetros en nuestra acción, también lo estamos haciendo obligatorios. Si por ejemplo a la acción ver_instrumento(), la llamamos sin el valor del id:

https://localhost/ci/instrumentos/ver_instrumento

Entonces por pantalla nos mostrará un error.

Para esto simplemente deberíamos cambiar:

public function ver_instrumento($id)

Por:

public function ver_instrumento($id=null)

Nuestro controlador finalmente quedará así:

<?php
if (!defined('BASEPATH'))
   exit('No direct script access allowed');
class Instrumentos extends CI_Controller { 
   private $lista = array(
      array('id' => 1, 'nombre' => 'Guitarra', 'descripcion' => 'Instrumento de cuerda.'),
      array('id' => 2, 'nombre' => 'Bajo', 'descripcion' => 'Instrumento de cuerda.'),
      array('id' => 3, 'nombre' => 'Batería', 'descripcion' => 'Instrumento de percusión.'),
   );
   public function ver_lista(){
      echo '<ul>';
      foreach($this->lista as $item){
         echo '<li> '.$item['nombre'].' </li>';
      }
      echo '</ul>';
   }
   public function ver_instrumento($id=null){
      $instrumento = $this->buscar_instrumento_por_id($id);
      if($instrumento){
         echo '<h1> '.$instrumento['nombre'].' </h1>';
         echo '<p> '.$instrumento['descripcion'].' </p>';
      }else{
         echo 'Instrumento no encontrado.';
      }
   }
   private function buscar_instrumento_por_id($id){
      foreach($this->lista as $item){
         if($item['id'] == $id){
            return $item;
         }
      }
      return false;
   }
}

 

Bueno con este es suficiente para comprender cómo trabajar nuestros controladores, más adelante veremos su relación con los modelos y las vistas.

 

Anterior: Codeigniter, parte 3: Página principal y error 404

Siguiente: Codeigniter, parte 5: Vistas

 


8 Respuestas a “Codeigniter, parte 4: Controladores”

  1. Interesante esta parte y bien explicada, aunque me surgen algunas dudas, una de ellas al no ser necesario usar $_GET en este ejemplo, tenemos que escribir a mano en la url los parámetros, me imagino que el funcionamiento es el mismo si lo estamos haciendo desde la «Vista» pasándole los datos desde un formulario.

    Otra de las que me surgen, ya que me gustaría poder transformar una aplicación hecha en php sin framework a Codeigniter si es recomendable mantener los $_GET modificando de alguna manera como comentabas al principio de esta parte o mantener la estructura de Codeigniter (Está pregunta es por curiosidad xD).

    Gracias.

  2. Excelente explicación Fernando. Einstein dijo: «No entiendes realmente algo a menos que seas capaz de explicárselo a tu abuela». Felicitaciones! Ahora sigo con los temas que continúan en este framework ideal para comenzar y tener las bases para otros de mayor complejidad, un saludos desde Chile

      1. de esa forma esta llamando a una funcion dentro del mismo contralador, no a una funcion de otro controlado.

        1. Bueno, en ese caso podés extender un controlador de otro, y por ende vas a poder acceder a todos los métodos que no sean privados del controlador padre.

          No entiendo muy bien, para qué serviría lo que estás pidiendo? Un gato no puede ladrar como un perro, osea un objeto no puede llamar al método del objeto vecino.

          Saludos!