Phalcon\Config::merge() of the same version of Phalcon (v3.1.2) behaves differently on PHP versions 7.0.14 and 7.0.17.
$config = new Phalcon\Config([
'a' => [
[
1
]
],
]);
$config->merge(new Phalcon\Config([
'a' => [
[
2
]
],
]));
$config is:

Everything is correct.
The same code results in the following $config value:

I expect $config to have the same value that's produced under v7.0.14.
Version => 3.1.2
Build Date => Apr 6 2017 21:22:10
Powered by Zephir => Version 0.9.7-1fae5e50ac
7.0.14 vs 7.0.170.9.7NginxPhalcon 3.2.x with PHP7.1.3 behaves exactly as Phalcon 3.1.2 & PHP7.0.17 (i.e. is broken).
I'll try to sort out. Thank you for pointing out
This "feature" broke our dev environment. We also found that the function works incorrectly when config keys are numerical, adding a letter to a key makes it work as intended.
The temporary solution is to overwrite the merge method in PHP:
class MyConfig Extends Phalcon\Config
{
function __merge($config, $instance = null)
{
if (gettype($instance) !== 'object') {
$instance = $this;
}
$number = $this->count($instance);
foreach (get_object_vars($config) as $key => $value) {
if ($localObject = $instance->{$key}) {
if (gettype($localObject) === 'object' && gettype($value) === 'object') {
if ($localObject instanceof Phalcon\Config && $value instanceof Phalcon\Config) {
$this->__merge($value, $localObject);
continue;
}
}
}
if (is_numeric($key)) {
$key = strval($number);
$number++;
}
$instance->{$key} = $value;
}
return $instance;
}
}
@piotrgolasz what makes you think it's a "feature"? hope you're being sarcastic :)
@sergeyklay
Do you know why this is happening? How could change in PHP minor version affect this, or is it something in Phalcon?
@temuri416, @piotrgolasz Could you please try to compile Phalcon from master (v3.1.2) by using ff769131f3751b590da702e3c7595411c07b0919 Zephir's commit?
@temuri416 more likely in zephir.
@sergeyklay any updates with this issue?
@piotrgolasz @temuri416 Could you please test by using latest Zephir from master branch and Phalcon 3.2.x ?
@sergeyklay
Looks like it's broken with PHP 7.1.5, with latest Phalcon 3.2.x:
Running the snipped above I am getting this:
Phalcon\Config Object
(
[a] => Phalcon\Config Object
(
[0] => Phalcon\Config Object
(
[0] => 1
)
[1] => Phalcon\Config Object
(
[0] => 2
)
)
)
Phalcon info:
Web framework delivered as a C-extension for PHP
phalcon => enabled
Author => Phalcon Team and contributors
Version => 3.2.0a
Build Date => Jun 14 2017 14:38:02
Powered by Zephir => Version 0.9.7-1fae5e50ac
Directive => Local Value => Master Value
phalcon.db.escape_identifiers => On => On
phalcon.db.force_casting => Off => Off
phalcon.orm.events => On => On
phalcon.orm.virtual_foreign_keys => On => On
phalcon.orm.column_renaming => On => On
phalcon.orm.not_null_validations => On => On
phalcon.orm.exception_on_failed_save => Off => Off
phalcon.orm.enable_literals => On => On
phalcon.orm.late_state_binding => Off => Off
phalcon.orm.enable_implicit_joins => On => On
phalcon.orm.cast_on_hydrate => Off => Off
phalcon.orm.ignore_unknown_columns => Off => Off
Powered by Zephir => Version 0.9.7-1fae5e50ac
Could you please use latest Zephir ?
Sure... where can I see the instructions on how to compile Phalcon with externally compiled Zephir?
Same result:
Phalcon\Config Object
(
[a] => Phalcon\Config Object
(
[0] => Phalcon\Config Object
(
[0] => 1
)
[1] => Phalcon\Config Object
(
[0] => 2
)
)
)
Web framework delivered as a C-extension for PHP
phalcon => enabled
Author => Phalcon Team and contributors
Version => 3.2.0a
Build Date => Jun 14 2017 17:43:44
Powered by Zephir => Version 0.9.8-096365f70b
Directive => Local Value => Master Value
phalcon.db.escape_identifiers => On => On
phalcon.db.force_casting => Off => Off
phalcon.orm.events => On => On
phalcon.orm.virtual_foreign_keys => On => On
phalcon.orm.column_renaming => On => On
phalcon.orm.not_null_validations => On => On
phalcon.orm.exception_on_failed_save => Off => Off
phalcon.orm.enable_literals => On => On
phalcon.orm.late_state_binding => Off => Off
phalcon.orm.enable_implicit_joins => On => On
phalcon.orm.cast_on_hydrate => Off => Off
phalcon.orm.ignore_unknown_columns => Off => Off
phalcon.orm.update_snapshot_on_save => On => On
phalcon.orm.disable_assign_setters => Off => Off
Provide please ini config example
You mean php.ini config?
$config = new Phalcon\Config([
'a' => [
[
1
]
],
]);
$config->merge(new Phalcon\Config([
'a' => [
[
2
]
],
]));
Your result is correct. You have TWO nested arrays. If you want to have returned a key with 1 and 2 value then you need to change your code to:
$config = new Phalcon\Config([
'a' => [
1
]
]);
$config->merge(new Phalcon\Config([
'a' => [
2
]
]));
Not sure why you have on php 7.0.14 diffrent result, maybe you were using outdated phalcon?
Are you saying that it was working incorrectly before and now it is correct?
Well actually im not sure, well i need to test it.
I don't care anymore which way is right - what was before or what's now. I don't need that type of merging anymore in my config (implemented it differently).
However, what's bugging me is that it's THE SAME combo of Phalcon & Zephir that behaves differently across minor PHP versions.
You sure that you had the same combo?
@temuri416 Could you please provide a small unit test to test it on Travis with PHP 5.6 - 7.1 ?
100%. Checked that several times, could not believe my eyes.
You can also ask @piotrgolasz.
The fact is, behaviour of Phalcon\Config::merge() has changed. And no one seem to understand why,
ok, but I never worked with that. Link for more info?
Just add new test here https://github.com/phalcon/cphalcon/blob/3.2.x/tests/unit/Config/Adapter/IniTest.php
ok, I'll try to do it this weekend.
I just think that result on php 7.0.17 is correct, not sure why you had returned 7.0.14, from logical point of view what i wrote above should be true.
Well i will need to test it, though from conditions i see there it should merge, for some reason it doesn't.
Well it looks like that we need to cast key to string most likely.
Okay so on first _merge run it properly go into "a" key of both configs. Then we have 0 key. This if fetch localObject, instance->{key} { just doesn't return anything, that's why it breaks. I guess we need to cast key.
Just code must be updated to something like:
for key, value in get_object_vars(config) {
let property = (string)key;
if fetch localObject, instance->{property} {
Yea i can confirm this is an fix, already tested @sergeyklay @temuri416 @piotrgolasz
Actually it's like this even in plain php, so im not sure how your code fixed it.
So it seems before v7.0.17 numeric keys were cast as strings
Yea and in 7.1.0-7.1.2 they went back to castings as ints and then go back to casting as string xD wtf
Well i guess just 7.1.3 was released same time as 7.0.17, right?
F**k.
Yea exactly, it's about release date, though it's pretty funny.
Still - there is just a bug in phalcon, and it was working because php was returning wrong value :D :D
So bug in php was fixing bug in phalcon, funny.
What is more stupid:
$key = 1;
$object->$key; // works
$object->1; // syntax error
@Jurigag, just PHP syntax
$object->{'1'}
Actually $object->{1} works too
Fixed in the 3.2.x branch. Feel free to open new issue if the problem appears again. Thank you for contributing.