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

Importar Excel en MySQL usando Phpspreadsheet en CodeIgniter

PhpSpreadsheet es una biblioteca escrita en PHP puro y ofrece un conjunto de clases que le permiten leer y escribir varios formatos de archivo de hoja de cálculo como Excel y LibreOffice Calc

Instalación

Use Composer para instalar PhpSpreadsheet en su proyecto:

composer require phpoffice/phpspreadsheet

Si está construyendo su instalación en una máquina de desarrollo que está en una versión de PHP diferente al servidor donde se implementará, o si su versión de la CLI de PHP no es la misma que su tiempo de ejecución, como php-fpm Apache mod_php, entonces es posible que desee para agregar lo siguiente a su composer.json antes de instalar:

{
"require": {
"phpoffice/phpspreadsheet": "^1.23"
},
"config": {
"platform": {
"php": "7.3"
}
}
}

y luego corre

composer install

para garantizar que se recuperen las dependencias correctas para que coincidan con su entorno de implementación.

Ahora que ya tenemos en nuestro proyecto Phpspreadsheet, vamos a realizar una serie de pasos para poder subir un archivo Excel.

1.- Vamos a crear un formulario y un archivo de ejemplo para este ejercicio.

<form method="post" action="<?= base_url ?>spreadsheet_import" enctype="multipart/form-data">
    <div class="form-group">
        <input type="file" name="upload_file" class="form-control" placeholder="Ingresa un excel" id="upload_file">
    </div>
    <div class="form-group">
        <input type="submit" name="submit" class="btn btn-primary">
    </div>
</form>

Ahora la estructura de nuestro Excel será la siguiente.

2.- Controlador

En su controlador, obtenga el archivo y verifique la extensión.

pathinfo - get the file extension (PATHINFO_EXTENSION);

Nuestro metodo debe quedar de la siguiente manera:

public function spreadsheet_import(){
    $upload_file = $_FILES['upload_file']['name'];
    $extension = pathinfo($upload_file,PATHINFO_EXTENSION);

    if($extension == 'csv'){
        $reader= new \PhpOffice\PhpSpreadsheet\Reader\Csv();
    }else if($extension == 'xls'){
        $reader= new \PhpOffice\PhpSpreadsheet\Reader\Xls();
    }else {
        $reader= new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
    }

    $spreadsheet = $reader->load($_FILES['upload_file']['tmp_name']);
    $sheetdata = $spreadsheet->getActiveSheet()->toArray();
    $seetcount = count($sheetdata);

    if($seetcount > 1){
        for ($i=1; $i < $seetcount; $i++) { 
            $nombre = $sheetdata[$i][0];
            $edad = $sheetdata[$i][1];
            $pais = $sheetdata[$i][2];

            $param['nombre'] = $nombre;
            $param['edad'] = $edad;
            $param['pais'] = $pais;
            
            $this->Mregistro->registro($param);
            
        }
        redirect(base_url(), 'refresh');	
    }

}

De esta manera implementamos Phpspreadsheet en CodeIgniter para realizar la carga de dichos documentos.

0

5 razones por las que utilizar CodeIgniter

De vez en cuando te encuentras con una entrada en un blog o una discusión en un foro sobre qué framework de aplicación PHP es el mejor. Cada uno tiene sus propios positivos y negativos, pero la verdadera respuesta a esa pregunta es que depende del programador. Cada programador tiene un estilo diferente y prioridades diferentes cuando se trata de adoptar un kit de herramientas para usar al crear aplicaciones. Hoy vamos a tratar los beneficios de utilizar CodeIgniter (CI) con 5 buenas razones:

1. Documentación de primera categoría.

De lejos, la mayor ventaja de CI sobre cualquier otro framework es su documentación. 
La documentación de CI es 10 veces mejor que la de otros frameworks que he encontrado y creo firmemente que es porque CI está respaldado por una empresa y no solo por una comunidad. 

2. Una gran comunidad de usuarios activos.

La última vez que revisé, había más de 57.000 miembros registrados en los foros de CI. Es una gran comunidad de usuarios y enormemente práctica cuando tienes un problema o alguna pregunta en el tintero, además, el sitio web de CI tiene un foro y una wiki donde buscar las respuestas adecuadas. 

3. No es necesaria una «instalación».

Lo creas o no, una de las cosas más difíciles es la instalación de frameworks
No hay necesidad de paquetes PEAR o modificaciones de servidor para poner el framework en funcionamiento. Sólo tienes que subir los archivos a su servidor y te olvidas.

4. Todas las herramientas que necesitas en un mismo paquete

Calendario, correo electrónico, codificación zip, validación, carga, sesiones, pruebas unitarias … eso es sólo algunas de las bibliotecas incorporadas que vienen con CI. También incluye un montón de asistentes predeterminados para cosas como formularios, manejo de archivos, arreglos, cadenas, cookies, directorios y más. Además, por si eso no fuera suficiente, puedes crear tus propias bibliotecas y asistentes o usar código que ha sido desarrollado por la comunidad de CI y publicado en la wiki.

5. Fácil de entender y extender.

Con CI también es fácil escribir nuevas bibliotecas, cambiar el comportamiento de las bibliotecas existentes y simplemente cambiar el comportamiento general del framework con poco esfuerzo.

0

UUID vs autoincremental como clave primaria

Al trabajar con bases de datos como MySql es común utilizar una clave primaría entera autoincremental que permita distinguir y referenciar cada uno de los registros. El problema surge cuando se tienen muchas computadoras remotas escribiendo una gran cantidad de registros al mismo tiempo, en este caso el proceso de inserción sería el cuello de botella ya que la generación de claves, aunque rápida, podría retrasar el ingreso de datos. Si, en cambio, se generan bases por separado para que cada una maneje una carga de inserción menor entonces las claves se repetirían y se perdería la función principal de la clave primaria. Una solución para estos escenarios en la utilización de un UUID como clave primaria.

¿Qué es un UUID?

El UUID, (universally unique identifier) es un número generado de 128 bits. En su forma canónica se expresa como 32 dígitos hexadecimales que son divididos en 5 grupos que al ser separados por guiones da un total de 36 caracteres en total.

Ventajas de utilizar UUID como clave primaria

  • Se garantiza la individualidad de cada clave : Aunque se utilicen varias tables, bases de datos y servidores las UUID seran diferentes.
  • Facilidad de unión de tablas: Si se trabaja en paralelo es posible unir registros o tablas enteras sin generar un conflicto por claves duplicadas
  • Permite la creación de relaciones sin necesidad de esperar a una de las partes: Si la tabla B tiene una relación con la tabla A es posible generar el registro de la tabla B con un UUID y luego agregar el registro en A con el UUID ya generado. En el caso de una clave primaria autoincremental es necesario crear antes el registro A para que pueda asignarse su clave.
  • La creación de claves puede ser externa : Aún trabajando en una misma base de datos la tarea de la creación de la clave puede generarse de manera paralela.

Desventajas de utilizar UUID como clave primaria

  • Ocupan más espacio que una clave autoincremental: Utiliza 128 bytes mientras que un entero utiliza solo 4 bytes.
  • No permiten ordenar rápidamente por fecha de creación: Al utilizar claves autoincrementales el orden se genera automáticamente ya que los números son secuenciales.
  • El proceso de inserción puede ser lento para grandes volúmenes de datos: En algunos experimentos se ha detectado un aumento del tiempo de inserción al aumentar el volumen de datos.

¿Cómo guardar las claves UUID?

Aunque el tamaño de UUID es de 128 bytes es posible utilizar un binario de solo 16 bytes para ahorrar espacio y de esta manera mejorar el rendimiento: Al crear la tabla es necesario especificar que la clave primaria será un campo binario de 16 bytes

CREATE TABLE `nombreTabla`( 
    `clavePrimaria` BINARY( 16 ) NULL ,
    PRIMARY KEY ( `clavePrimaria` ) 
)ENGINE = INNODB ;

Antes de insertar la clave está deberá ser generada y se deberán suprimir los guiones, luego la función UNHEX lo convertitá en binario antes de insertarlo.

INSERT INTO `nombreTabla` 
( `clavePrimaria` ) VALUES ( UNHEX( 'c985098b44b141059a224ca2640d0885' ) 
);

Al obtener la clave se reconvertirá en hexadecimal con la función HEX y la aplicación deberá agregar los guiones de ser necesario.

SELECT HEX(clavePrimaria) AS clavePrimaria FROM `nombreTabla`

Conclusión

La utilización de UUID como claves primarias para base de datos dependerá mucho de la naturaleza de la aplicación, antes de tomar la decisión de no utilizar claves autoincrementales es importante tener en cuenta que la necesidad de una clave única universal no se da en la mayoría de los casos y aunque se plantea como una solución a el problema de la carga en paralelo no es la única disponible.