PHP类型提示可调用函数
好的,我已经定义了这个类方法来接受回调,并且我已经根据类型提示文档将其类型提示为可调用PHP类型提示可调用函数,php,Php,好的,我已经定义了这个类方法来接受回调,并且我已经根据类型提示文档将其类型提示为可调用 protected function AddTransformData(array $definition,array $where,callable $callback){ $this->transforms[]=[$definition,$where,$callback]; } 下面是一个我可以调用此函数的示例。使用数组语法将方法和对象作为回调传递 public function __co
protected function AddTransformData(array $definition,array $where,callable $callback){
$this->transforms[]=[$definition,$where,$callback];
}
下面是一个我可以调用此函数的示例。使用数组语法将方法和对象作为回调传递
public function __construct(PostalZoneMapping $pzm){
$this->pzm=$pzm;
$this->AddTransformData(Countries::region,['filter'],[$this,'TransformId']);
$this->AddTransformData(PostalZones::id,['filter'],[$this,'TransformId']);
$this->ReceiveData();
}
这会抛出一个错误,如下图所示,抱怨参数3不可调用,而是一个数组。从逻辑上讲,我想这是有道理的,因为它是数组,但它是一个可调用函数的数组——当然它必须检测到它是一个回调
这是PHP的怪癖还是我做错了什么
如果您的PHP版本低于7.4,则应改为:
$callable = fn() => $this->$method();
这样做:
$callable = function() use ($method) { $this->$method() };
您还可以收到一个参数:
$callable = fn($param) => $this->$method($param);
或
看起来
TransformId
不是该类上的方法。可能是打字错误,可能是属性,但不是方法
为了使数组成为有效回调,它必须是:实例化对象的方法作为数组传递,数组包含索引0处的对象和索引1处的方法名称。
这项工作:
class A {
function __construct() {
$this->asd2([$this, 'asd']);
}
private function asd() {}
public function asd2(callable $c) {}
}
$a = new A();
这并不是:
class A {
function __construct() {
$this->asd2([$this, 'somethingElse']);
}
private function asd() {}
public function asd2(callable $c) {}
}
Fatal error: Uncaught TypeError: Argument 1 passed to A::asd2() must be callable, array given, called in
如果我错了-粘贴整个类代码,包括
TransformId
方法。我创建了一些测试代码来重现错误,注意到我将回调声明为私有!此代码将不起作用,但如果将TransformId方法更改为protected或public,则此代码将起作用
<?php
abstract class CommonDataInterface{
private $transforms=[];
/**
* Adds a callback that transform data
*
* @param array $definition Definition, where, if matches, callback is called.
* @param array $where Where to transform data, array values one or more of 'set','insert' or'filter'
* @param callable $callback Function that takes value as parameter, and returns transformed value.
* @return void
*/
protected function AddTransformData(array $definition,array $where,callable $callback){
$this->transforms[]=[$definition,$where,$callback];
}
}
class Api_PostalZoneMapping extends CommonDataInterface{
private $pzm;
public function __construct($pzm){
$this->pzm=$pzm;
$this->AddTransformData(['blah'],['filter'],[$this,'TransformId']);
$this->AddTransformData(['blah2'],['filter'],[$this,'TransformId']);
//$this->ReceiveData();
}
private function TransformId($data){
if($data==-1)
return null;
return $data;
}
}
$p=new Api_PostalZoneMapping('not relevant for test');
是什么导致了异常?我试图创造一些类似的东西,但无法重现结果。你能创建一组简单的代码来重现问题中的这个错误吗?这不是一个简单的IDE错误吗?这是实际运行代码时遇到的真正异常吗?这是什么IDE?可能它不理解可调用数组表示法。哪种可视性有“TransformId”方法?它是私有的还是受保护的?@IvanShumakov根据文档:允许从类中访问受保护的和私有的方法代码>-所以即使它在这个类的上下文中是私有的,它也应该是有效的可调用的?好的,事实证明它不是在单个类的上下文中,而是在父-子上下文中。然后必须至少对其进行保护,以便可以在父级中调用它。
class A {
function __construct() {
$this->asd2([$this, 'somethingElse']);
}
private function asd() {}
public function asd2(callable $c) {}
}
Fatal error: Uncaught TypeError: Argument 1 passed to A::asd2() must be callable, array given, called in
<?php
abstract class CommonDataInterface{
private $transforms=[];
/**
* Adds a callback that transform data
*
* @param array $definition Definition, where, if matches, callback is called.
* @param array $where Where to transform data, array values one or more of 'set','insert' or'filter'
* @param callable $callback Function that takes value as parameter, and returns transformed value.
* @return void
*/
protected function AddTransformData(array $definition,array $where,callable $callback){
$this->transforms[]=[$definition,$where,$callback];
}
}
class Api_PostalZoneMapping extends CommonDataInterface{
private $pzm;
public function __construct($pzm){
$this->pzm=$pzm;
$this->AddTransformData(['blah'],['filter'],[$this,'TransformId']);
$this->AddTransformData(['blah2'],['filter'],[$this,'TransformId']);
//$this->ReceiveData();
}
private function TransformId($data){
if($data==-1)
return null;
return $data;
}
}
$p=new Api_PostalZoneMapping('not relevant for test');