【问题标题】:PHP __call method for REST HTTP VerbsREST HTTP 动词的 PHP __call 方法
【发布时间】:2015-06-24 17:39:45
【问题描述】:

我正在编写一个 REST 包装类,如下所示:

class RestApi
{
      public function __call($method, $resource, $data = []){
           return $this->call($method, $resource, $data);
      }

      public function call($http_verb, $resource, $data = []){}
}

但是当我尝试运行以下...

$ra = new RestApi();
$ra->post('api/book/index');

它会引发以下错误...

RestApi::__call() 必须正好有 2 个参数

我想摆脱重复代码,所以我决定对所有四个 http 动词使用 __call 魔术方法。请提出一种方法。谢谢。

【问题讨论】:

    标签: php oop php-5.3


    【解决方案1】:

    就像错误消息所暗示的那样,__call 魔术方法只接受 2 个参数:请求的方法的名称,以及传递的参数的数组。所有这些信息都可以在here找到。

    考虑到这一点,也许修改你的代码看起来更像这样:

    public function __call($method, $arguments) {
        return $this->call($method, $arguments[0], $arguments[1]);
    }
    

    假设您使用 CURL 实现实际的 API 请求(这可能是一个非常大的假设),您可以在您的 call() 方法中执行类似的操作:

    switch (strtoupper($http_verb)) {
        case 'GET':
            // Nothing special happens here, this is CURL's default behavior
            break;
        case 'POST':
            curl_setopt($ch, CURLOPT_POST, true);
            break;
        case 'PUT':
            curl_setopt($ch, CURLOPT_PUT, true);
            break;
    
        // Etc...
    }
    

    这纯粹是一个示例,用于演示您可以使用 __call() 魔术方法执行的条件逻辑。有许多 libraries and frameworks 创建 REST 包装器,就像您正在尝试做的那样。我建议将其中的一个视为一种学习体验,或者调查像 Guzzle 这样的库。

    注意:当然,如果有一个可选的第二个参数(就像你上面所说的那样),在盲目地传递它们之前做一些检查以查看 $arguments[1] 等是否存在是明智的。否则你会得到类似PHP Notice: Undefined offset: 1的东西。

    更新

    关于我的最后一段,@JayTaph 有一个很好的建议。一种简洁的方法(一行,无需额外检查)是使用以下内容:

    public function __call($method, $arguments) {
        return this->call($method, array_shift($arguments), $arguments);
    }
    

    如果只传递一个参数,在第一个元素被array_shift() 移出后,$arguments 将是一个空数组,这避免了我上面提到的PHP Notice: Undefined offset 错误。

    【讨论】:

    • 为什么不$this->call($method, array_shift($arguments), $arguments);
    • 如果我使用call_user_func_array()会怎样
    • @JayTaph 对我来说似乎不错,假设方法签名保持不变。我更新了我的答案。
    • @seoppc 看起来你在__call() 的正确轨道上,所以你可能不需要切换到call_user_func_array()。您是否正在寻找关于在实际 call() 函数中放入什么内容的建议?如果是这样,我可以更新我的答案。
    • @seoppc 请查看我的更新答案。这是我在不为您编写所有代码的情况下能做的最好的事情。我希望这会有所帮助。
    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多