【问题标题】:My mixin class is causing my classes to become static - PHP我的 mixin 类导致我的类变成静态的 - PHP
【发布时间】:2013-10-08 20:54:21
【问题描述】:

这是我的 mixin 类:

class AisisCore_Loader_Mixins {

    private $_classes;

    private $_class_objects = array();

    private $_methods = array();

    public function __construct(){
        $this->init();
    }

    public function init(){}

    public function setup($class){
        if(!is_array($class)){
            throw new AisisCore_Loader_LoaderException('Object passed in must be of type $class_name=>$params.');
        }

        $this->_classes = $class;
        $this->get_class_objects();
        $this->get_methods();    
    }

    public function get_class_objects(){
        foreach($this->_classes as $class_name=>$params){
            $object = new ReflectionClass($class_name);
            $object_name = get_class($object);
            $this->_class_objects[$object->name] = $object->newInstanceArgs($params);
        }
    }

    public function get_methods(){ 
        foreach($this->_class_objects as $class_object_name => $class_object){
            $this->_methods[$class_object_name] = get_class_methods($class_object);
        }

        return $this->_methods;
    }

    public function __call($name, $param = null){
        foreach($this->_methods as $class_name=>$methods){
            foreach($methods as $method){
                if($name === $method){
                    return $this->isParam($class_name, $method, $param);
                }
            }
        }

        throw new AisisCore_Loader_LoaderException("Method: " .$name. 
                            " does not exist or it's access is not public");
    }

    private function isParam($class_name, $method, $param){
        if($param != null){
            call_user_func(array($class_name, $method), $param);
        }else{
            call_user_func(array($class_name, $method));
        }        
    }
}

很简单的东西,加载一组类,允许你调用它们的函数等等,但是我们有一个新问题。似乎传递给它的类被实例化为静态的,因此它们的方法不能使用$this->,他们求助于使用self::,这是错误的。

让我们看一个例子来说明这一切是如何工作的:

class BaseBridge extends AisisCore_Loader_Mixins{

    public function __construct(){ 
        parent::construct();

        $this->setup(array('ClassB' => array()));
    }
}

让我们定义ClassB

class ClassB{

    public function __construct(){}

    public function some_method(){
        $this->_some_private_method();
    }

    private function _some_private_method(){}
}

相当基本的东西,所以让我们把它全部连接到ClassA

class ClassA extends BaseBridge{

    public function __construct(){ 
        parent::__construct(); 
        $this->some_method();
    }
} 

快速回顾:我们有一个核心类ClassA,它扩展了BaseBridge,这是我们在ClassA 扩展的一个或多个(旨在与更多)类之间的桥梁类从。在这种情况下,为简单起见,仅从 ClassB 扩展。

出了什么问题? 看,ClassB 的表现如何:$this->_some_private_method(); 是的,这将是巨大而灾难性的失败。 为什么? 因为我收到错误:Using $this when not in object context,这让我很困惑,所以我将其更改为:self::$_some_private_method();,它就像一个魅力。

为什么?以及我必须更改或修复什么才能使$this 可以在通过mixin 类实例化的类中使用?

【问题讨论】:

  • 许多语言不支持多重继承是有原因的,你真的应该停止试图强迫 PHP 做一些它不应该做的事情......
  • 被标记为不具建设性。 @MarcB 事情可能并不容易,但我设法做到了这一点。
  • 我的第一个建议是完全避免 mixins/traits。 通常如果答案是多重继承或水平代码重用,那么你就问错问题了。我的第二个建议是,如果你绝对必须这样做......停止尝试自己实现 mixins。只需升级到 PHP5.4 并使用 traits 作为语言的一部分。
  • 一:WordPress用户使用5.2.x,没办法。二:实现mixins并不难,我只是有一个小问题。和三个我很想去 5.5.x 但又是 WordPress。 @rdlowrey
  • 这个问题突出了 Wordpress 及其插件生态系统的核心问题之一:兼容性混乱。大多数(任何我处理过的)托管服务提供商都支持 5.4;快到 2013 年底了,你也应该这样。不要硬塞一个已经存在 19 个月的语言功能。升级。

标签: php object this mixins self


【解决方案1】:

因此,通过一些细微的修改,我设法完成了这项工作。我怎么不相信具有多个参数的函数会起作用 - 感谢反馈。

class AisisCore_Loader_Mixins {

    private $_classes;

    private $_class_objects = array();

    private $_methods = array();

    public function __construct(){
        $this->init();
    }

    public function init(){}

    public function setup($class){
        if(!is_array($class)){
            throw new AisisCore_Loader_LoaderException('Object passed in must be of type $class_name=>$params.');
        }

        $this->_classes = $class;
        $this->get_class_objects();
        $this->get_methods();    
    }

    public function get_class_objects(){
        foreach($this->_classes as $class_name=>$params){
            $object = new ReflectionClass($class_name);
            $this->_class_objects[$object->name] = $object->newInstanceArgs($params);
        }
    }

    public function get_methods(){ 
        foreach($this->_class_objects as $class_object_name => $class_object){
            $this->_methods[$class_object_name] = get_class_methods($class_object);
        }

        return $this->_methods;
    }

    public function __call($name, $param = null){
        foreach($this->_methods as $class_name=>$methods){
            foreach($methods as $method){
                if($name === $method){
                    return $this->_is_param($class_name, $method, $param);
                }
            }
        }

        throw new AisisCore_Loader_LoaderException("Method: " .$name. 
                            " does not exist or it's access is not public");
    }

    private function _is_param($class_name, $method, $param){
        if($param != null){
            $this->_param_is_array($class_name, $method, $param);
        }else{
            call_user_func(array($this->_class_objects[$class_name], $method));
        }        
    }

    private function _param_is_array($class_name, $method, $param){
        if(is_array($param)){
            call_user_func_array(array($this->_class_objects[$class_name], $method), $param);
        }else{
          call_user_func(array($this->_class_objects[$class_name], $method, $param));  
        }        
    }
}

现在此类注册的类中的函数可以使用$this->

问题是我不确定多个基于参数的函数是否真的有效。

【讨论】:

    猜你喜欢
    • 2018-03-12
    • 1970-01-01
    • 2011-03-20
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    相关资源
    最近更新 更多