【问题标题】:CodeIgniter Drivers : __call() methodCodeIgniter 驱动程序:__call() 方法
【发布时间】:2017-10-25 23:11:23
【问题描述】:

我在 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.
    }
}

现在我有了像这样的 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 方法来调用此驱动程序的方法 OR 模型的方法时。不幸的是,这种神奇的方法对我没有用,也从来没有用过。如果可能的话,我该怎么做?如果没有,是否有任何解决方法?

提前致谢。

【问题讨论】:

  • 请向我们展示您对__call的实现。
  • @DFriend 我编辑了代码并添加了我的实现(请不要介意拼写错误)

标签: php codeigniter libraries drivers magic-methods


【解决方案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 的代码是什么?

编辑回复评论:

请告诉我.. 有没有办法让孩子访问其兄弟姐妹的方法?

我的第一反应是,如果您有这种需求,那么“驱动程序”可能不是要使用的模式。正如在 CI 中实现的那样,驱动程序是一种特殊类型的库,它具有父类和任意数量的潜在子类。子类可以访问父类,但不能访问它们的兄弟。

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

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

这些示例是我想知道您是否没有选择错误的软件模式的原因。至少,兄弟姐妹交流的需要往往指向separation of concerns的错误想法。

话虽如此,我认为解决方案是在处理家务的父级中放置一个方法。此方法将从一个兄弟姐妹调用到父级,该父级将在另一个兄弟姐妹中调用适当的方法。注意:我没有测试过这个想法。 __call 可能能够处理这个问题,但在我看来,显式调用是一个更干净的解决方案。

如果您还没有在此处找到它们,这里有几个 CI 驱动程序教程可能会对您有所帮助。 Kevin Phillipscodebyjeff

【讨论】:

  • :'( .. 对于我所做的每个项目,我都因此放弃了使用 CodeIgniter 驱动程序,而你的到来让我的生活更快乐 :) ... 这就是我想要的更多超过两 (2) 年!感谢您和 Stackoverflow ,一天之内就解决了
  • 请告诉我@DFriend .. 有没有办法让孩子访问其兄弟姐妹的方法?
  • 我在回答中添加了一些内容以解决上述评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 2014-07-23
  • 2012-01-01
相关资源
最近更新 更多