Laravel简化框架Model类update函数适配数组批量更新改造求助
改造Model的update方法实现多字段批量更新
问题背景
现有Model类的update方法仅支持单字段更新,尝试传入数组实现多字段批量更新时,出现两个错误:
Array to string conversion:数组被直接拼接进SQL语句导致类型转换错误ArgumentCountError: Too few arguments to function Connection::safeQuery():调用该方法时传入的参数数量不足
原有代码
Model类update方法
public static function update($column, $value, $where){ $request = 'UPDATE '.self::_getTable().' SET '.$column.' = ? WHERE '.$where; return Connection::safeQuery($request, [$value]); }
控制器调用代码
$siteId = $website->getId(); $createTest = [ 'nom'=>$nom, 'url'=>$url, 'prix'=>$prix, 'casino'=>$casino, 'cbd'=>$cbd, 'google_news'=>$google_news, 'categorie_1'=>$categorie_1, 'categorie_2'=>$categorie_2, 'categorie_3'=>$categorie_3, 'TTF'=>$ttf, 'TF'=>$tf, 'CF'=>$cf, 'Backlinks'=>$refDomains, ]; Website::update($createTest, $createTest, $siteId);
报错原因
- 数组转字符串错误:原方法将
$column视为字符串直接拼接进SQL,传入数组时PHP自动尝试将数组转为字符串,触发警告。 - 参数不足错误:
Connection::safeQuery要求至少3个参数,但原代码仅传入了SQL语句和参数数组2个参数。
改造方案
修改update方法,使其支持数组类型的字段批量更新,同时兼容原有单字段更新逻辑,并修复safeQuery的参数问题:
public static function update($fields, $whereOrValue, $where = null){ $setPart = ''; $params = []; // 处理多字段批量更新:$fields是键值对数组 if(is_array($fields)){ $setClauses = []; foreach($fields as $column => $value){ // 字段名加反引号避免关键字冲突 $setClauses[] = "`$column` = ?"; $params[] = $value; } $setPart = implode(', ', $setClauses); // 此时$whereOrValue就是where条件 $finalWhere = $whereOrValue; } else { // 兼容原有单字段更新逻辑 $setPart = "`$fields` = ?"; $params[] = $whereOrValue; $finalWhere = $where; } $request = 'UPDATE '.self::_getTable().' SET '.$setPart.' WHERE '.$finalWhere; // 根据safeQuery要求传入至少3个参数,此处假设第三个参数为结果获取模式(需根据实际Connection类调整) return Connection::safeQuery($request, $params, PDO::FETCH_ASSOC); }
方案说明
- 参数兼容:通过判断
$fields是否为数组,同时支持多字段数组更新和原有单字段更新调用 - SQL安全:所有字段值使用参数化占位符,避免SQL注入;字段名添加反引号防止与SQL关键字冲突
- 参数修复:补充
safeQuery的第三个参数,需根据Connection类中该方法的实际定义调整(例如如果第三个参数是是否返回受影响行数,可传入对应值)
正确调用示例
多字段批量更新
$siteId = $website->getId(); $updateData = [ 'nom'=>$nom, 'url'=>$url, 'prix'=>$prix, 'casino'=>$casino, 'cbd'=>$cbd, 'google_news'=>$google_news, 'categorie_1'=>$categorie_1, 'categorie_2'=>$categorie_2, 'categorie_3'=>$categorie_3, 'TTF'=>$ttf, 'TF'=>$tf, 'CF'=>$cf, 'Backlinks'=>$refDomains, ]; // 直接传入字段数组和where条件 Website::update($updateData, 'id = '.$siteId);
单字段更新(兼容原有调用)
// 原有调用方式依然有效 Website::update('nom', '新名称', 'id = 123');
额外优化建议
为进一步提升安全性,可将where条件也改为参数化,避免直接拼接字符串带来的SQL注入风险:
public static function update($fields, $whereClause, $whereParams = []){ $setPart = ''; $params = []; if(is_array($fields)){ $setClauses = []; foreach($fields as $column => $value){ $setClauses[] = "`$column` = ?"; $params[] = $value; } $setPart = implode(', ', $setClauses); } else { $setPart = "`$fields` = ?"; $params[] = $whereClause; $whereClause = $whereParams; $whereParams = []; } // 合并where参数 $params = array_merge($params, $whereParams); $request = 'UPDATE '.self::_getTable().' SET '.$setPart.' WHERE '.$whereClause; return Connection::safeQuery($request, $params, PDO::FETCH_ASSOC); }
调用示例:
Website::update($updateData, 'id = ?', [$siteId]);
内容的提问来源于stack exchange,提问作者Undercover
相关产品推荐
相关产品推荐

