声明和调用名称中带有句点的PHP对象函数

声明和调用名称中带有句点的PHP对象函数,php,oop,Php,Oop,我正在使用一个返回不同值的API,我想动态地告诉我的类运行一个同名函数(这样我就不需要一个巨大的开关或if/else混乱) 如何声明对象方法song.pause 如何使用对象方法song.pause 这可能是一个错误,那么有更好的方法吗?我想到的另一种方法是总是调用str_replace('.',''.',$type)并设置不带句点的函数。想法 例如: <?php class MyClass { ... ... $type = "song.pause"; // Th

我正在使用一个返回不同值的API,我想动态地告诉我的类运行一个同名函数(这样我就不需要一个巨大的
开关
if/else
混乱)

  • 如何声明对象方法
    song.pause
  • 如何使用对象方法
    song.pause
  • 这可能是一个错误,那么有更好的方法吗?我想到的另一种方法是总是调用
    str_replace('.',''.',$type)
    并设置不带句点的函数。想法
  • 例如:

    <?php
    class MyClass {
        ...
        ...
        $type = "song.pause"; // This value is returned from another API I can't control
    
        if (property_exists('MyClass', $type)) {
            $success = $this->{$type}(); // ???
        } else {
            header("HTTP/1.1 400 Invalid type: $type);
            exit;
        }
    
    
        public function 'song.pause'() { // obviously incorrect :)
              ???
        }
    

    不幸的是,您通常要求的是不受支持。从:

    函数名遵循与PHP中其他标签相同的规则。有效的 函数名以字母或下划线开头,后跟任意 字母、数字或下划线的数量。作为正则表达式, 可以这样表达:[a-zA-Z\ux7F-\xff][a-zA-Z0-9\ux7F-\xff]*

    这也适用于类方法

    在本次演练中,您可以按照自己建议的方式进行:

    $type = 'song.pause';
    $type = str_replace('.', '_', $type);
    $this->{$type}(); // will call song_pause()
    
    或使用:

    
    
    显示:

    song.pause           // < the method
    Array                // < arguments
    (
        [0] => 1
        [1] => 2
        [2] => 3
    )
    
    song.pause/<
    数组/<参数
    (
    [0] => 1
    [1] => 2
    [2] => 3
    )
    

    然而,我完全同意“长”且真正透明的方式。

    @HAL9000是正确的:您想要的东西不受支持。一个潜在的解决办法是:

    定义处理程序:

    $typeHandlers = array();
    $typeHandlers['song.pause'] = function () {
        echo 'Pause!'; // or whatever...
    };
    
    调用相应的处理程序:

    $typeHandlers[$type]();
    

    返回<代码>歌曲。暂停<代码>,概念上<代码>歌曲<代码>应该是类名,<代码>暂停<代码>应该是方法,考虑这种可能性:

    class MyClass {
        protected $classes = array();
    
        function processResponse($response) {
            // $response example is "song.pause"
            list($class, $method) = explode('.', $response);
            if(!class_exists($class)) {
                // Class doesn't exist
                die("Class name {$class} doesn't exist! Exiting...");
            }
    
            // Instantiate class
            $this->classes[$class] = new $class();
    
            if(!method_exists($this->classes[$class], $method)) {
                // Method doesn't exist within specified class
                die("Method name {$method} doesn't exist within {$class}. Exiting...");
            }
    
            // Call method
            $result = $this->classes[$class]->{$method}();
    
            return $result;
        }
    }
    
    您的逻辑实现如下所示:

    class song {
        public function pause() {
            return 'foobar';
        }
    }
    

    好吧,我也这么认为。谢谢看起来我必须要有创意。+1但是在
    $this->classes
    中保留对象的副本有什么意义(特别是因为它被覆盖了)?纯粹是为了不需要为每个子类名定义属性-而是将它们保留在数组中。如果要为每个可能的子级定义它,那么它和
    $this->{$class}
    之间没有区别。
    class song {
        public function pause() {
            return 'foobar';
        }
    }