Filtering results causes field to "disappear"

Hii there,

Today I found a bug in my website caused by filtering some results.
this is my code:

public function __construct() {
  self::$_projectsTable = TableRegistry::get('Projects');
  self::$_projectsReleasesTable = TableRegistry::get('ProjectsReleases'); 
  self::$_projectsDescriptionsTable = TableRegistry::get('ProjectsDescriptions');
}

public static function findProjects(bool $withRelease = true) {
  $projects = self::$_projectsTable
    ->find();
  
  if($withRelease) {
    $projects = $projects
      ->select(['Projects.id'])
      ->select(self::$_projectsTable)
      ->matching('ProjectsReleases', function ($q) {
        $conditions = [['published' => 1]];
        if(Permission::check('view_privatereleases', 1)) {
          $conditions[] = ['published' => 0];
        }
        
        if(Permission::check('view_prereleases', 1)) {
          $conditions[] = ['published' => -1];
        }
        
        return $q
        ->where(['OR' => $conditions]);
      })
      ->distinct(['Projects.id']);
  }
  
  $projects = $projects->contain([
    'ProjectsDescriptions'
  ]);
    
  return $projects;
}

So what happens is that when I call findProjects with the $withRelease being true, it will return only the projects with releases visible by the user (based on permissions).
This part works absolutely fine but when I try to contain the ProjectsDescriptions, it goes wrong since it just completely ignores that statement.

When I set the $withRelease to false, it will also show projects without a release but it does load the ProjectsDescriptions just fine.

So my question is: why does this happen and how can I fix it?

Doing the following instead of a contain works fine but I’d still like to know why this happens and how to properly fix this.

$projects = self::$_projectsTable->loadInto($projects, ['ProjectsDescriptions']);

not sure if i understand correctly you want to use https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#custom-finder-methods ?
so basicly it would boild down to

return $this->Projects->find($withRelease ? 'withProjects' : 'all')
   ->contain(['ProjectsDescriptions']);

also side notes:

  1. you dont need to assign $projects = $projects-> each time
  2. use ModelAwareTrait; and $this->loadModel('Projects'); IMHO are easier to use than self::$_projectsTable = TableRegistry::get('Projects');
  3. if your tables are associated you dont need to load them you can just use $this->Projects->ProjectsDescriptions in your table code

EDIT:
as for your question you dont ->select anything from ProjectsDescriptions when $withRelease = true; thats why it queries DB but dont hydrate objects

Thanks for your explanation.

I didn’t know about the ModelAwareTrait so it’s hard to use that (goodluck trying to use something you don’t even know about :slight_smile: ).
I’ll update my code soon™ to use this instead.

EDIT: I can’t use the ModelAwareTrait since the methods are all static :\

You did notice @Graziel’s edit about your use of select and why it’s breaking your results?

No, but now I did :slight_smile:

yeah sorry for that i knew the answer, got sidetracked and got back to writing again

as for static methods try to avoid them they are pain to test

I’ll keep that in mind :slight_smile: