2016-06-08 3 views
1

Mit CakePHP 3.x habe ich 3 Modelle: StudentProfile, Diploma1 und Diploma2.Mehrere übereinstimmende() und contain(), Bedingung für verwandte Datensätze zählen

  • StudentProfile hasMany Diploma1
  • StudentProfile hasMany Diploma2

Diploma1 einen ganzzahligen "Zustand" ein.

Ich brauche StudentProfiles zu erhalten, die:

  • hat eine (oder mehr) im Zusammenhang Diploma1 wo Diploma1.state = 2 OR
  • hat eine (oder mehrere) Diploma2 (keine Bedingung auf Diploma2 Feldern)

Ich muss die passenden Diploma1 und Diploma2 mit meinen StudentProfiles abrufen.

Ich benutze die Such-und Paginator-Komponenten, also muss ich dies mit einer Abfrage tun.

Vorerst I'v der Lage gewesen, indem Sie den ersten Teil zu bekommen:

$query = $this->StudentProfiles 
    ->find('search', $this->StudentProfiles->filterParams($this->request->query)) 
    ->contain(['Diploma1' => function ($q) { 
     return $q->where(['Diploma1.state' => 2]); 
    }]) 
    ->matching('Diploma1', function($q) { 
     return $q->where(['Diploma1.state' => 2]); 
    }) 
    ->distinct(['StudentProfiles.id']) 
    ; 

    $this->set('studentProfiles', $this->paginate($query)); 

Kombination Matching und enthält ermöglicht es mir, um den Zustand zu addieren und die dazugehörigen Diploma1 bekommen (wie ich es verstehe).

Jetzt muss ich auch alle StudentProfiles mit einem verwandten Diplom2 bekommen, das ist, wo ich stecken bleibe. Wenn ich

->contain(['Diploma2']) 

... zu meiner Anfrage hinzufügen, bekomme ich nur Diploma2 für StudentProfiles, die einen entsprechenden Diploma1 haben (wo state = 2), aber ich weiß nicht nur StudentProfiles mit verwandten Diploma2 erhalten (ohne passende Diploma1), das ist völlig normal.

So habe ich 2 Fragen:

  • wie kann ich alle StudentProfiles erhalten, die einen verwandten Diploma2 haben (? Dh fügen Sie eine Bedingung count (...)> 0 vielleicht)
  • wie kann ich Kombiniere dies mit einer passenden Klausel mit einer Bedingung (state = 2)?

Ich hoffe, das ist klar. Dank

Antwort

0

ein etwas anderer Ansatz, aber vielleicht hilft es

$query = $this->Profile->find(); 

$query->select([ 
    'Profile.id', 
    'Profile.name', 
    'D1.id', 
    'D1.name', 
    'D1.status', 
    'D1.profile_id', 
    'D2.id', 
    'D2.name', 
    'D2.status', 
    'D2.profile_id', 
    'd1c' => 'COUNT(D1.id)', 
    'd2c' => 'COUNT(D2.id)', 
]); 
$query->contain([ 
    'D1' => function($q) { 
     $q->where(['D1.status' => 2]); 
     return $q; 
    }, 
    'D2' 
]); 
$query->leftJoinWith('D1', function($q) { 
    return $q->where(['D1.status' => 2]); 
}); 
$query->leftJoinWith('D2', function($q) { 
    return $q; 
}); 
$query->having(function($q) { 
    return $q->or_([ 
     'd1c >' => 0, 
     'd2c >' => 0, 
    ]); 

}); 
$query->group('Profile.id'); 

ich nicht wirklich contain bekommen konnte erstellen beitreten, so hatte ich die leftJoinWith

+0

interessant an, ich geb dies versuchen Sie so schnell wie möglich, danke! – Flo

+0

funktioniert super bei meinem allerersten Test :), vielen Dank für diese "Frage-mit-Kuchen" Lektion! Ich verstehe einfach nicht, warum wir sowohl leftJoinWith als auch contain benötigen, aber es funktioniert. – Flo

+0

@Flo 'contain' ist wie ein anderer Bereich, so dass die' Hauptabfrage' nicht einmal über die Daten in 'contain' weiß, deshalb brauchen Sie' join' anstelle von 'contain'. –