我想出了以下代码来在我的 PHP 类中通过 AJAX 调用方法:
PHP:
class Ajax extends Controller {
private $class;
private $method;
private $params;
function __construct()
{
$this->params = $_POST; // Call params
$call = explode('->', $this->params['call']);
$this->class = new $call[0]; // e.g. controller->method
$this->method = $call[1];
array_shift($this->params);
$this->parse();
}
public function index()
{
//Dummy
}
public function parse()
{
$r = '';
$r = call_user_func_array(array($this->class, $this->method), $this->params);
echo $r;
}
}
客户:
function creditCheck2(id)
{
$.post(ROOT + 'Ajax', {call: 'Record->creditState', id: id, enquiryid: enquiryId}, function(data) {
alert(data)
}, 'json')
}
它似乎工作得很好,但它是否安全并且可以做得更好吗?
仅供引用,我添加了我的代码以及答案建议的更改:
class Call extends Controller {
private $class;
private $method;
private $params;
private $authClasses = array(
'Gallery'
);
function __construct()
{
$this->params = $_POST; // Call params
$call = explode('->', $this->params['call']);
if(!in_array($call[0], $this->authClasses))
{
die();
}
$this->class = new $call[0]; // e.g. controller->method
$this->method = $call[1];
unset($this->params['call']);
$this->parse();
}
public function parse()
{
$r = '';
$param = array();
// Params in any order...
$mRef = new ReflectionMethod($this->class, $this->method);
foreach($mRef->getParameters() as $p) {
$param[$p->name] = $this->params[$p->name];
}
$this->params = $param;
if($r = @call_user_func_array(array($this->class, $this->method), $this->params))
{
echo $r;
}
else {
}
}
}
最佳答案
小问题
array_shift($this->params)
不必要地假设 params 数组中的第一项将始终是 call
可能会更好。那是不正确的,它不同意您之前所做的直接访问 $this->params['call']
。 array_shift
应该简单地替换为 unset($this->params['call'])
。
更大的问题
还有一个问题是,params 数组中值的顺序必须与您尝试调用的方法签名中的参数顺序相匹配。我认为不能保证顺序与 AJAX 请求中参数的顺序相同,所以这是一个理论上的问题。
非常大的问题
更重要的是,这种处理方式强制 AJAX 代码的作者匹配您尝试调用的方法签名中的参数顺序。 这引入了可怕的耦合程度,是一个主要问题。更糟糕的是,错误地更改参数的顺序不会很明显。考虑:
public function bankTransfer($fromAccount, $toAccount, $amount);
$.post(ROOT + 'Ajax', {
call: 'Bank->bankTransfer',
from: "sender",
to: "recipient",
amount: 42
}, function(data) { ... });
这行得通。但是如果你这样做
$.post(ROOT + 'Ajax', {
call: 'Bank->bankTransfer',
to: "recipient", // swapped the order of
from: "sender", // these two lines
amount: 42
}, function(data) { ... });
您将得到与预期相反的结果。我相信很明显这非常糟糕。
要解决此问题,您必须使用反射将 $this->params
中的数组键与被调用方法的参数的正式名称相匹配。
安全
最后,此代码是不安全的,因为任何人都可以发出请求,指示您的代码使用适当的参数调用任何类的任何方法——甚至是不应从 Web 环境访问的方法。
这是另一个严重的问题,除非您在调度逻辑中引入某种类型的过滤,否则无法真正解决。
关于php - 使用 AJAX 调用 PHP 类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18506709/