Created
July 7, 2016 12:34
-
-
Save half2me/2b4d9d97130a06692bb70fcd6c7a603e to your computer and use it in GitHub Desktop.
Inner JOIN bug in CakePHP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// So I'm going to be demonstrating a problem with INNER joins | |
//Bake automatically creates INNER JOINs for a belongsTo association, | |
// where the foreign key is not allowed to be null (Always BelongsTo) | |
// This is great if you have an (AlwaysBelongsTo) association, but | |
// when you don't always BelongTo another model, we need LEFT joins. | |
// The problem arised when you have a model that someTimesBelongsTo another model | |
// and that other model alwaysBelongsTo another model (LEFT, then INNER joins) | |
// Cake doesn't use proper parenthesis in these cases, but simply lines the joins up, | |
// one after another. | |
// Let me show you the following scenario | |
// Comments someTimesBelongsTo Articles (Lets say we can have stray comments) // LEFT JOIN here | |
// Articles alwaysBelongsTo Authors // INNER JOIN here | |
// CommentsTable.php | |
public function initialize(array $config) | |
{ | |
// ... | |
$this->belongsTo('Articles', [ | |
'joinType' => 'INNER' | |
]); | |
//... | |
} | |
// ArticlesTable.php | |
public function initialize(array $config) | |
{ | |
// ... | |
$this->belongsTo('Authors', [ | |
'joinType' => 'LEFT' // Or just leave this blank, I think LEFT joins are the default | |
]); | |
//... | |
} | |
// Now lets try the following code in our CommentsController.php | |
// Note that if we run this with an empty Articles and Authors table, it will still work fine | |
// Only thing we will notice, is that our entity will have a $entity->articles field set to null | |
$this->Comments->find() | |
->contain(['Articles']); | |
// Now lets try it this way: | |
$this->Comments->find() | |
->contain(['Articles', 'Articles.Authors']); // since we want to not only have articles, but their authors as well | |
// This works fine, if there are authors in the system, but try it when there are no authors. It will return an empty result. | |
// Not just an empty articles association, but it won't find any comments, because its doing an INNER JOIN. | |
// Of course if change the strategy to use a separate query that will work, but joining should work as well. I would suggest | |
// the proper use of parenthesis in such situations. | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment