unbindModel and $this->paginate()
Published on Aug 20, 2009 by Jamie MunroUgggh what a disaster today was! On a client's site, we have an older version of CakePHP, pre containable functionality. Because of this, we have to use unbindModel and bindModel to accomplish the same functionality.
Over the past while, it has not been such a big deal. However, for some other unknown reason, a search feature wasn't returning back the appropriate associative data. This had been working for quite some time, then suddenly stopped. As I mentioned, I'm not exactly sure when and why it stopped working, but it did.
Regardless of that factor, I was tasked with solving the issue. It was pretty easy to determine it was a join issue, so the first step was to force recursion. I did this before the $this->paginate() query; however, all of the data that was attempted to be joined caused a memory problem. I knew because of this I had to limit the data being joined on.
I proceeded to open my model and see all of the tables that were marked in the various join types (hasMany, belongsTo, etc...). I updated the controller to do an unbindModel prior to my query. Once completed, I saved and reloaded the webpage. Still nothing, data was not being unbinded.
I then proceeded to turn debugging on so I could see the queries. It was the weirdest thing, the paginateCount query that gets run immediately before the paginate query was clearly unbinded, but the proceeding query was not!
Once I realized this, I begin looking further at the unbindModel function. I so rarely use it, that I didn't even know that it took a second parameter. After a quick glance at the API: http://api.cakephp.org/class/model#method-ModelunbindModel it was immediately obvious to me what the problem was. By default, when you unbindModel something, it only works on the next query! If we were doing a straight find query instead of paginate, there would be no issues because it would work for that query. With paginate, however, the first query is the count query, so in this scenario it was fine and the second one was not. The secret is to pass "false" as the second parameter to the unbindModel function.
$this->User->unbindModel(array('hasMany' => 'Comment'), false);