带有 SQL-UNION 的 Moodle 过滤器
Moodle Filters with SQL-UNION
当 SQL 查询中出现 UNION 时,我们如何才能使用 moodle 过滤器。下面的代码显示了过滤器不起作用的过滤器表单。该代码在不使用 UNION 时有效。
require_once($CFG->dirroot.'/filter_form.php');
$mform = new filter_form();
$firstnamefilter = '';
$lastnamefilter = '';
if ($formdata = $mform->get_data()) {
$firstnamefilter = $formdata->firstname;
$lastnamefilter = $formdata->lastname;
}
$toform->id = $id;
$mform->set_data($toform);
$mform->display();
$reporttable = new html_table();
$reporttable->head = array('Name', 'Email');
$reporttable->attributes['class'] = 'table';
$sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.email FROM {user} JOIN {user_enrolments} ue
ON u.id= ue.userid WHERE u.id = '.$id.'
UNION
SELECT ae.id, ae.username, ae.firstname, ae.lastname, ae.email FROM {auth_user} JOIN {user_enrolments} ue
ON ae.id= ue.userid WHERE u.id = '.$id.'
";
$params = array();
if (!empty($firstnamefilter)) {
$params['firstname'] = '%' . $DB->sql_like_escape($firstnamefilter) . '%';
$sql .= " AND " . $DB->sql_like('u.firstname', ':firstname', false);
} else if (!empty($lastnamefilter)) {
$params['lastname'] = '%' . $DB->sql_like_escape($lastnamefilter) . '%';
$sql .= " AND " . $DB->sql_like('u.lastname', ':lastname', false);
}
$mds = $DB->get_recordset_sql($sql, $params);
foreach ($mds $m) {
$reporttable->data[] = new html_table_row(array(implode(array($m->firstname. $m->lastname)), $m->email ));
}
echo html_writer::table($reporttable);
太棒了,你使用了正确的 like 函数!
对于 SQL,您需要为每个联合使用单独的 where 而不是在末尾。您还使用了 u.id = $id
,这会将其限制为一个用户 ID。
所以我修改了你的 SQL - 这应该有效。
$params = array();
$wheres1 = array();
$wheres2 = array();
if (!empty($firstnamefilter)) {
$params['firstname1'] = '%' . $DB->sql_like_escape($firstnamefilter) . '%';
$params['firstname2'] = $params['firstname1'];
$wheres1[] = $DB->sql_like('u.firstname', ':firstname1', false);
$wheres2[] = $DB->sql_like('ae.firstname', ':firstname2', false);
}
if (!empty($lastnamefilter)) {
$params['lastname1'] = '%' . $DB->sql_like_escape($lastnamefilter) . '%';
$params['lastname2'] = $params['lastname1'];
$wheres1[] = $DB->sql_like('u.lastname', ':lastname1', false);
$wheres2[] = $DB->sql_like('ae.lastname', ':lastname2', false);
}
$where1 = '';
$where2 = '';
if (!empty($wheres1)) {
$where1 = "WHERE " . implode(" AND ", $wheres1);
$where2 = "WHERE " . implode(" AND ", $wheres2);
}
$sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.email
FROM {user} u
JOIN {user_enrolments} ue ON u.id = ue.userid
{$where1}
UNION
SELECT ae.id, ae.username, ae.firstname, ae.lastname, ae.email
FROM {auth_user} ae
JOIN {user_enrolments} ue ON ae.id = ue.userid
{$where2}";
当 SQL 查询中出现 UNION 时,我们如何才能使用 moodle 过滤器。下面的代码显示了过滤器不起作用的过滤器表单。该代码在不使用 UNION 时有效。
require_once($CFG->dirroot.'/filter_form.php');
$mform = new filter_form();
$firstnamefilter = '';
$lastnamefilter = '';
if ($formdata = $mform->get_data()) {
$firstnamefilter = $formdata->firstname;
$lastnamefilter = $formdata->lastname;
}
$toform->id = $id;
$mform->set_data($toform);
$mform->display();
$reporttable = new html_table();
$reporttable->head = array('Name', 'Email');
$reporttable->attributes['class'] = 'table';
$sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.email FROM {user} JOIN {user_enrolments} ue
ON u.id= ue.userid WHERE u.id = '.$id.'
UNION
SELECT ae.id, ae.username, ae.firstname, ae.lastname, ae.email FROM {auth_user} JOIN {user_enrolments} ue
ON ae.id= ue.userid WHERE u.id = '.$id.'
";
$params = array();
if (!empty($firstnamefilter)) {
$params['firstname'] = '%' . $DB->sql_like_escape($firstnamefilter) . '%';
$sql .= " AND " . $DB->sql_like('u.firstname', ':firstname', false);
} else if (!empty($lastnamefilter)) {
$params['lastname'] = '%' . $DB->sql_like_escape($lastnamefilter) . '%';
$sql .= " AND " . $DB->sql_like('u.lastname', ':lastname', false);
}
$mds = $DB->get_recordset_sql($sql, $params);
foreach ($mds $m) {
$reporttable->data[] = new html_table_row(array(implode(array($m->firstname. $m->lastname)), $m->email ));
}
echo html_writer::table($reporttable);
太棒了,你使用了正确的 like 函数!
对于 SQL,您需要为每个联合使用单独的 where 而不是在末尾。您还使用了 u.id = $id
,这会将其限制为一个用户 ID。
所以我修改了你的 SQL - 这应该有效。
$params = array();
$wheres1 = array();
$wheres2 = array();
if (!empty($firstnamefilter)) {
$params['firstname1'] = '%' . $DB->sql_like_escape($firstnamefilter) . '%';
$params['firstname2'] = $params['firstname1'];
$wheres1[] = $DB->sql_like('u.firstname', ':firstname1', false);
$wheres2[] = $DB->sql_like('ae.firstname', ':firstname2', false);
}
if (!empty($lastnamefilter)) {
$params['lastname1'] = '%' . $DB->sql_like_escape($lastnamefilter) . '%';
$params['lastname2'] = $params['lastname1'];
$wheres1[] = $DB->sql_like('u.lastname', ':lastname1', false);
$wheres2[] = $DB->sql_like('ae.lastname', ':lastname2', false);
}
$where1 = '';
$where2 = '';
if (!empty($wheres1)) {
$where1 = "WHERE " . implode(" AND ", $wheres1);
$where2 = "WHERE " . implode(" AND ", $wheres2);
}
$sql = "SELECT u.id, u.username, u.firstname, u.lastname, u.email
FROM {user} u
JOIN {user_enrolments} ue ON u.id = ue.userid
{$where1}
UNION
SELECT ae.id, ae.username, ae.firstname, ae.lastname, ae.email
FROM {auth_user} ae
JOIN {user_enrolments} ue ON ae.id = ue.userid
{$where2}";