0

Relaciones de tipo foraneas en CodeIgniter 4

Una clave foránea o FK de sus siglas en inglés de Foreign Key, es un campo (o colección de campos) en una tabla, que se refiere a la CLAVE PRIMARIA en otra tabla.

La restricción FOREIGN KEY se usa para evitar acciones que destruirían enlaces entre tablas y poder enlazar tablas sin necesidad de duplicar registros, si no simplemente referenciando a los mismos.

Migración de la tabla a relacionar

En CodeIgniter 4, al igual que ocurre con Laravel, para poder estructurar este tipo de relaciones, tenemos que definirlas desde las migraciones; en este ejemplo, voy a tomar un par de tablas de mi curso completo, las de movies y categorías en la cual una movie o película pertenece a una categoría; primero la migración de la tabla a relacionar, es decir, la de movies:

<?php namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;
class Categories extends Migration
{
public function up(){
$this->forge->addField([
'id'          => [
'type'           => 'INT',
'constraint'     => 5,
'unsigned'       => TRUE,
'auto_increment' => TRUE
],
'title'       => [
'type'           => 'VARCHAR',
'constraint'     => '255',
],
]);
$this->forge->addKey('id', TRUE);
$this->forge->createTable('categories');
}
//--------------------------------------------------------------------
public function down()
{
$this->forge->dropTable('categories');
}
}

Lo típico, un campo id y nombre para las categorías y en la función down hacemos las operaciones inversas a la de uno, que si en la de up creamos una tabla, por el down la destruimos; recuerda que el tema de las migraciones en CodeIgniter ya fue tratado.

Migración de la FK o clave foranea

Finalmente la tabla que vamos a relacionar mediante la foreign key:

<?php namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Movies extends Migration
{
public function up()
{
$this->forge->addField([
'id'          => [
'type'           => 'INT',
'constraint'     => 5,
'unsigned'       => TRUE,
'auto_increment' => TRUE
],
            title=> [
                'type' => 'VARCHAR',
                'constraint' => 255
            ]
'category_id'          => [
'type'           => 'INT',
'constraint'     => 5,
'unsigned'       => TRUE
],
 ****
]);
$this->forge->addKey('id', TRUE);
            $this->forge->addForeignKey('category_id' , categories,'id','CASCADE','CASCADE');
$this->forge->createTable('movies');
}
//--------------------------------------------------------------------
public function down()
{
$this->forge->dropTable('movies');
}
}

Una migración con un campo ID para mantenerla sencilla y el resto de los campos  que de manera ejemplificada solamente tenemos el del título; lo importante de aqui es la columna llamada category_id que con la misma más adelante la empleamos para definir la clave foránea mediante la función de addForeignKey, la cual recibe:

  1. El nombre de la columna en movies, es decir, la tabla que mantendrá la relación FK
  2. El nombre de la tabla a relacionar, categories en nuestro caso
  3. La columna de la tabla a relacionar, es decir, la PK de categorías que se llama id

Modelos

Finalmente, los modelos de las migraciones anteriores:

<?php namespace App\Models;
use CodeIgniter\Model;
class MovieModel extends Model
{
    protected $table = 'movies';
    protected $primaryKey = 'id';
    protected $allowedFields = ['title','category_id'];
}
<?php namespace App\Models;
use CodeIgniter\Model;
class CategoryModel extends Model
{
    protected $table = 'categories';
    protected $primaryKey = 'id';
    protected $allowedFields = ['title'];
    public function get($id = null)
    {
        if ($id === null) {
            return $this->findAll();
        }
        return $this->asArray()
            ->where(['id' => $id])
            ->first();
    }
}

Extra: Crear un registro con relación foránea

Para crear un registro no tienes que definir alguna regla y estructura adicional; la relación FK a la final es una columna de tipo entero con una restricción extra que es el de la FK; así que, pasamos directamente el valor de la clave a relacionar; en este ejemplo, estamos suponiendo que estos datos son recibidos desde un formulario:

$movie = new MovieModel();
        if ($this->validate('movies')) {
            $id = $movie->insert([
                'title' => $this->request->getPost('title'),
                'description' => $this->request->getPost('description'),
                'category_id' => $this->request->getPost('category_id'),
            ]);
0

Crea cuadrículas de datos Ajax con CodeIgniter y jQuery

En esta lección, crearemos una biblioteca CodeIgniter que nos permite generar cuadrículas de datos automáticamente para administrar cualquier tabla de base de datos. Explicaré cada paso necesario para crear esta clase; por lo que probablemente aprenderás algunas técnicas/conceptos nuevos de programación orientada a objetos en el proceso.

Como beneficio adicional, procederemos a escribir un código jQuery que permitirá al usuario actualizar el contenido de la cuadrícula de datos sin tener que esperar a que se actualice la página.

¿Qué es una cuadrícula de datos?

Una cuadrícula de datos es una tabla que muestra el contenido de una base de datos o una tabla junto con los controles de clasificación.

Una cuadrícula de datos es una tabla que muestra el contenido de una base de datos o una tabla junto con los controles de clasificación. En este tutorial, se nos asignará la tarea de proporcionar esta funcionalidad, pero también evitar que el usuario espere a que la página se actualice cada vez que se realiza una operación. ¡Gracias a jQuery, esta será una tarea bastante simple!

¿Qué pasa con los usuarios que no tienen Javascript habilitado? ¡No te preocupes, también los compensaremos!

Paso 1: crear una clase de generador de cuadrícula de datos

Queremos construir una herramienta que nos permita crear cuadrículas de datos dinámicamente para cualquier tabla de base de datos que tengamos. Esto significa que el código no está vinculado a ninguna estructura de tabla específica y, por lo tanto, es independiente de los datos en sí. Todo lo que el codificador (el desarrollador que usa nuestra clase) debe saber es el nombre de la tabla que se va a transformar en una cuadrícula y la clave principal de esa tabla. Aquí está el previo de la clase que desarrollaremos durante la mayor parte de este tutorial:

<?php
class Datagrid{
    private $hide_pk_col = true;
    private $hide_cols = array();
    private $tbl_name = '';
    private $pk_col = '';
    private $headings = array();
    private $tbl_fields = array();
}
?>

La clase Datagrid bien podría agregarse a la carpeta de la aplicación/biblioteca, pero la vamos a agregar como ayuda al marco CodeIgniter. ¿Por qué? Debido a que cargar bibliotecas no nos permite pasar argumentos al constructor de la clase, cargarlo como ayuda resolverá el problema. Este punto tendrá más sentido para ti cuando hayamos terminado de escribir el constructor.

El método constructor de clase

public function __construct($tbl_name, $pk_col = 'id'){
    $this->CI =& get_instance();
    $this->CI->load->database();
    $this->tbl_fields = $this->CI->db->list_fields($tbl_name);
    if(!in_array($pk_col,$this->tbl_fields)){
        throw new Exception("Primary key column '$pk_col' not found in table '$tbl_name'");
    }
    $this->tbl_name = $tbl_name;
    $this->pk_col = $pk_col;
    $this->CI->load->library('table');
   

Ya tenemos mucho que hacer; pero no te preocupes, ya que te lo explicaré todo en el siguiente párrafo.

El constructor toma dos argumentos: el primero es el nombre de la tabla en tu base de datos que desea mostrar como una cuadrícula de datos al usuario; el segundo parámetro es el nombre de la columna que sirve como clave principal para esa tabla (más sobre esto más adelante). Dentro del cuerpo del constructor, instanciamos el objeto CodeIgniter, el objeto de base de datos y la clase/biblioteca de tabla HTML. Todos estos serán necesarios durante la vida útil de un objeto de cuadrícula de datos y ya están integrados en el marco de CI. Ten en cuenta que también verificamos si la clave principal realmente existe en la tabla dada y, en caso de que no, lanzamos una excepción que informa el error. Ahora la variable miembro $this->tbl_fields estará disponible para su uso posterior, por lo que no tenemos que recuperar la base de datos nuevamente.

«Podemos usar el comando $CI->db->list_fields($tbl_name) para obtener los nombres de todos los campos que tiene una tabla. Sin embargo, para un mejor rendimiento, recomiendo almacenar los resultados en caché «.

Método para personalizar los títulos de las tablas

public function setHeadings(array $headings){
    $this->headings = array_merge($this->headings, $headings);
}

Esto te permite personalizar los encabezados de la tabla de la cuadrícula de datos, es decir, puedes sobrescribir los nombres de las columnas originales para ciertos campos de la tabla. Se necesita un array asociativo, como este: regdate =>»Registration Date». En lugar de solo el «Regdate» técnico como el encabezado de la columna para ese tipo de datos, tenemos un título más legible por humanos en su lugar. En breve se dará a conocer el código responsable de la aplicación de los títulos.

Método para ignorar/ocultar campos de tabla

public function ignoreFields(array $fields){
    foreach($fields as $f){
        if($f!=$this->pk_col)
            $this->hide_cols[] = $f;
    }
}

ignoreFields recibe un array que contiene los campos que se ignorarán al obtener datos de la base de datos. Esto es útil cuando tenemos tablas con muchos campos, pero solo queremos ocultar un par de ellos. Este método es lo suficientemente inteligente como para rastrear un intento de ignorar el campo de clave principal y luego omitirlo. Esto es así porque la clave principal no se puede ignorar por razones técnicas (verás por qué en breve). Aún así, si deseas ocultar la columna de clave principal para que no aparezca en el Reino Unido, puedes usar el método hidePkCol:

public function hidePkCol($bool){
    $this->hide_pk_col = (bool)$bool;
}

Este método recibe un valor booleano para indicar si queremos ocultar la columna de clave primaria para que no aparezca en la cuadrícula de datos. A veces, es una idea desagradable mostrar los datos pkey, que generalmente es un código numérico sin ningún significado para el usuario.

Método de la siguiente instancia:

private function _selectFields(){
    foreach($this->tbl_fields as $field){
        if(!in_array($field,$this->hide_cols)){
            $this->CI->db->select($field);
            // hide pk column heading?
            if($field==$this->pk_col && $this->hide_pk_col) continue;
                $headings[]= isset($this->headings[$field]) ? $this->headings[$field] : ucfirst($field);
        }
    }
    if(!empty($headings)){
        // prepend a checkbox for toggling 
        array_unshift($headings,"<input type='checkbox' class='check_toggler'>");
        $this->CI->table->set_heading($headings);
    }
     
}

Aquí tenemos un método auxiliar; por eso tiene el modificador «private» y tiene como prefijo un carácter subrayado (convención de código). Será utilizado por el método generate() – explicado brevemente – para tener los campos de tabla apropiados seleccionados y también los encabezados apropiados establecidos para la tabla (generador) object. Observa la siguiente línea:

$headings[]= isset($this->headings[$field]) ? $this->headings[$field] : ucfirst($field);

Aquí es donde aplicamos los encabezados personalizados o recurrimos a los predeterminados si no se da ninguno. Si se supone que la columna pk está oculta de la pantalla, se omitirá su encabezado. También observa la siguiente línea:

array_unshift($headings,"<input type='checkbox' class='dg_check_toggler'>");

El comando anterior indica al programa que anteponga una casilla de verificación «Master» como el primer encabezado de la tabla. Esa casilla de verificación es diferente de otras casillas de verificación en la cuadrícula en que le permite al usuario marcar o desmarcar todas las casillas de verificación de una sola vez. Esta funcionalidad de alternancia se implementará en unos momentos con un simple fragmento de código jQuery.

Método para generar/renderizar la cuadrícula de datos

Ahora viene lo que realmente hace el trabajo por nosotros:

public function generate(){
    $this->_selectFields();
    $rows = $this->CI->db
            ->from($this->tbl_name)
            ->get()
            ->result_array();
    foreach($rows as &$row){
        $id = $row[$this->pk_col];
         
        // prepend a checkbox to enable selection of items/rows
        array_unshift($row, "<input class='dg_check_item' type='checkbox' name='dg_item[]' value='$id' />");
         
        // hide pk column cell?
        if($this->hide_pk_col){
            unset($row[$this->pk_col]);
        }
    }
     
    return $this->CI->table->generate($rows);
}

El método generate, como su nombre indica, es responsable de generar la propia cuadrícula de datos. Debes llamar a este método solo después de haber configurado el objeto de acuerdo a tus necesidades. Lo primero que hace es llamar al método $this->_selectFields() para realizar las acciones que explicamos anteriormente. Ahora tiene que buscar todas las filas de la base de datos y luego recorrerlas, agregando casillas de verificación al comienzo de cada fila:

// prepend a checkbox to enable selection of items/rows
array_unshift($row, "<input class='dg_check_item' type='checkbox' name='dg_item[]' value='$id' />");

Dentro del bucle foreach en el método generate, si el indicador $this->hide_pk_col se establece en true, entonces debemos desarmar la entrada de clave primaria en la matriz $row array para que no aparezca como una columna cuando $this->CI->table object procesa todas las filas y genera la salida html final. En este punto, está bien eliminar la clave principal, si es necesario, porque ya no necesitamos esa información.

Pero, ¿qué hace el usuario con las filas seleccionadas/marcadas? Para responder a esto, he preparado algunos métodos más. El primero nos permite crear «action buttons» sin tener que conocer ningún detalle técnico sobre cómo funciona internamente el sistema de cuadrícula:

Método para agregar botones a un formulario de cuadrícula de datos

public static function createButton($action_name, $label){
    return "<input type='submit' class='$action_name' name='dg_action[$action_name]' value='$label' />";
}

Simplemente pasa el nombre de la acción como primer argumento y un segundo argumento para indicar la etiqueta del botón generado. Se genera automáticamente un atributo class para ese botón para que podamos jugar con él más fácilmente cuando estamos trabajando con él en nuestro JavaScript. Pero, ¿cómo sabemos si el usuario ha pulsado un determinado botón de acción? La respuesta se puede encontrar en el siguiente método:

public static function getPostAction(){
// get name of submitted action (if any)
    if(isset($_POST['dg_action'])){
        return key($_POST['dg_action']);
    }
}

¡Sí! Otro método estático que nos ayuda cuando se trata de formularios. Si se ha enviado alguna cuadrícula de datos, este método devolverá el nombre de la acción (u «operation») asociada con ese evento de envío. Además, otra herramienta útil para procesar nuestros formularios de cuadrícula de datos es …

public static function getPostItems(){
    if(!empty($_POST['dg_item'])){
        return $_POST['dg_item'];
    }
    return array();
}

… que devuelve un array que contiene los ids seleccionados para que puedas rastrear qué filas se han seleccionado en la cuadrícula y luego realizar alguna acción con ellas. Como ejemplo de lo que se puede hacer con una selección de ids de fila, he preparado otro método, este es un método de instancia, y no uno estático, porque hace uso de los recursos de instancia del objeto para hacer su negocio:

public function deletePostSelection(){
// remove selected items from the db
    if(!empty($_POST['dg_item']))
        return $this->CI->db
            ->from($this->tbl_name)
            ->where_in($this->pk_col,$_POST['dg_item'])
            ->delete();
}

Si se marcó al menos una casilla de verificación, el método deletePostSelection() generará y ejecutará una declaración SQL como la siguiente (supón $tbl_name='my_table' y $pk_col='id'):

DELETE FROM my_table WHERE id IN (1,5,7,3,etc...)

… que eliminará efectivamente las filas seleccionadas de la capa persistente. Podría haber más operaciones que podrías agregar a una cuadrícula de datos, pero eso dependerá de las características específicas de tu proyecto. Como consejo, podrías extender esta clase a, digamos, InboxDatagrid, por lo que, más allá del método deletePostSelection, podría incluir operaciones adicionales, como moveSelectedMessagesTo($place), etc…

Poniendo todo junto

Ahora, si has seguido este tutorial paso a paso, deberías haber terminado con algo similar a lo siguiente:

class Datagrid{
     
    private $hide_pk_col = true;
    private $hide_cols = array();
    private $tbl_name = '';
    private $pk_col = '';
    private $headings = array();
    private $tbl_fields = array();
     
    function __construct($tbl_name, $pk_col = 'id'){
        $this->CI =& get_instance();
        $this->CI->load->database();
        $this->tbl_fields = $this->CI->db->list_fields($tbl_name);
        if(!in_array($pk_col,$this->tbl_fields)){
            throw new Exception("Primary key column '$pk_col' not found in table '$tbl_name'");
        }
        $this->tbl_name = $tbl_name;
        $this->pk_col = $pk_col;
        $this->CI->load->library('table');
         
    }
     
    public function setHeadings(array $headings){
        $this->headings = array_merge($this->headings, $headings);
    }
     
    public function hidePkCol($bool){
        $this->hide_pk_col = (bool)$bool;
    }
     
    public function ignoreFields(array $fields){
        foreach($fields as $f){
            if($f!=$this->pk_col)
                $this->hide_cols[] = $f;
        }
    }
     
    private function _selectFields(){
        foreach($this->tbl_fields as $field){
            if(!in_array($field,$this->hide_cols)){
                $this->CI->db->select($field);
                // hide pk column heading?
                if($field==$this->pk_col && $this->hide_pk_col) continue;
                $headings[]= isset($this->headings[$field]) ? $this->headings[$field] : ucfirst($field);
            }
        }
        if(!empty($headings)){
            // prepend a checkbox for toggling 
            array_unshift($headings,"<input type='checkbox' class='dg_check_toggler'>");
            $this->CI->table->set_heading($headings);
        }
         
    }
     
    public function generate(){
        $this->_selectFields();
        $rows = $this->CI->db
                ->from($this->tbl_name)
                ->get()
                ->result_array();
        foreach($rows as &$row){
            $id = $row[$this->pk_col];
             
            // prepend a checkbox to enable selection of items
            array_unshift($row, "<input class='dg_check_item' type='checkbox' name='dg_item[]' value='$id' />");
             
            // hide pk column?
            if($this->hide_pk_col){
                unset($row[$this->pk_col]);
            }
        }
         
        return $this->CI->table->generate($rows);
    }
     
    public static function createButton($action_name, $label){
        return "<input type='submit' class='$action_name' name='dg_action[$action_name]' value='$label' />";
    }
     
    public static function getPostAction(){
    // get name of submitted action (if any)
        if(isset($_POST['dg_action'])){
            return key($_POST['dg_action']);
        }
    }
     
    public static function getPostItems(){
        if(!empty($_POST['dg_item'])){
            return $_POST['dg_item'];
        }
        return array();
    }
     
    public function deletePostSelection(){
    // remove selected items from the db
        if(!empty($_POST['dg_item']))
            return $this->CI->db
                ->from($this->tbl_name)
                ->where_in($this->pk_col,$_POST['dg_item'])
                ->delete();
    }
 
}

Aviso: no olvides guardar este archivo como datagrid_helper.php y colocarlo en «application/helper/»

Paso 2: Probar la clase auxiliar de cuadrícula de datos con un controlador CodeIgniter

Ahora crearemos un controlador de prueba simple y cargaremos la clase Datagrid como ayuda en su constructor. Pero antes de eso, debemos definir una tabla de base de datos ficticia y completarla con algunos datos de muestra.

Ejecuta el siguiente SQL para crear la base de datos y la tabla de usuario:

CREATE DATABASE `dg_test`;
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(80) NOT NULL,
  `password` varchar(32) NOT NULL,
  `email` varchar(255) NOT NULL,
  UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

A continuación, agreguemos algunos usuarios:

INSERT INTO `users` (`id`, `username`, `password`, `email`) VALUES
(1, 'david', '12345', 'david@domain.com'),
(2, 'maria', '464y3y', 'maria@domain.com'),
(3, 'alejandro', 'a42352fawet', 'alejandro@domain.com'),
(4, 'emma', 'f22a3455b2', 'emma@domain.com');

Ahora, guarda el siguiente código como «test.php«, y agréguelo a la carpeta «aplicación/controladores»:

<?php
class Test extends CI_Controller{
 
    function __construct(){
        parent::__construct();
        $this->load->helper(array('datagrid','url'));
        $this->Datagrid = new Datagrid('users','id');
    }
     
    function index(){
        $this->load->helper('form');
        $this->load->library('session');
 
        $this->Datagrid->hidePkCol(true);
        $this->Datagrid->setHeadings(array('email'=>'E-mail'));
        $this->Datagrid->ignoreFields(array('password'));
         
        if($error = $this->session->flashdata('form_error')){
            echo "<font color=red>$error</font>";
        }
        echo form_open('test/proc');
        echo $this->Datagrid->generate();
        echo Datagrid::createButton('delete','Delete');
        echo form_close();
    }
     
    function proc($request_type = ''){
        $this->load->helper('url');
        if($action = Datagrid::getPostAction()){
            $error = "";
            switch($action){
                case 'delete' :
                    if(!$this->Datagrid->deletePostSelection()){
                        $error = 'Items could not be deleted';
                    }
                break;
            }
            if($request_type!='ajax'){
                $this->load->library('session');
                $this->session->set_flashdata('form_error',$error);
                redirect('test/index');
            } else {
                echo json_encode(array('error' => $error));
            }
        } else {
            die("Bad Request");
        }
    }
 
}
?>

Se crea una instancia de esta clase y se pasa como referencia al miembro $this->Datagrid .Ten en cuenta que obtendremos datos de una tabla llamada «usuarios» cuya clave principal es la columna «id»; luego, en el método de índice, tomamos los siguientes pasos: configurar el objeto Datagrid, renderizarlo dentro de un formulario con un botón de eliminar agregado y ver si todo funciona como se esperaba:

Pregunta: ¿Qué sucede cuando se envía el formulario?

Respuesta: El método «Test::proc()» se encarga de procesar el formulario y elegir la operación correcta para aplicar contra los id que fueron seleccionados por el remitente del formulario. También se encarga de las solicitudes AJAX, por lo que enviará un objeto JSON al cliente. Esta función compatible con AJAX será útil cuando jQuery entre en acción, ¡que es ahora mismo!

«Siempre es una buena idea crear aplicaciones web que compensen cuando JavaScript/AJAX no está disponible. De esta manera, algunos usuarios tendrán una experiencia más rica y más rápida, mientras que aquellos que no tengan JavaScript habilitado aún podrán usar la aplicación con normalidad «.

Paso 3: Implementando de Ajax (¡jQuery al rescate!)

Cuando el usuario hace clic en el botón (o cualquier otro botón de acción), nos gustaría, quizás, evitar que la página se recargue y tenga que generar todo de nuevo; ¡Esto podría hacer que el usuario de nuestra aplicación se duerma! Eludir este problema no será una tarea difícil si nos ceñimos a la biblioteca jQuery. Dado que este no es un tutorial para «principiantes», no voy a repasar todos los detalles relacionados con cómo obtener la biblioteca, cómo incluirla en la página, etc. Se espera que conozcas estos pasos por tu cuenta.

Crea una carpeta, llamada «js«, agrega la biblioteca jQuery dentro y crea un archivo de vista, llamado users.php. Abrd este nuevo archivo y agrega:

<html>
<head>
    <title>Users Management</title>
    <script src="<?php echo base_url(); ?>js/jquery-1.6.3.min.js"></script>
    <script src="<?php echo base_url(); ?>js/datagrid.js"></script>
</head>
<body>
<?php
        $this->Datagrid->hidePkCol(true);
        if($error = $this->session->flashdata('form_error')){
            echo "<font color=red>$error</font>";
        }
        echo form_open('test/proc',array('class'=>'dg_form'));
        echo $this->Datagrid->generate();
        echo Datagrid::createButton('delete','Delete');
        echo form_close();
?>
</body>
</html>

¿Te diste cuenta de que hemos movido el código de Test::index al nuevo script de vista? Esto significa que debemos cambiar el método Test::index() en consecuencia:

function index(){
    $this->load->helper('form');
    $this->load->library('session');
    $this->load->view('users');
}

Eso está mejor. Si deseas agregar algo de estilo a la cuadrícula, puedes usar el siguiente CSS (o hacer un mejor diseño por tu cuenta):

.dg_form table{
    border:1px solid silver;
}
 
.dg_form th{
    background-color:gray;
    font-family:"Courier New", Courier, mono;
    font-size:12px;
}
 
.dg_form td{
    background-color:gainsboro;
    font-size:12px;
}
 
.dg_form input[type=submit]{
    margin-top:2px;
}

Ahora, por favor, crea un archivo «datagrid.js», colócalo en el directorio «js» y comienza con este código:

$(function(){
	// cool stuff here...
})

Dentro de este cierre, escribiremos código que se encargará de controlar ciertos eventos de envío una vez que la página se haya cargado por completo. Lo primero que debemos hacer es rastrear cuando un usuario hace clic en un botón de envío en el formulario de cuadrícula de datos y luego enviar esos datos para que se procesen en el servidor.

$('.dg_form :submit').click(function(e){
		e.preventDefault();
		var $form = $(this).parents('form');
		var action_name = $(this).attr('class').replace("dg_action_","");
		var action_control = $('<input type="hidden" name="dg_action['+action_name+']" value=1 />');
		
		$form.append(action_control);
		
		var post_data = $form.serialize();
		action_control.remove();
		
		var script = $form.attr('action')+'/ajax';
		$.post(script, post_data, function(resp){
			if(resp.error){
				alert(resp.error);
			} else {
				switch(action_name){
					case 'delete' :
						// remove deleted rows from the grid
						$form.find('.dg_check_item:checked').parents('tr').remove();
					break;
					case 'anotherAction' :
						// do something else...
					break;
				}
			}
		}, 'json')
	})

Alternativamente, podríamos haber comenzado con algo como: $('.Dg_form').submit(function(e){...}). Sin embargo, dado que quiero rastrear qué botón se ha presionado y extraer el nombre de la acción elegida en función de él, prefiero vincular un controlador de eventos al botón de enviar y luego subir en la jerarquía de nodos para encontrar el formulario que el botón presionado pertenece a:

// finds the form
var $form = $(this).parents('form');
// extracts the name of the action
var action_name = $(this).attr('class').replace("dg_action_","");

A continuación, agregamos un elemento de entrada oculto dentro del elemento del formulario para indicar qué acción se está enviando:

// create the hidden input
var action_control = $('<input type="hidden" name="dg_action['+action_name+']" value=1 />');
// add to the form
$form.append(action_control);

Esto es necesario porque la función no considera que el botón de envío sea una entrada de formulario válida. Entonces debemos tener ese truco en su lugar al serializar los datos del formulario.

action_control.remove();

«¡No lo olvides: la función ignora el botón de enviar y lo descarta como una simple pieza de chatarra de marcado!»

Envíando datos del formulario al servidor

A continuación, procedemos a obtener el atributo action del elemento de formulario y anexamos la cadena «/ajax» a esa url, para que el método sepa que, de hecho, se trata de una solicitud AJAX. Después de eso, usamos la función jQuery.post para enviar los datos para ser procesados por el controlador apropiado, del lado del servidor, y luego interceptar el evento de respuesta con un callback/closure registrado:

var script = $form.attr('action')+'/ajax';
	$.post(script, post_data, function(resp){
		if(resp.error){
			alert(resp.error);
		} else {
			switch(action_name){
				case 'delete' :
					// remove deleted rows from the grid
					$form.find('.dg_check_item:checked').parents('tr').remove();
				break;
				case 'anotherAction' :
					// do something else...
				break;
			}
		}
	},'json')

Observa que estamos pidiendo que la respuesta se codifique como «json» ya que estamos pasando esa cadena como el cuarto argumento de la función $.post. El contenido de la devolución de llamada que trata de la respuesta del servidor debería ser bastante sencillo de comprender; determina si hay un error y, de ser así, lo alerta. De lo contrario, indicará que la acción fue procesada con éxito (en este caso, si se trata de una «» acción, eliminamos las filas relacionadas con los ids que fueron seleccionados por el usuario).

Paso 4: ¡Marca todo o nada!

Lo único que falta ahora es la funcionalidad de alternancia que prometí antes. Debemos registrar una función de devolución de llamada para cuando se haga clic en la casilla de verificación «Master», que tiene un atributo de clase establecido en «dg_check_toggler«. Agrega el siguiente fragmento de código después del anterior:

$('.dg_check_toggler').click(function(){
		var checkboxes = $(this).parents('table').find('.dg_check_item');
		if($(this).is(':checked')){
			checkboxes.attr('checked','true');
		} else {
			checkboxes.removeAttr('checked');
		}
	})

Cuando se hace clic en la casilla de verificación «toggler», si pasa a un estado «checked», todas las filas de la cuadrícula de datos correspondiente se marcarán simultáneamente; de lo contrario, todo estará desmarcado.

Pensamientos finales

No hemos llegado a la punta del iceberg cuando se trata de cuadrículas de datos para sistemas de gestión de contenido más complejos. Otras características que pueden resultar útiles son:

  • Ordenar la cuadrícula de datos por nombres de columna
  • Enlaces de paginación para navegar por la cuadrícula de datos
  • Editar/modificar enlaces para actualizar los datos de una sola fila
  • Mecanismo de búsqueda para filtrar resultados

Gracias por leer. Si desea un tutorial de seguimiento, házmelo saber en los comentarios.

0

Requerimientos de Codeigniter 4 y software a emplear

Antes de comenzar a desarrollar vamos a ver que necesitamos para poder empezar a trabajar con Codeigniter 4, es decir el software necesario el cual va contener Codeigniter. Para eso vamos a ir a la sección de requerimientos y vamos a ver que básicamente necesitamos PHP en su versión 7.4 o superior.

También vamos a necesitar algunos de los motores de base de datos básicamente SQL o SQL lite, nosotros empleamos SQL básicamente te sirve cualquiera de los ya conocidos ambientes de desarrollo para trabajar con PHP.

tengamos en cuenta puedes emplear este llamado Wamps Server que es bastante común.

Este conocido como UwAmp que te permite cambiar fácilmente entre versiones distintas de PHP.

Este también conocido como saben que tambien tiene bastante tiempo en el mercado XAMPP

Adicionalmente a estos vas a necesitar composer ya que nosotros vamos a emplear Composer para instalar Codeigniter 4 , composer simplemente es un manejador de dependencias.

Básicamente es una especie de manejador de paquetes en el cual nosotros podemos instalar distintas librerías, distintas dependencias mediante la línea de comandos, esta es la manera el cual nosotros instalamos Codeigniter 4 ya que de esta manera vamos a poder actualizar fácilmente nuestro framework así que si vas a instalar algunos de estos ambientes de desarrollo que te presente anteriormente vas a necesitar también instalar composer.

Ahora bien también puedes instalar en tu equipo este software conocido como laragon que ya nos trae de manera predeterminada Xampp que básicamente los ambientes de desarrollo de software que está presente anteriormente para desarrollar con PHP.

también nos trae incorporado un conjunto de software de manera por defecto vamos a ir a la sección que dice Why laragon?

vamos a ver a qui que básicamente nos trae todos estos software instalados de manera por defecto de tal manera que no lo tenemos que instalar uno a uno, ya nos trae instalado apache , PHP, SQL y también estará instalado de manera por defecto con composer, aparte como otro software como Node.js, por lo cual es un excelente candidato para desarrollar nuestras aplicaciones modernas en PHP.

Aparte de esto también nos trae un agregado que vamos a volar un poco más adelante vamos a ir ahora a la sección de Docs y vamos a ver que de manera por defecto nos va construir unas URL limpias lo cual lo veremos en otro post más adelante.

Básicamente no tenemos que acceder de la manera tradicional que simplemente colocar localhost/app, si no de manera por defecto ya nos arma URL de la siguiente manera app.test

Otra característica bastante interesante que es un software portable lo que significa que tú puedes mover fácilmente entre distintos discos que inclusive no te va dar conflictos en caso que tu tengas instalado XAMPP, Wamp Server o sea lo que sea que tu tengas instalado en tu equipo es decir tú lo puedes instalar de manera paralela a tu ambiente del que tengas en tu equipo.
Este es el que nosotros recomendamos para nuestros colegas y es el que nosotros empleamos en nuestros desarrollos.