如何通过数组键调用PHP方法?产品入库代码异常排查与修复
问题背景
- 代码功能:将特定类型产品添加至数据库,
config.php包含三类带专属属性getter/setter及insert()的产品类、一个负责显示/删除的类、一个带通用属性getter/setter的抽象类 - 异常现象:仅一种产品的所有属性能存入数据库,其他产品仅能存入sku、name、price三个核心属性;显示/删除功能正常,问题出在提供的代码中
- 限制条件:不能弃用getter/setter,不能用条件语句处理产品类型
问题代码
<?php session_start(); error_reporting(E_ALL); ini_set('display_errors', 1); require_once 'config.php'; // here are the classes function getClassname() { $prod = $_POST['type']; return new $prod(); } $methods = [ 'setSize' => $_POST['size'], 'setWeight' => $_POST['weight'], 'setHeight' => $_POST['height'], 'setWidth' => $_POST['width'], 'setLength' => $_POST['length'] ]; function insertData(array $func) { $product = getClassname(); $product->dbConnect(); $product->uniqueSku(); $product->setSku($_POST['sku']); $product->setName($_POST['name']); $product->setPrice($_POST['price']); foreach ($func as $m => $arg) { if(method_exists($product, $m)){ $reflect = new ReflectionMethod($_POST['type'], $m); $reflect->invoke($product, $arg); //$product->$m($arg); doesn't help } else { break; } } $product->insert(); } insertData($methods); //header('Location: ...');
问题根源
- 循环终止逻辑错误:遍历
$methods数组时,只要遇到当前产品类不存在的方法就直接break终止整个循环。比如某产品类只有setWeight方法,但数组中setSize排在前面,遍历到setSize发现不存在就直接跳出,后续的setWeight根本没机会执行,导致专属属性无法设置。 - 反射使用冗余:完全没必要用
ReflectionMethod,直接调用$product->$m($arg)即可,反射不仅没解决核心问题,还增加了代码复杂度。
修复方案
核心修复:调整循环逻辑
把循环里的break改成continue,碰到不存在的方法就跳过,继续遍历后续方法;同时去掉冗余的反射:
function insertData(array $func) { $product = getClassname(); $product->dbConnect(); $product->uniqueSku(); $product->setSku($_POST['sku']); $product->setName($_POST['name']); $product->setPrice($_POST['price']); foreach ($func as $m => $arg) { if(method_exists($product, $m)){ $product->$m($arg); // 直接调用方法,无需反射 } // 删除break,不存在的方法直接跳过,继续循环 } $product->insert(); }
可选优化:精简方法数组
只收集表单中存在有效值的方法,减少无效遍历:
$methods = []; // 只保留有提交值的属性对应的set方法 if(!empty($_POST['size'])) $methods['setSize'] = $_POST['size']; if(!empty($_POST['weight'])) $methods['setWeight'] = $_POST['weight']; if(!empty($_POST['height'])) $methods['setHeight'] = $_POST['height']; if(!empty($_POST['width'])) $methods['setWidth'] = $_POST['width']; if(!empty($_POST['length'])) $methods['setLength'] = $_POST['length'];
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

