0

I'm having a strange issue with a CakePHP 2.1.1 Project.
The issue is that if I call a find() on the Competition model (in the following code), right after it I call a custom method in another model the operation fails with the following error:

Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'getAddedPlayersIds' at line 1

SQL Query: getAddedPlayersIds 

My CompetitionsController::view() code is as follows:

public function view($id = null) {
        $this->layout = 'competition';
        $this->Competition->id = $id;
        if (!$this->Competition->exists()) {
            throw new NotFoundException(__('Invalid competition'));
        }

        $active = $this->Competition->field('active', array('id' => $id));
        if (!$active) {
        $this->redirect(array('controller' => 'pages', 'action' => 'display', 'competition_inactive'));
        }
            //THIS IS WHERE IT BECOMES STRANGE:
        $competition = $this->Competition->find('first', array('conditions' => array('Competition.id' => $id)));

        $addedPlayersIds = $this->CompetitionsPlayer->getAddedPlayersIds($id);

            //SOME CODE INTENTIONALLY REMOVED HERE!!!       

        $this->set('playerShops', $playerShops);    
        $this->set('messages', $messages);
        $this->set('competition', $this->Competition->read(null, $id));
            //render() IS CALLED FOR A SPECIFIC REASON
        $this->render();
    }

This is what the CompetitionsPlayer::getAddedPlayersIds() method looks like:

public function getAddedPlayersIds($competitionId = null){
        if(!isset($competitionId)) {
            return false;
        }

        $this->displayField = 'player_id';
        return $this->find('list', array('conditions' => array('competition_id' => $competitionId)));
    }

I initially thought that it's somehow breaking, because of the variable name I'm assigning the return of the Model::find() operation to, which is 'competition', but what's more interesting is that if I move the Competition::find() call after the CompetitionsPlayer::getAddedPlayersIds() it works!
Furthermore if I rename the variable it will sometimes work, and sometimes not...!?
I still can't figure out which is when because I currently have no time to research this further. Notice that according to the debug information the query that gets executed over the database is:

getAddedPlayersIds

which is the name of the function I'm calling!

As I mentioned I already know the workaround for this - just swap the two calls.But what if the first was to be before the seconds and there was no other way to implement the task at hand??
All I want now is to know why this happens?

tereško
  • 58,060
  • 25
  • 98
  • 150
Borislav Sabev
  • 4,776
  • 1
  • 24
  • 30
  • At the end it turned out that this line: $active = $this->Competition->field('active', array('id' => $id)); Messes things up. As explained in my answer. – Borislav Sabev Jun 07 '12 at 12:43

2 Answers2

0

This usually happens when it cannot find the your model and Cakephp loads a default model instead, thus not having getAddedPlayersIds method and cake thinking its a magic query.

Here's what I suggest, double check your file names and paths.

One possible issue I can see is this line:

$this->CompetitionsPlayer->getAddedPlayersIds($id);

Should that not be:

$this->Competition->CompetitionsPlayer->getAddedPlayersIds($id);

by model association and chaining. How is that model set up? What are the relationships?

tigrang
  • 6,767
  • 1
  • 20
  • 22
  • Oops I failed to mention that the CompetitionsPlayer model is included in the $uses controller property. It is working when I don't call the find call on the Competitions Model. I also just tried going over the Model relationship Competition->CompetitionsPlayer as you suggested and as I expected it did not work. :) This shouldn't be a problem when the CompetitionsPlayer Model is included in the $uses property. Another thing that I didn't mention is that the CompetitionsPlayer Model is a join model, which is kind-a obvious according to the conventions. – Borislav Sabev May 18 '12 at 14:58
  • If its a join table you don't need it in $uses, if you setup the correct association in Competition model. Do this: debug(get_class($this->CompetitionsPlayer)); Is the output `AppModel` or `CompetitionsPlayer`. If its the first, that's your issue. – tigrang May 18 '12 at 20:49
  • As I said, it is a join model, but this doesn't mean that if I have some other custom methods in it I shouldn't call them through $this->CompetitionsPlayer->methodName(). I did check get_class(), before I asked and the result was the correct CompetitionsPlayer class. – Borislav Sabev May 19 '12 at 06:28
0

It turns out that when using Model::field() the function's implementation sets recursive to -1 or 0. The CakePHP core code is:

public function field($name, $conditions = null, $order = null) {
//Some code ommited
    if ($this->recursive >= 1) {
        $recursive = -1;
    } else {
        $recursive = $this->recursive;
    }
//Some code ommited
}

So as explained this is the issue. I understand that this is a performance optimization, but I am not sure if this is a feature or a problem. To me this is strange behavior.

Borislav Sabev
  • 4,776
  • 1
  • 24
  • 30