codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.39k stars 1.9k forks source link

Bug: The model fails to save entities when they have internal entities. #6336

Closed Patricio-Byte-Solution closed 2 years ago

Patricio-Byte-Solution commented 2 years ago

PHP Version

8.0

CodeIgniter4 Version

4.2.1

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

apache

Database

MySQL

What happened?

The model fails to save entities when they have internal entities. This occurs because of an error in the code in system\Model.php. Specifically in the function objectToRawArray(). When "parent::objectToRawArray($data, $onlyChanged); " is called in that function, the parameter "$recursive" is missing.

    /**
     * Takes a class an returns an array of it's public and protected
     * properties as an array with raw values.
     *
     * @param object|string $data
     * @param bool          $recursive If true, inner entities will be casted as array as well
     *
     * @throws ReflectionException
     *
     * @return array|null Array
     */
    protected function objectToRawArray($data, bool $onlyChanged = true, bool $recursive = false): ?array
    {
        $properties = parent::objectToRawArray($data, $onlyChanged);

        // Always grab the primary key otherwise updates will fail.
        if (
            method_exists($data, 'toRawArray') && (! empty($properties) && ! empty($this->primaryKey) && ! in_array($this->primaryKey, $properties, true)
            && ! empty($data->{$this->primaryKey}))
        ) {
            $properties[$this->primaryKey] = $data->{$this->primaryKey};
        }

        return $properties;
    }

Steps to Reproduce

$entityFather = new FatherEntity();

$entityFather->name      = 'Patricio';
$entityFather->sonEntity = new SonEntity([ 'name' => 'Maximo', 'age' => 18 ]);

// Get the raw array with $onlyChanged = false and $recursive = true
$rawArray = $entityFather->toRawArray(false,true);

// $rawArray is now:
Array(
     'name'      => 'Patricio',
     'sonEntity' => SonEntity Object (
        ....
        ...
    )
)

Expected Output

// $rawArray should be

Array(
    'name'      => 'Patricio',
    'sonEntity' => Array(
        'name'    => 'Maximo',
        'age'     => '18',
    )
)

Anything else?

Thank you very much for your work.

kenjis commented 2 years ago

Duplicate of #4360 ?

MGatner commented 2 years ago

Maybe need to revive #4368? @najdanovicivan are you available/interested to complete that?

najdanovicivan commented 2 years ago

@MGatner I’m willing to work on this one but I’m currently on vacation. I wont be able to start working on this one before the September 5th

MGatner commented 2 years ago

Not a problem! We're all volunteers doing what we can when we can πŸ€— If this isn't feasible for you then please speak up so others will take it on - no judgement whatsoever (I haven't written code for CI4 in months).

ping-yee commented 2 years ago

Does this issue has been solved at current develop branch? Because I can't reproduce the output by using the same Steps to Reproduce code.

image

This is the output what I get, as this image shows that the type of sonEntity is array without SonEntity Object.

kenjis commented 2 years ago

Does this issue has been solved at current develop branch?

Yes, I cannot reproduce the issue.

On develop branch.

<?php

namespace App\Controllers;

use CodeIgniter\Entity\Entity;

class Home extends BaseController
{
    public function index()
    {
        $entityFather = new Entity();

        $entityFather->name      = 'Patricio';
        $entityFather->sonEntity = new Entity(['name' => 'Maximo', 'age' => 18]);

        $rawArray = $entityFather->toRawArray(false, true);

        dd($rawArray);
    }
}
$ php public/index.php 

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ $rawArray                                                                                                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
array (2) [
    'name' => string (8) "Patricio"
    'sonEntity' => array (2) [
        'name' => string (6) "Maximo"
        'age' => integer 18
    ]
]
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Called from .../app/Controllers/Home.php:18 [dd()]
kenjis commented 2 years ago

The model fails to save entities when they have internal entities. This occurs because of an error in the code in system\Model.php. Specifically in the function objectToRawArray(). When "parent::objectToRawArray($data, $onlyChanged); " is called in that function, the parameter "$recursive" is missing.

https://github.com/codeigniter4/CodeIgniter4/blob/6234f0ed45c66da356f88255e831336978b3127d/system/Model.php#L706-L708

I don't know this is a bug or not.

MGatner commented 2 years ago

I don't know this is a bug or not.

Looks like it to me!