Mezzair
Mezzair

Reputation: 317

CakePHP remove empty hasMany results

I've got the following code that is matching the user_id of the hasMany relationship. The sample results that I get back are as follows:

array(
(int) 0 => array(
'Scorecard' => array(
        'id' => '529e400a-6e98-4471-8465-04470a0a0a0a',
        'course_id' => '0a111cdd-4732-11e3-98e6-080027f3add4',
        'flag_count' => '0',
        'status' => '1',
    ),
    'ScorecardsUser' => array(
        (int) 0 => array(
            'id' => '529e400a-8a30-4e63-b6c6-04470a0a0a0a',
            'user_id' => '527d5dff-e9a0-40c0-8512-04510a0a0a0a',
            'scorecard_id' => '529e400a-6e98-4471-8465-04470a0a0a0a',
            'gross_score' => '50',
            'points_score' => '0',
            'match_score' => '0',
            'handicap' => '0',
            'team' => '0',
            'created' => '2013-12-03 20:33:14',
            'modified' => '2013-12-03 20:33:14'
        )
    )
),
(int) 1 => array(
    'Scorecard' => array(
        'id' => '52b0c20d-61e8-425d-9b8c-05d40a0a0a0a',
        'course_id' => '0a111cdd-4732-11e3-98e6-080027f3add4',
        'flag_count' => '0',
        'status' => '1',
    ),
    'ScorecardsUser' => array()
),

)

The first result it finds is exactly what I expect. However, the user_id doesn't match on the second one - hence the result is blank for ScorecardsUser. However, should that second result come out at all as it didn't match the condition on the hasMany model?

This is the code in the Scorecard Model:

public function getUsersScoreCards($user_id = null) {

    $this->bindModel(array(
        'hasMany' => array(
            'ScorecardsUser' => array(
                'conditions' =>array(
                    'ScorecardsUser.user_id' => $user_id
                )
            )
        )
    ));

    $this->recursive = 1;
    $this->Behaviors->load('Containable');
    $contain = array('ScorecardsUser');

    return $this->find('all', array('conditions' => array('Scorecard.status' => 1), 'contain' => $contain));

}

Upvotes: 0

Views: 952

Answers (1)

Nunser
Nunser

Reputation: 4522

The result will come back even if doesn't match the related models conditions. That happens when you're using Containable. It's how cake behaves.

If it bothers you, you have 3 ways to solve it.

1) Use joins instead of containable. With joins you will trim out Scorecard records that doesn't match the ScorecardUser condition. You can read about joins here.

2) Keep using containable if it's easier for you, and do a loop to trim the ones that doesn't have ScorecardUser

foreach($the_find_array as $i => $data)
  if (empty($data['ScorecardUser']))
      unset($the_find_array[$i]);

3) Do separate queries with containable. Fetch the ScorecardUser that has user_id = $user_id, get those scorecard_ids, and do another query that fetches the Scorecards with status 1 and within those ids

$this->find('all', array('conditions' => array('Scorecard.status' => 1,
                                               'Scorecard.id' => $ids_of_filtered_scorecardusers), 'contain' => $contain));

The join solution is the easiest one, but doesn't hurt to know the alternatives.

Upvotes: 2

Related Questions