Relaciones de tipo foraneas en CodeIgniter 4

- Andrés Cruz

In english

Las relaciones son el corazón de las base de datos relacional, las relaciones son un conjunto de reglas que describen cómo las tablas en la base de datos se relacionadas entre sí; y de aquí el nombre de relación. En una base de datos relacional, los datos se organizan en tablas, y cada tabla representa una entidad u objeto; pero muchas veces se relacionan entre si, si tenemos una relación carro, los carros tienen marcas, por lo tanto, podemos tener una tabla para los carros y otra para las marcas y las relacionamos entre si mediante el identificador único que se asigna a cada tabla, es decir, la PK; esta clave primaria cuando es establecida en la tabla a relacionar (en este ejemplo, debemos de registrar la PK de la tabla de modelos en la tabla de carros) se conoce como una restricción de tipo FOREIGN KEY o clave foranea en español. Veamos como manejarla en Codeigniter 4.

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'),
            ]);
Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy