cakephp/cakephp

Different behavior of Hash::insert and Hash::extract which leads to fatal error

ibering opened this issue · 1 comments

Description

Hi,

I try to insert a new value into an existing array with conditions using Hash::insert.

$data = [
            0 => ['up' => true, 'Item' => ['id' => 1, 'title' => 'first']],
            1 => ['Item' => ['id' => 2, 'title' => 'second']],
            2 => ['Item' => ['id' => 3, 'title' => 'third']],
            3 => ['Item' => ['id' => 3, 'title' => 'third']],
            4 => ['up' => true, 'Item' => ['id' => 4, 'title' => 'fourth']],
            5 => ['Item' => ['id' => 4, 'title' => 'fifth']],
        ];
        

If I try to insert data using {s} string wildcard, I get following error

$result = Hash::insert($data, '{n}.{s}[id=4].new', 9);

        /**
         * PHP Fatal error:  Uncaught Error: Call to a member function offsetExists() on bool in /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php:265
        Stack trace:
        #0 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php(340): Cake\Utility\Hash::_matches()
        #1 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php(342): Cake\Utility\Hash::insert()
        #2 /opt/openitc/frontend/src/Command/TestingCommand.php(141): Cake\Utility\Hash::insert()
        #3 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Console/BaseCommand.php(190): App\Command\TestingCommand->execute()
        #4 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Console/CommandRunner.php(334): Cake\Console\BaseCommand->run()
        #5 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Console/CommandRunner.php(172): Cake\Console\CommandRunner->runCommand()
        #6 /opt/openitc/frontend/bin/cake.php(12): Cake\Console\CommandRunner->run()
        #7 {main}
        thrown in /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php on line 265

        Fatal error: Uncaught Error: Call to a member function offsetExists() on bool in /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php:265
        Stack trace:
        #0 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php(340): Cake\Utility\Hash::_matches()
        #1 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php(342): Cake\Utility\Hash::insert()
        #2 /opt/openitc/frontend/src/Command/TestingCommand.php(141): Cake\Utility\Hash::insert()
        #3 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Console/BaseCommand.php(190): App\Command\TestingCommand->execute()
        #4 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Console/CommandRunner.php(334): Cake\Console\BaseCommand->run()
        #5 /opt/openitc/frontend/vendor/cakephp/cakephp/src/Console/CommandRunner.php(172): Cake\Console\CommandRunner->runCommand()
        #6 /opt/openitc/frontend/bin/cake.php(12): Cake\Console\CommandRunner->run()
        #7 {main}
        thrown in /opt/openitc/frontend/vendor/cakephp/cakephp/src/Utility/Hash.php on line 265
         */

If I replace {s} wildcard with a fixed key Item it works as expected

 $result = Hash::insert($data, '{n}.Item[id=4].new', 9); // no errors

Hash extract has no issue with using {s} wildcard

 $result = Hash::extract($data, '{n}.{s}[id=4]');
/**
        array:2 [
            0 => array:2 [
                "id" => 4
                "title" => "fourth"
            ]
            1 => array:2 [
                "id" => 4
                "title" => "fifth"
            ]
        ]
 */

My expected behavior would be that Hash::insert could use the same syntax as Hash::extract

CakePHP Version

4.5.3

PHP Version

8.1.2

Many thanks! 👍