CodeIgniter 驱动程序:__call() 方法

CodeIgniter Drivers : __call() method

我在 Whosebug 上搜索了很长时间以寻找我的问题的答案,但我没有找到答案,这里没有,其他地方也没有。

无论如何,我尝试了很多次使用 CodeIgniter 的驱动程序,但我经常因为 __call 方法而放弃。让我用一个例子来解释。

假设我有一个名为 App 的驱动程序(当然是扩展 CI_Driver_Library)

class App extends CI_Driver_Library
{
    public $CI;
    public $valid_drivers;

    public function __constructor()
    {
        $this->CI &= get_instance();
        $this->valid_drivers = ['users']; // An example.
    }
}

现在我有了这样的 users 驱动程序。

class App_users extends CI_Driver 
{
    private $CI;

    public function __construct()
    {
        $this->CI =& get_instance();
        $this->CI->load->model('users_model');
    }

    public function __call($method, $params = [])
    {
        if (method_exists($this, $method)
        {
            return call_user_func_array(array($this, $method), $params);
        }
        elseif (method_exists($this->CI->users_model, $method))
        {
            return call_user_func_array(array($this->CI->users_model, $method), $params);
        }
        else
        {
            throw new BadMethodCallException("No such method: {$method}");
        }
    }
}

我想在这个App_users__constructor中加载Users_model(可能但是parent::$CI 无法访问,但我成功了)。

我面临的问题是当使用__call方法调用这个驱动程序的方法时模型的方法。不幸的是,那个神奇的方法没有也从来没有对我有用。如果可能的话,我该怎么做呢?如果没有,是否有任何解决方法?

提前致谢。

首先你要知道第一个if条件

if (method_exists($this, $method)...

毫无意义,因为条件永远不会满足。 __call 在找不到 class 方法时神奇地触发。已经确定 method_exists($this, $method) 不是 TRUE。如果它是 TRUE,那么 __call() 就不会被触发。

删除第一个 if 块会导致此结果。

public function __call($method, $params = [])
{
    if (method_exists($this->CI->users_model, $method))
    {
        return call_user_func_array(array($this->CI->users_model, $method), $params);
    }
    else
    {
        throw new BadMethodCallException("No such method: {$method}");
    }
}

这应该有效。

如果没有,我不得不问,您希望触发的代码是什么 __call

编辑回复评论:

tell me please.. Is there a way a child can access to its sibling's methods?

我的第一反应是,如果您有这种需要,那么 "drivers" 可能不是要使用的模式。正如在 CI 中实现的那样,驱动程序是一种特殊类型的库,具有 parent class 和任意数量的潜在 child classes。 Child classes 可以访问 parent class,但不能访问他们的兄弟姐妹。

这种安排是有目的的,因为通常每个驱动程序都设计用于处理单一类型的设备或特定的软件服务。例如,在数据库的上下文中,每个驱动程序处理特定类型的数据库服务器(即 MySQL、SQLite)and/or 对服务器类型的扩展(即 mysql、mysql一世)。

CI 库 CI_Cache 有几个不同动态缓存系统的驱动程序。这些系统往往是相互排斥的。我怀疑同时尝试 运行 memcachedredis 会导致严重的头痛。

这几个例子不知道你是不是选错软件模式了。至少,在 separation of concerns.

方面,兄弟姐妹需要交流往往会指向错误的想法。

综上所述,我认为解决方案是在 parent 中放置一个方法来处理琐事。此方法将从一个兄弟调用到 parent,后者将调用另一个兄弟中的适当方法。注意:我没有测试过这个想法。 __call 或许可以解决这个问题,但在我看来,显式调用是一种更简洁的解决方案。

如果您还没有找到它们,这里有一些 CI 驱动程序教程可能会对您有所帮助。 Kevin Phillips and codebyjeff