1

I am experiencing unexpected behaviour with the php function array_merge_recursive. Any advice or work-around would be appreciated.

The problem is with unexpected replacement of string keys with numeric key during the array_merge_recursive.

Details:

I have three associative arrays ($birthdays,$custom,$natHolidays), to which these values are programmatically added:

$birthdays['0808'][] = 'John MacLoud';
$birthdays['0819'][] = 'Susan MacLoud';
$birthdays['0903'][] = 'Catherine MacLoud';
$birthdays['1008'][] = 'Daisy Simpson';
$birthdays['1015'][] = 'Phillip MacLoud';
$birthdays['1212'][] = 'Aloysius Simpson';
$natHolidays['0317'][] = 'St. Patrick's Day';
$natHolidays['0317'][] = 'la Saint-Patrick';
$natHolidays['0701'][] = 'Canada Day';
$natHolidays['0701'][] = 'la fête du Canada';
$natHolidays['1031'][] = 'Hallowe'en';
$natHolidays['1031'][] = 'l'Halloween';
$natHolidays['1031'][] = 'Hallowe'en';
$natHolidays['1031'][] = 'l'Halloween';
$natHolidays['1111'][] = 'Remembrance Day';
$natHolidays['1111'][] = 'jour du souvenir';
$natHolidays['1224'][] = 'Christmas Eve';
$natHolidays['1224'][] = 'la vielle de Noël';
$natHolidays['1225'][] = 'Christmas';
$natHolidays['1225'][] = 'Noël';
$natHolidays['1226'][] = 'Boxing Day';
$natHolidays['1226'][] = 'le lendemain de Noël';
$natHolidays['1231'][] = 'New Year's Eve';
$natHolidays['1231'][] = 'vielle du jour de 'an';
$natHolidays['0907'][] = 'Labour Day';
$natHolidays['0907'][] = 'la fête du Travail';
$natHolidays['0922'][] = 'Equinox';
$natHolidays['0922'][] = 'l'equinoxe';
$natHolidays['1012'][] = 'Thanksgiving';
$natHolidays['1012'][] = 'l'action de grace';
$natHolidays['1101'][] = 'Daylight Savings ends';
$natHolidays['1101'][] = 'fall back';
$natHolidays['1221'][] = 'Solstice';
$natHolidays['1221'][] = 'le solstice';
$custom['0922'][] = 'Test value 1';
$custom['1122'][] = 'Test value 2';

I then merge the arrays: $dates = array_merge_recursive($birthdays,$custom,$natHolidays);

The resulting $dates array outputs:

["0808"]=>
  array(1) {
    [0]=>
    string(13) "John MacLoud"
  }
  ["0819"]=>
  array(1) {
    [0]=>
    string(13) "Susan MacLoud"
  }
  ["0903"]=>
  array(1) {
    [0]=>
    string(14) "Catherine MacLoud"
  }
  [0]=>
  array(1) {
    [0]=>
    string(15) "Daisy Simpson"
  }
  [1]=>
  array(1) {
    [0]=>
    string(14) "Phillip MacLoud"
  }
  [2]=>
  array(1) {
    [0]=>
    string(13) "Aloysius Simpson"
  }
  ["0317"]=>
  array(2) {
    [0]=>
    string(22) "St. Patrick's Day"
    [1]=>
    string(16) "la Saint-Patrick"
  }
  ["0701"]=>
  array(2) {
    [0]=>
    string(10) "Canada Day"
    [1]=>
    string(18) "la fête du Canada"
  }
  [3]=>
  array(2) {
    [0]=>
    string(15) "Hallowe'en"
    [1]=>
    string(16) "l'Halloween"
  }
  [4]=>
  array(2) {
    [0]=>
    string(15) "Remembrance Day"
    [1]=>
    string(16) "jour du souvenir"
  }
  [5]=>
  array(2) {
    [0]=>
    string(13) "Christmas Eve"
    [1]=>
    string(18) "la vielle de Noël"
  }
  [6]=>
  array(2) {
    [0]=>
    string(9) "Christmas"
    [1]=>
    string(5) "Noël"
  }
  [7]=>
  array(2) {
    [0]=>
    string(10) "Boxing Day"
    [1]=>
    string(21) "le lendemain de Noël"
  }
  [8]=>
  array(2) {
    [0]=>
    string(19) "New Year's Eve"
    [1]=>
    string(26) "vielle du jour de 'an"
  }
  ["0907"]=>
  array(2) {
    [0]=>
    string(10) "Labour Day"
    [1]=>
    string(19) "la fête du Travail"
  }
  ["0922"]=>
  array(3) {
    [0]=>
    string(14) "Test value 1"
    [1]=>
    string(7) "Equinox"
    [2]=>
    string(15) "l'equinoxe"
  }
  [9]=>
  array(1) {
    [0]=>
    string(15) "Test value 2"
  }
  [10]=>
  array(2) {
    [0]=>
    string(12) "Thanksgiving"
    [1]=>
    string(22) "l'action de grace"
  }
  [11]=>
  array(2) {
    [0]=>
    string(21) "Daylight Savings ends"
    [1]=>
    string(9) "fall back"
  }
  [12]=>
  array(2) {
    [0]=>
    string(8) "Solstice"
    [1]=>
    string(11) "le solstice"
  }

The only pattern I have noticed is that any key string starting with a '0' (i.e. 0130) works as expected, and any key string starting with a '1' (i.e. 1022) replaces the string key with a sequential numeric key.

Thoughts?

Btw:

Creating the new tag 'array-merge-recursive' requires at least 1500 reputation. Try something from the existing tags list instead.

1 Answer 1

1

PHP is loosely typed, and it is casting your array keys.

You could use integer as keys to avoid the cast:

$arr[10] = 'foo';

and not

$arr["10"] = 'foo';

Updated answer:

The casting is treating keys starting with "0" as strings, and so far so good. The other keys are treated like integers, and array_merge will renumber them starting from 0 (as it is happening here).

I know you are using array_merge_recursive, but it appears to behave the same.

Sign up to request clarification or add additional context in comments.

3 Comments

The MMDD string in the key seemed the easiest way to make connections between the DOY and the data — the alternatives seem to take longer and more elaborate workarounds. I guess that my "delving-deeper" question would be: "Why is php casting the string as an integer in this particular circumstance? I understand casting, but I don't understand how this example follows those rules.
Hey @Parapluie, i have updated my answer, maybe it could help you a bit more.
It took me while to fully grok this, but I now understand what's happening. Your answer helped, as did this question where someone comes at it from a different direction: stackoverflow.com/questions/4100488/… . I think that prepending my keys with a dummy alpha character should solve the casting problem (['d0130']). What a weird one this was!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.