Cakephp 3.x 在多级连接中过滤数组中的行
Cakephp 3.x Filter rows on array in multilevel joins
我的数据库的第一个重要结构:
teachers:
id, int
username, varchar
certificates:
id, int
teacher_id, int
vality_date, date
languages:
id, int
certificate_id, int
language_id, int
Teachers
有很多 Certificates
有很多 Languages
一位教师可以拥有多种语言的多个证书。多种语言可以在多个证书上拆分。
我正在尝试找到一种 cakephp 方式来获取所有拥有定义语言有效认证的教师,可能有多种认证,但很难在 cakephp 中构建查询。我尝试了很多,但我总是遇到会所有或只有一种要求的语言的老师。
你会如何解决这个问题?
您可以通过连接(或使用 QueryBuilder 调用的 matching()
。
如果您要使用:
$teachers = $this->Teachers->find()
->innerJoinWith('Certificates.Languages');
...您将有效地获得 table 名教师,每位教师都有证书,每种证书都有语言。也可能会有重复。
您现在可以过滤合并的数据(并排除重复数据):
$lang_list = ['NL', 'DE'];
$teachers = $this->Teachers->find()
->where(['Languages.lang IN' => $lang_list])
->innerJoinWith('Certificates.Languages')
->group('Teachers.id');
我不确定这是否会直接起作用,但肯定是这样的。
SQL IN
关键字可用于限制数组的值。或者,您可以构造多个 AND
语句(无论出于何种原因)。
另请注意,我个人更喜欢 ...JoinWith
而不是 matching
。 (没有真正的原因。)
为了完整起见,matching()
看起来像:
$lang_list = ['NL', 'DE'];
$teachers = $this->Teachers->find()
->matching('Certificates.Languages', function ($q) use ($lang_list) {
return $q->where(['lang IN' => $lang_list]);
});
我的数据库的第一个重要结构:
teachers:
id, int
username, varchar
certificates:
id, int
teacher_id, int
vality_date, date
languages:
id, int
certificate_id, int
language_id, int
Teachers
有很多 Certificates
有很多 Languages
一位教师可以拥有多种语言的多个证书。多种语言可以在多个证书上拆分。
我正在尝试找到一种 cakephp 方式来获取所有拥有定义语言有效认证的教师,可能有多种认证,但很难在 cakephp 中构建查询。我尝试了很多,但我总是遇到会所有或只有一种要求的语言的老师。
你会如何解决这个问题?
您可以通过连接(或使用 QueryBuilder 调用的 matching()
。
如果您要使用:
$teachers = $this->Teachers->find()
->innerJoinWith('Certificates.Languages');
...您将有效地获得 table 名教师,每位教师都有证书,每种证书都有语言。也可能会有重复。
您现在可以过滤合并的数据(并排除重复数据):
$lang_list = ['NL', 'DE'];
$teachers = $this->Teachers->find()
->where(['Languages.lang IN' => $lang_list])
->innerJoinWith('Certificates.Languages')
->group('Teachers.id');
我不确定这是否会直接起作用,但肯定是这样的。
SQL IN
关键字可用于限制数组的值。或者,您可以构造多个 AND
语句(无论出于何种原因)。
另请注意,我个人更喜欢 ...JoinWith
而不是 matching
。 (没有真正的原因。)
为了完整起见,matching()
看起来像:
$lang_list = ['NL', 'DE'];
$teachers = $this->Teachers->find()
->matching('Certificates.Languages', function ($q) use ($lang_list) {
return $q->where(['lang IN' => $lang_list]);
});