CakePHP has find('threaded') which lets you fetch records recursively. A good example is threaded comments. Say, you have Articles hasMany Comments, and each comment can have a parent, linked via parent_comment_id.
You define your association as usual. Then in the Comments table add the following:
public function beforeFind($event, $query, $options, $primary)
{
$query->find('threaded', [
'parentField' => 'parent_comment_id'
]);
}
This allows you to define an association and call $this->Articles->find('all')->contain('Comments') as normal, yet still benefit from the built-in threaded feature.