We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Foreach vs Crazy Resultset

I have seen many weird bug but this one wins the prime. I cannot even define the reason or the what arounds with it. Let the code talk! :D

It's started with this

    $orders = OrderModel::find();

    foreach ($orders as $order) {
      $order->callSmth();
    }

    foreach ($orders as $ord) {
      try {
          if ( ! is_bool($ord)) {
              $ord->callAnotherThing();
          } else {
              throw new Exception('It became a boolean...');
          }
      } catch (Exception $e) {
          fwrite(STDOUT, 'It became a boolean!');
      }
    }

Oki, let me walk this through, the OrderModel after a simple foreach turns into a bool if I try to foreach it again; This is rather weird, but what is even more weird the unexpected result, when the $ord variable is being tested for bool, returns false, then the PHP drops an error saying I called callAnotherThing on a boolean... The model turns into boolean between the is_bool and the call, without any interaction or modification.

Nope, I am not crazy, who testing the model for bool on default, just added that because the error log had an entry saying I call the fn on a bool, and this is a debuging code.

But things get worse now. Today I found a code where an another result set turns into this joking madness, instead of the model turning into bool the following happens:

    $stacks = StackModel::find('status != "disposed"');

    foreach ($stacks as $stack) {
        if ($stack->status == 'disposed') {
            throw new Exception('Stack is disposed .... ' . $stack->status);
        }
    }

There is no getStatus modification on the model, if I call print_r($stacks->toArray()); the models prints the status as stored, but then when I start to iterate it, the $status variable turns into disposed, this makes no sense, there is not even a single line of code to do that, nothing is being called, just the foreach :D

No cache nor modifications on the model, I could not even turn the $ord variable into a boolean even if I try with the first fn called, no references are used nothing. The second example makes the least sense.

Usualy I know where or what can cause a bug, but I never seen anything like this.


Spec live server:

  • PHP: 5.6.29
  • OS: Debian 8.6
  • MySql: 5.7
  • Phalcon: 3.0.1

Spec dev server:

  • PHP: 5.6.27
  • OS: Debian 8.6
  • MySql: 5.7
  • Phalcon: 3.0.3

Forgot to mention but this is not constant, not happening with every resultset or query, it's just randomly starts to happen all around with a 100k+ line of code, the codes above worked perfectly for months now, without any update or change they started to break, and more and more problem happens day by day.

edited Jan '17

I would start with checking sql what query is being made and check with raw query what it's returning. It doesn't have to be phalcon problem.

edited Jan '17

Sadly the returning values are fine, before the iteration begins, if I call a print_r($resultSet->toArray()); I get the expected values.

In your first example, what do you see when you var_dump the $ord variable after $ord->callAnotherThing fails? The second one is weird, does it always happen to the same record when you're iterating or is it just random?

Also, what happens when you use a for($i =0;) count loop instead of foreach?

In the first the value turns into a false, even tho the is_bool test returns false. Second one happens with the "same" record, in terms of the last entry, but the stacks moving around fast, so happens with a different database row, it's just happens with the last entry for now.

Many more weird things started to fold out with the ResultSet, now I have a point where it can't count itself, even tho it has 2 object the ->count() returns with "1"

In your first example, what do you see when you var_dump the $ord variable after $ord->callAnotherThing fails? The second one is weird, does it always happen to the same record when you're iterating or is it just random?

Also, what happens when you use a for($i =0;) count loop instead of foreach?

Hm, what happens when you combine those two foreaches into one? I can't shake the feeling it has something to do with that.

Do you see the same behaviour on both your dev and live environment?

What is your db service set up ($di->set(...)? It reminds me of mysql cursor misconfiguration...