
本文介绍如何通过 sql 的 like 多条件组合与 php 动态查询,实现在 `
在实际业务场景中,用户常需从大量合同记录中快速定位特定类型与年份的条目(例如“框架合同 2023 年度”)。仅靠前端 JavaScript 过滤效率低、不支持服务端逻辑(如权限控制或敏感字段脱敏),而简单拼接 SQL 字符串又易引发 SQL 注入风险。因此,推荐采用服务端动态构建安全查询 + 前端触发重载的方案。
✅ 推荐做法:使用 MySQLi 预处理语句(安全 & 可复用)
假设合同标题字段为 id_contrato(或你实际存储完整描述的字段,如 descripcion),以下为完整示例:
<?php
// 定义过滤关键词(可来自 $_GET 或表单提交)
$keywords = ['FRAMEWORK CONTRACT', '2023'];
// 构建动态 WHERE 条件
$conditions = [];
$params = [];
$types = '';
foreach ($keywords as $kw) {
$conditions[] = "id_contrato LIKE ?";
$params[] = '%' . trim($kw) . '%';
$types .= 's'; // string 类型
}
$whereClause = !empty($conditions) ? 'WHERE ' . implode(' AND ', $conditions) : '';
// 准备预处理语句
$stmt = $conexion->prepare("SELECT * FROM `contratos` $whereClause");
if ($stmt) {
if (!empty($params)) {
$stmt->bind_param($types, ...$params);
}
$stmt->execute();
$result = $stmt->get_result();
echo '<select name="contrato_id" id="contrato-select">';
echo '<option value="">Seleccione...</option>';
while ($row = $result->fetch_assoc()) {
// 注意:确保 $tipo_nombre 已正确定义(如从关联表获取),此处暂设为固定值或空字符串
$tipo_nombre = $row['tipo_nombre'] ?? '';
echo sprintf(
'<option value="%d">%s - %s %s / %s</option>',
$row['id'],
$row['id_contrato'],
$tipo_nombre,
$row['no_ctto'] ?? '',
$row['anno'] ?? ''
);
}
echo '</select>';
$stmt->close();
}
?>⚠️ 关键注意事项
- 字段名校验:务必确认 id_contrato 等字段真实存在且包含完整标题文本(如示例中的 "FRAMEWORK CONTRACT TO CONTRACT 19/ 2023"),否则 LIKE 将无法匹配。
- 大小写敏感性:MySQL 默认不区分大小写,但若使用 utf8mb4_bin 排序规则,则需统一大小写处理(建议在查询中使用 LOWER() + LOWER(?) 匹配)。
- 性能优化:对高频搜索字段(如 id_contrato)添加全文索引(FULLTEXT)或前缀索引(如 INDEX idx_title (id_contrato(100))),避免全表扫描。
- 用户体验增强:可结合 AJAX 实现无刷新筛选,或在前端添加搜索输入框实时调用后端 API 返回
? 总结
硬编码 WHERE ... LIKE '%xxx%' AND ... 虽能快速验证逻辑,但不可用于生产环境。始终优先采用预处理语句 + 参数绑定,既保障安全性,又提升代码可维护性与复用性。将查询逻辑封装为独立函数(如 getFilteredContracts($keywords)),更利于后续扩展多条件排序、分页或权限过滤。











