Search code examples
phpjoincakephpquery-buildercakephp-3.x

Join sub-query after contain joins in CakePHP 3


I am currently experiencing an issue in CakePHP 3 - I am trying to join a subquery onto an existing query, however the ORM is adding the subquery BEFORE processing the "contain" method, but the subquery join relies on some of the contained tables. Is there any way to force the joins to run after contain?

My code is fairly long and convoluted but I will write a simple example:

$articles = $this->find()
  ->select(['Articles.id', 'Articles.title', 'Users.id'])
  ->contain(['Users','Tags']);

$subQuery = $this->find()
  ->select(['text' => 'Articles.body', 'user_id' => 'Users.id', 'article_id' => 'Articles.id'])
  ->contain(['Users','Tags']);

$articles
  ->join([
    'ArticleText' => [
      'table' => $subQuery,
      'type' => 'LEFT',
      'conditions' => ['ArticleText.user_id = Users.id', 'ArticleText.article_id = Articles.id']
    ]);

Now this code is overly simple and obviously unnecessary, but the issue is essentially that the ORM will generate a query that tries to perform the join first, and the join will fail because Users.id has not been joined yet. Is there any way to make the contains run first?


Solution

  • AFAIK the order cannot (yet) be influenced, containments and matchings (that's also the *JoinWith() methods) will come after manual joins, see also https://github.com/cakephp/cakephp/issues/10746.

    So you'll probably have to join the Users association manually too, instead of using contain().