4

I have a content type that has a multi-value taxonomy field. When I create a new item and select several values, I am presented with the following error:

Array to string conversion in DrupalDefaultEntityController->cacheGet() (line 369 of /path/to/drupal/installation/includes/entity.inc).

The values are saved and everything appears to be working, but having this error appear every time is a little distracting, especially for the office staff who are actually entering the data.

Why does this happen?

  • Seems to be a core bug - drupal.org/node/1525176 – Mathankumar Apr 3 '13 at 5:30
  • 4
    This question appears to be off-topic because it is about core bug already posted in issue queue and apparently it is not a question that appeared during bug fixing. See this meta thread. – Mołot Aug 23 '13 at 13:10
  • 2
    @Molot - While the rule makes sense, like all rules it needs to be taken in concept. Some answers below have very good work-arounds, and sometimes a fresh pair of eyes on an old problem is all that is needed to get the ball rolling for a fix to be thought-up, created & coded, reviewed and last but not least ... merged. Hats off to IntegrityFirst for his answer. – stefgosselin Nov 23 '13 at 20:25
  • @stefgosselin I disagree - this question does not meet requrements from help center, nor any exceptions established in this meta question about exceptions to "no bugs" rule. Specific meta question about this question here. – Mołot Nov 24 '13 at 10:10
  • 1
    @Molot - Can we then agree to disagree? Are "rules" not made to be broken? Innovation often comes about when some rule is broken. If you hold the belief that this particular rule is an exception and should be applied by the book, it is your right. Just please keep in mind the bug is real, has been reported for a few years. All this while there is a very trivial fix that has been available!?! What is the harm in having this posted? Either a patch or an upgrade solves this issue. I got held up on this issue this post lead me to the solution, in my case, the post rocked. Cheers, amigo – stefgosselin Nov 24 '13 at 18:25
10

There's a very quick fix already, posted several weeks later after IntegrityFirst's answer.

See https://drupal.org/comment/7812787#comment-7812787 and this patch: https://drupal.org/files/drupal7.entity-system.1525176-104.patch (thanks to Molot for link to core bug thread).

It turns out that there is a function in Drupal core that supports multidimensional array diff causing this bug, but it's just not used there.

So, fix is to replace array_diff_assoc (not recursive) with drupal_array_diff_assoc_recursive (recursive, as it comes from its name) at line 364 of includes/entity.inc (see DrupalDefaultEntityController::cacheGet if line number differs or if patch fails).

5

Problem:

Since PHP 5.4 this notice appears when an array is compared as the string "array". The problem is in the file includes/entity.inc in the method cacheGet which gathers items from a static cache.

On line 369 it uses array_assoc_diff which compares the array indexes and values and returns the difference of the two arrays. Unfortunately it doesn't do this recursively meaning if it is a multidimensional array it will use "array" as a string and compare it with the other array. This is what causes the notice to occur.

It seems that the code is flawed and not performing the proper function get a given item from the cache.

First Solution:

The first solution I came up with to resolve this issue was to loop through each item of the condition and use the key of the conditions to check if the entity value for that key isset. If it it isn't set then there is a difference. This would mean that the entities with that key would be unset. I don't like using nested foreach loops though this came to me as the most immediate solution to resolve the problem.

The fix was to replace lines 369 to 371:

if (array_diff_assoc($conditions, $entity_values)) {
  unset($entities[$entity->{$this->idKey}]);
}

With this piece of code:

foreach ($conditions as $key=>$values) {
    if (!isset($entities[$key])) {
        unset($entities[$entity->{$this->idKey}]);
    }
    elseif ($conditions[$key] !== $entity_values[$key])
    {
        unset($entities[$entity->{$this->idKey}]);
    }
}

Second Solution:

A second thought I've had is to add a new function that has a similar functionality as the php function array_diff_assoc except that it does the comparison recursively. While looking through the on-line PHP manual I found a function that would accomplish that.

Place this at top of entity.inc after the opening php tags:

function array_diff_assoc_recursive($array1, $array2) {
    $difference=array();
    foreach($array1 as $key => $value) {
        if( is_array($value) ) {
            if( !isset($array2[$key]) || !is_array($array2[$key]) ) {
                $difference[$key] = $value;
            } else {
                $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                if( !empty($new_diff) )
                    $difference[$key] = $new_diff;
            }
        } else if( !array_key_exists($key,$array2) || $array2[$key] !== $value )     {
            $difference[$key] = $value;
        }
    }
    return $difference;
}

Replace what you see on line 369 from:

if (array_diff_assoc($entity_values, $conditions)) {

With this code:

if (array_diff_assoc_recursive($entity_values, $conditions)) {
  • 5
    This is a known issue, see drupal.org/node/1525176. The issue needs a test (easy, just an example call that triggers this notice) to be able to be committed. – Berdir Jul 17 '13 at 7:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.