我有两个问题:
我是否有一种更干净的方法来执行此准备好的语句?似乎这里发生了很多事情。
您能否在代码中指出“我如何对此进行清理”的部分进行解决?我要确保它的安全。
顺便说一句,这一切似乎都很好。只是想修复一下。
this
答案 0 :(得分:3)
如前所述,htmlentities()
与防止SQL注入无关。当您希望将某些内容输出到HTML并希望避免XSS漏洞时使用它。
我不会将所有这些查询都写为单独的子查询。单个SQL语句的结果不太可能需要获取所有这些信息。尝试将大量工作塞入单个SQL调用中并不会使其效率大大提高,但是确实使您编写代码变得更加困难。
请记住以下智慧:
每个人都知道调试的难度是编写程序的两倍。因此,如果您在编写时尽可能聪明,那么将如何调试它?
所以这是我的编码方式:
如果使用参数化查询,则根本不需要清理。但是,如果需要,这是一种更简单的方法:
$customer_id = (int) $_GET['customer_id'];
是的!只需强制转换为(int)
。编写此代码很简单,在代码审查中也很容易解释,并且比函数调用执行起来更快。
然后将SQL分为几个查询,以一种明智的方式将它们分组,因此您不需要子查询或列别名。更简单的查询更易于编码,更易于调试,更易于修改(如果您以后需要这样做)(或者,如果另一个开发人员需要对其进行修改,他们将感谢您编写更易于使用的代码)。
获得首次访问的一种简单方法是按created_at排序并使用LIMIT 1。
$sql = "SELECT bdi, pain, suicidality FROM treatment_log WHERE treatment_fk = ?
ORDER BY created_at LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows1 = $stmt->fetch_all(MYSQLI_ASSOC);
获取最后一次访问-按created_at 降序排序并使用LIMIT 1。
$sql = "SELECT bdi, pain, suicidality, DATE(created_at) AS last_visit
FROM treatment_log WHERE treatment_fk = ?
ORDER BY created_at DESC LIMIT 1";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows2 = $stmt->fetch_all(MYSQLI_ASSOC);
这是一个技巧:在MySQL中true为1,false为0,因此您可以SUM()
1来作为对某些表达式为true的行进行计数的一种方式。
$sql = "SELECT COUNT(*) AS completed_treatments,
SUM(missed_treatments='yes') AS number_of_missed_treatments
FROM treatment_log WHERE treatment_fk = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows3 = $stmt->fetch_all(MYSQLI_ASSOC);
其他查询非常简单。
$sql = "SELECT COUNT(*) AS completed_bdis FROM bdi WHERE bdi_fk = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows4 = $stmt->fetch_all(MYSQLI_ASSOC);
$sql = "SELECT f_name, l_name, status, mrn, ohip, sex, address, city, country,
phone, about, date_of_birth, protocol, treatment_location, area, dx, room,
coil, target_threshold, number_of_treatments, motor_threshold,
threshold_multiplier, created_at, updated_at
FROM customers WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $customer_id);
$stmt->execute();
$rows5 = $stmt->fetch_all(MYSQLI_ASSOC);
在所有这些查询中,我们只需为每个查询绑定一次$customer_id
,这使编写此代码的方式更加容易。无需费心计算长字符串“ iiii ...”的长度并将其与参数数量匹配。
P.S .:我没有测试此代码,因此,如果有错别字,我相信您可以解决。
答案 1 :(得分:2)
开始于:
SELECT {customer fields},
{MIN/MAX(treatment log fields)},
COUNT(*) as completed_treatements
SUM(missed_treatment='yes') AS number_of_missed_treatments
FROM customers
LEFT JOIN treatment_log ON treatment_log.treatment_fk=customers.id
WHERE customer.id=?
bdi
似乎无关