CodeIgniter驱动程序:__ call()方法

时间:2017-10-25 23:11:23

标签: php codeigniter libraries drivers magic-methods

我在 Stackoverflow 上搜索了很多关于我的问题的答案,但我找不到答案,而不是其他地方。

无论如何,我多次尝试使用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.
    }
}

现在我有用户驱动程序。

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 无法访问但我管理过。)< / p>

我遇到的问题是使用 __ call 方法来调用此驱动程序的方法 OR 模型的方法。不幸的是,这种神奇的方法没有,也从来没有为我工作过。如果可能,我怎么能这样做呢?如果没有,是否有任何解决方法?

提前致谢。

1 个答案:

答案 0 :(得分:1)

首先,您应该知道第一个if条件

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

毫无意义,因为永远不会满足条件。无法找到类方法时,会神奇地触发__call。已经确定method_exists($this, $method)不是真的。如果为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的代码是什么?

编辑回复评论:

  请告诉我..孩子有没有办法使用兄弟姐妹的方法?

我的第一反应就是说,如果你有这种需要,那么&#34; drivers&#34;可能不是使用的模式。在CI中实现,驱动程序是一种特殊类型的库,它具有父类和任意数量的潜在子类。子类可以访问父类,但不能访问其兄弟。

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

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

这些例子就是我想知道你是否选择了错误的软件模式的原因。至少,兄弟姐妹沟通的必要性往往指向separation of concerns时的错误思考。

所有这一切,我认为解决方案是在处理杂务的父级中放置一个方法。这个方法将从一个兄弟调用到父节点,它将在另一个兄弟节点中调用适当的方法。注意:我没有测试过这个想法。 __call可能能够解决这个问题,但在我看来,显式调用是一个更清晰的解决方案。

如果您还没有找到它们,请参阅一些CI驱动程序教程,您可能会发现它们很有帮助。 Kevin Phillipscodebyjeff