代码之家  ›  专栏  ›  技术社区  ›  user2173353

PHP-参数#3($修饰符)的类型必须是可调用的,给定字符串

  •  0
  • user2173353  · 技术社区  · 9 月前

    我试图将可调用/闭包存储为类字段/属性。

    我最初的尝试是这样的:

    class MyClass
    {
        protected callable $modifier;
    
        public function __construct(callable $modifier) {
            $this->modifier = $modifier;
        }
    }
    
    class SomeOtherClass
    {
        public static function func()
        {
            return ['a' => 'b'];
        }
    }
    
    $test = new MyClass('SomeOtherClass::func');
    

    这返回了一个错误:

    $修饰符不能具有可调用类型

    然后,在阅读之后 this 在网上,我尝试过但没有成功:

    class MyClass
    {
        protected Closure $modifier;
    
        public function __construct(callable $modifier) {
            $this->modifier = Closure::fromCallable($modifier);
        }
    }
    
    class SomeOtherClass
    {
        public static function func()
        {
            return ['a' => 'b'];
        }
    }
    
    $test = new MyClass('SomeOtherClass::func');
    

    最后一个返回此错误:

    参数#1($修饰符)的类型必须为callable,给定字符串

    然后我尝试了这个:

    class MyClass
    {
        protected Closure $modifier;
    
        public function __construct(callable $modifier) {
            $this->modifier = Closure::fromCallable($modifier);
        }
    }
    
    class SomeOtherClass
    {
        public static function func()
        {
            return ['a' => 'b'];
        }
    }
    
    $test = new MyClass(['SomeOtherClass', 'func']); // <----- changed string to an array
    

    返回以下错误:

    参数#1($modifier)的类型必须是callable,给定数组

    这在PHP中可以实现吗?

    1 回复  |  直到 9 月前
        1
  •  2
  •   ADyson    9 月前

    假设您使用的是PHP 8.1或更高版本(在撰写本文时是 only supported versions 无论如何,PHP),然后您可以使用 first-class callable 语法,如8.1中介绍的。

    为此,您可以使用函数的名称,然后 (...) 作为传递的论点。

    因此,在您的情况下,您可以这样做:

    class MyClass
    {
        protected Closure $modifier;
    
        public function __construct(callable $modifier) {
            $this->modifier = Closure::fromCallable($modifier);
        }
        
        public function runClosure()
        {
            var_dump(($this->modifier)());
        }
    }
    
    class SomeOtherClass
    {
        public static function func()
        {
            return ['a' => 'b'];
        }
    }
    
    $test = new MyClass(SomeOtherClass::func(...));
    $test->runClosure();
    

    现场演示: https://3v4l.org/nMmvq


    注意:上面的代码假设您想使用 func() 作为静态方法(如示例代码中所定义)。如果有人正在阅读并想用实例方法做类似的事情,你需要做一个小的调整,如下所示:

    class MyClass
    {
        protected Closure $modifier;
    
        public function __construct(callable $modifier) {
            $this->modifier = Closure::fromCallable($modifier);
        }
    
        public function runClosure()
        {
            var_dump(($this->modifier)());
        }
    }
    
    class SomeOtherClass
    {
        public function func()
        {
            return ['a' => 'b'];
        }
    }
    
    $soc = new SomeOtherClass();
    $test = new MyClass($soc->func(...));
    $test->runClosure();
    

    现场演示: https://3v4l.org/iEAiM

        2
  •  2
  •   Michal Hynčica    9 月前

    只是为了完整。OP代码中的问题很可能是由命名空间引起的。

    您必须在array/string callable中使用完全限定名。所以,你必须使用 [SomeOtherClass::class, 'func'] ['\MyNamespace\SomeOtherClass', 'func'] .

    观看现场演示: https://3v4l.org/pnWYC