views:

49

answers:

2

I am using cakephp 1.2 and I have an array that appears to have a value change even though that variable is not being manipulated. Below is the code to that is causing me trouble.

PLEASE NOTE - UPDATE Changing the variable name makes no difference to the outcome.

function findCountByString($string, $myArr=array()) {

$main_conditions['or'] = array();
$main_conditions['or']['Article.title LIKE '] = '%'.$string.'%';
$main_conditions['or']['Article.html_content LIKE '] = '%'.$string.'%';
$conditions['and'][] = $main_conditions;
$filter_conditions['or'] = array();
if(count($myArr) > 0) {
    # UPDATE NUMBER 2
    # if I comment out the below line everything is fine, this makes no sense!!!
    $filter_conditions['or']['ArticleEntity.entity_id'] = $myArr;
    $conditions['and'][] = $filter_conditions;
}

echo "Start of findCountByString()";
var_dump($myArr);

$test  = $this->find('count', array(
    'conditions' => $conditions,
    'joins' => array('LEFT JOIN `articles_entities` AS ArticleEntity ON `ArticleEntity`.`article_id` = `Article`.`id`'),
    'group' => 'Article.id'
    ));

echo "End of findCountByString()";
var_dump($myArr);

return $test;

}

I am getting the following output:

Start of findCountByString()

array(4) {
  [0]=>
  string(36) "4bdb1d96-c680-4c2c-aae7-104c39d70629"
  [1]=>
  string(36) "4bdb1d6a-9e38-479d-9ad4-105c39d70629"
  [2]=>
  string(36) "4bdb1b55-35f0-4d22-ab38-104e39d70629"
  [3]=>
  &string(36) "4bdb25f4-34d4-46ea-bcb6-104f39d70629"
}

End of findCountByString()

array(4) {
  [0]=>
  string(36) "4bdb1d96-c680-4c2c-aae7-104c39d70629"
  [1]=>
  string(36) "4bdb1d6a-9e38-479d-9ad4-105c39d70629"
  [2]=>
  string(36) "4bdb1b55-35f0-4d22-ab38-104e39d70629"
  [3]=>
  &string(38) "'4bdb25f4-34d4-46ea-bcb6-104f39d70629'"
}

The the value in my array have changed, and I don't know why?

Any suggestions?

+1  A: 

Probably $filters is a reference and it's being changed in the method call or pr itself has state/side effects. The second option can be eliminated by removing the calls to pr and replacing it with var_dump.

Your code snippet does not provide sufficient information. Your best option here is a debugger.

EDIT: Your last element is a reference (probably a remnant of a foreach by reference). Fix the code that builds the array so that it doesn't leave a reference in the last element.

Artefacto
I have added extra notes, changing the variable name makes no difference, I have also replaced pr() to print_r();
Lizard
@Lizard use "var_dump", not "print_r". What is `$myArr` being used in the function for, anyway?
Artefacto
I have updated the question to the FULL function, as I have found the line of code that is at fault, but it makes even less sense now.
Lizard
@Lizard OK, now with `var_dump`, you see the last element is a reference. There's something wrong with your code that builds the array that's passed to the function.
Artefacto
+1  A: 

Seems like the bug with accessing a PHP array by reference.

Due to peculiarities of the internal workings of PHP, if a reference is made to a single element of an array and then the array is copied, whether by assignment or when passed by value in a function call, the reference is copied as part of the array. This means that changes to any such elements in either array will be duplicated in the other array (and in the other references), even if the arrays have different scopes (e.g. one is an argument inside a function and the other is global)! Elements that did not have references at the time of the copy, as well as references assigned to those other elements after the copy of the array, will behave normally (i.e. independent of the other array).

This will not be fixed anytime soon. It is a deep seated problem in the implementation and fixing it would cause speed problems and numerous other problems, This is somthing that can be coded around too so should not cause massive problems.

http://bugs.php.net/bug.php?id=8130.

AlexV
I'd call this "intended behavior", not a bug. If an array has a reference and I copy it, why would I expect the reference to stop being one? Seems arbitrary, with the downside that doing otherwise would entail copying the element instead of just incrementing its reference count.
Artefacto
Ohh this is a bug and a really deep one. I've found at least 5 bug report on PHP.net and they were all acknowledged as such. It's just that fixing this would mean rewriting big chunk of PHP's core and will change too much thing all around for this "hassle" (who can be avoided pretty easily). Bottom line: don't use references on arrays. If you still think this is not a bug read carefully the article in the first link of my answer. After that if you still think it's "normal behavior", I'm glad for you :)
AlexV
@AlexV OK, I was thinking about the case you explicitly added a reference to an array, but, as the article points out, the reference flag is set also when creating a reference from an array element. Well, this certainly is not very normal, though once you understand how references are implemented in PHP, it's what you'd expect (namely there's no way to distinguish how the reference was created, i.e., what was the original symbol).
Artefacto