joomla / joomla-cms

Home of the Joomla! Content Management System
https://www.joomla.org
GNU General Public License v2.0
4.73k stars 3.64k forks source link

Registry converts objects from merged registry to array #34981

Closed horvathcsabazoltan closed 3 years ago

horvathcsabazoltan commented 3 years ago

Steps to reproduce the issue

  1. Create a registry with an object item in it
  2. Merge it into another registry
  3. The resulting registry will return the item as array

Expected result

Preserve item type (including class)

Actual result

The original item returned as array

System information (as much as possible)

Joomla 3.9.26

Additional comments

ReLater commented 3 years ago

Can't confirm when using recursive = true in merge():

defined('_JEXEC') or die;
use Joomla\Registry\Registry;

$obj1 = new stdClass;
$obj1->a = 'a';
$obj1->b = 'b';
$obj1->c = 'c';

$arr1 = ['d', 'e', 'f'];

$registry1 = new Registry;
$registry2 = new Registry;

$registry1->set('val1', 1);
$registry1->set('val2', 2);
$registry1->set('obj1', $obj1);
$registry1->set('arr1', $arr1);
$registry2->set('val3', 3);

$registry2->merge($registry1, true);

echo '  <pre>' . print_r($registry2, true) . '</pre>';exit;

Output:

Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [val3] => 3
            [val1] => 1
            [val2] => 2
            [obj1] => stdClass Object
                (
                    [a] => a
                    [b] => b
                    [c] => c
                )

            [arr1] => Array
                (
                    [0] => d
                    [1] => e
                    [2] => f
                )

        )

    [initialized:protected] => 1
    [separator] => .
)
richard67 commented 3 years ago

@horvathcsabazoltan Can you check and report back if it works for you when doing as advised in the previous comment? Thanks in advance.

horvathcsabazoltan commented 3 years ago

It's almost perfect. But all classes are converted to stdClass.

defined('_JEXEC') or die;
use Joomla\Registry\Registry;

class FooBar {
    public $property1 = 'property-1-value';
    public $property2 = 'property-2-value';
}

$registry = new Registry();
$registry->set('associative-array-item', ['key1' => 'value1', 'key2' => 'value2']);
$registry->set('object-item', (object)['property1' => 'value1', 'property2' => 'value2']);
$registry->set('class-item', new FooBar);

echo '<pre>Before merge<br>';
print_r($registry);

$merge1 = new Registry(['merge' => '$recursive = false']);
$merge1->merge($registry);
$merge2 = new Registry(['merge' => '$recursive = true']);
$merge2->merge($registry, true);

echo 'Merge results:<br>';
print_r($merge1);
print_r($merge2);

echo '</pre>';

Output:

Before merge
Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [associative-array-item] => Array
                (
                    [key1] => value1
                    [key2] => value2
                )

            [object-item] => stdClass Object
                (
                    [property1] => value1
                    [property2] => value2
                )

            [class-item] => FooBar Object
                (
                    [property1] => property-1-value
                    [property2] => property-2-value
                )

        )

    [initialized:protected] => 
    [separator] => .
)
Merge results:
Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [merge] => $recursive = false
            [associative-array-item] => Array
                (
                    [key1] => value1
                    [key2] => value2
                )

            [object-item] => Array
                (
                    [property1] => value1
                    [property2] => value2
                )

            [class-item] => Array
                (
                    [property1] => property-1-value
                    [property2] => property-2-value
                )

        )

    [initialized:protected] => 1
    [separator] => .
)
Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [merge] => $recursive = true
            [associative-array-item] => stdClass Object
                (
                    [key1] => value1
                    [key2] => value2
                )

            [object-item] => stdClass Object
                (
                    [property1] => value1
                    [property2] => value2
                )

            [class-item] => stdClass Object
                (
                    [property1] => property-1-value
                    [property2] => property-2-value
                )

        )

    [initialized:protected] => 1
    [separator] => .
)
horvathcsabazoltan commented 3 years ago

Another strange thing: associative arrays are converted to stdClass if $recursive = true

defined('_JEXEC') or die;
use Joomla\Registry\Registry;

class FooBar {
    public $property1 = 'property-1-value';
    public $property2 = 'property-2-value';
    public $arrayprop = ['key1' => 'value1', 'key2' => 'value2'];
}

$registry = new Registry();
$registry->set('associative-array-item', ['key1' => 'value1', 'key2' => 'value2']);
$registry->set('class-item', new FooBar);

echo '<pre>Before merge<br>';
print_r($registry);

$merge2 = new Registry(['merge' => '$recursive = true']);
$merge2->merge($registry, true);

echo 'Merge results:<br>';
print_r($merge2);
echo '</pre>';

Output:

Before merge
Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [associative-array-item] => Array
                (
                    [key1] => value1
                    [key2] => value2
                )

            [class-item] => FooBar Object
                (
                    [property1] => property-1-value
                    [property2] => property-2-value
                    [arrayprop] => Array
                        (
                            [key1] => value1
                            [key2] => value2
                        )

                )

        )

    [initialized:protected] => 
    [separator] => .
)
Merge results:
Joomla\Registry\Registry Object
(
    [data:protected] => stdClass Object
        (
            [merge] => $recursive = true
            [associative-array-item] => stdClass Object
                (
                    [key1] => value1
                    [key2] => value2
                )

            [class-item] => stdClass Object
                (
                    [property1] => property-1-value
                    [property2] => property-2-value
                    [arrayprop] => stdClass Object
                        (
                            [key1] => value1
                            [key2] => value2
                        )

                )

        )

    [initialized:protected] => 1
    [separator] => .
)
ReLater commented 3 years ago

All I can say is: "That is by design." if I inspect the Registry class and and merge(), bindData() .

I think the right place for the issue/discussion is https://github.com/joomla-framework/registry

Joomla 3 uses version 1.6 at the moment https://github.com/joomla-framework/registry/blob/1.6.3/src/Registry.php . Joomla 4 the current 2 beta https://github.com/joomla-framework/registry/blob/2.0.0-beta/src/Registry.php . But there I don't see a change concerning this issue here.

horvathcsabazoltan commented 3 years ago

@ReLater: Thank you, I submitted a new issue where you said: https://github.com/joomla-framework/registry/issues/57

alikon commented 3 years ago

closing here then