Skip to content

Bug: Model inserts the casted $primaryKey value when using an entity and casts. #7797

@MaulanaMalikS

Description

@MaulanaMalikS

PHP Version

8.2

CodeIgniter4 Version

4.3.3

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

cli-server (PHP built-in webserver)

Database

No response

What happened?

If I understand correctly, based on the documentation, casting only occurs when a value is read, not when a value is inserted, and only raw values are inserted.

However, when using an entity and casting the primary key, the casted value is inserted instead of the raw value.

For example, I am using the Entity constructor to generate a binary representation of UUID for the primary key:

public function __construct(?array $data = null)
{
    parent::__construct($data);

    $this->attributes['id'] = Services::uuid()->generateBinary();
}

When using toRawArray(), all values are correct and ready to be inserted into the database. The $primaryKey value is a binary string.
When using toArray(), all values are casted correctly, including the $primaryKey being casted to a string representation.

However, when I insert the entity into the model, the inserted $primaryKey value is casted.
When I check the database, string representations are inserted instead of the raw binary representation.

Steps to Reproduce

  1. Create an Entity and use casting on the primary key. Here is my example:
<?php

namespace App\Entities\Application;

use CodeIgniter\Entity\Entity;
use App\Entities\Cast\Uuid as CastUuid;
use Config\Services;

/**
 * @property string $id
 * @property string $name
 * @property string $logo
 */
class Application extends Entity
{
    protected $dates   = ['deleted_at'];
    protected $casts = [
        'id' => 'uuid',
    ];

    protected $castHandlers  = [
        'uuid' => CastUuid::class
    ];

    public function __construct(?array $data = null)
    {
        parent::__construct($data);

        $this->attributes['id'] = Services::uuid()->generateBinary();
    }
}
  1. Create a Model and set $returnType to the Entity. Here is my example:
<?php

namespace App\Models\Application;

use CodeIgniter\Model;
use App\Entities\Application\Application as ApplicationEntitiy;

class Application extends Model
{
    protected $table = 'm_application';
    protected $primaryKey = 'id';
    protected $useAutoIncrement = false;
    protected $returnType = ApplicationEntitiy::class;
    protected $useSoftDeletes   = true;
    protected $allowedFields = ['name', 'logo'];

    // Dates
    protected $useTimestamps = true;
    protected $dateFormat    = 'datetime';
    protected $createdField  = null;
    protected $updatedField  = null;
    protected $deletedField  = 'deleted_at';

    public function getEntity(array $data = null): ApplicationEntitiy
    {
        return new ApplicationEntitiy($data);
    }
}
  1. Insert the data. In this case, I am using a Seeder:
<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;
use App\Models\Application\Application;

class ApplicationSeeder extends Seeder
{
    public function run()
    {
        $model = model(Application::class);
        $entity = $model->getEntity();

        $data = [
            'name' => 'User Management'
        ];

        $entity->fill($data);
        var_dump($model->insert($entity));
    }
}

Expected Output

The primary key should be inserted as a raw value.

Anything else?

My guess is that this code here:

$properties[$this->primaryKey] = $data->{$this->primaryKey};

gets the property directly, instead of using cast(false) or toRawArray().

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugVerified issues on the current code behavior or pull requests that will fix them

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions