解决使用IDE开发laravel项目无法智能提示eloquent的可调用方法的问题

1.官方推荐使用eloquent的方式

laravel官方文档关于eloquent的使用方式的介绍有两种,一种是静态调用,一种是实例化。但是这两种方式在使用IDE(phpstorm)开发时,都有点不便-IDE不提示可调用的方法。
官方静态调用示例
官方实例化调用示例

2.解决IDE不提示eloquent可调用的方法的问题

要解决这个问题很简单,只需要在使用这两种方式调用链式方法前调用另一个方法就可以了。

用于静态调用的方式

在静态调用其他链式方法前调用`query`方法,之后IDE就能提示其他可调用的链式方法了。
优化静态调用

用于实例化调用的方式

接收实例化Model后再调用`newQuery`方法的返回值,这样IDE就能提示可调用的链式方法了。
优化实例化调用

3.分析原因

现在解释一下为什么用官方文档方式IDE不会提示可调用的链式方法,而经过这样的调整,IDE又行了。

主要因为`\Illuminate\Database\Eloquent\Model`类中的两个魔术方法的作用:`__call`、`__callStatic`。

官方文档的调用方式最后都会由`__call`处理,所以我们只要理解`Model`类的`__call`方法具体做了什么就能理解为什么上面的解决方式有效了。

`Model`类中`__call`的具体代码
php 复制代码
/**
     * Handle dynamic method calls into the model.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters)
    {
        if (in_array($method, ['increment', 'decrement'])) {
            return $this->$method(...$parameters);
        }

        if ($resolver = (static::$relationResolvers[get_class($this)][$method] ?? null)) {
            return $resolver($this);
        }
       
        return $this->forwardCallTo($this->newQuery(), $method, $parameters);
    }
`forwardCallTo`的具体代码
php 复制代码
/**
     * Forward a method call to the given object.
     *
     * @param  mixed  $object
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    protected function forwardCallTo($object, $method, $parameters)
    {
        try {
            return $object->{$method}(...$parameters);
        } catch (Error|BadMethodCallException $e) {
            $pattern = '~^Call to undefined method (?P<class>[^:]+)::(?P<method>[^\(]+)\(\)$~';

            if (! preg_match($pattern, $e->getMessage(), $matches)) {
                throw $e;
            }

            if ($matches['class'] != get_class($object) ||
                $matches['method'] != $method) {
                throw $e;
            }

            static::throwBadMethodCallException($method);
        }
    }

可以发现关键代码`forwardCallTo `,结合`forwardCallTo`的方法参数可以发现,最终由`**this-\>newQuery()**\`创建的对象,调用链式的方法名。因此可以得出官方文档中的链式调用方法其实都是\`this->newQuery()`方法返回值可调用的方法。

到这里就可以了。如果我们能直接持有`newQuery()`的返回值,那么就能直接调用它的方法了,而不用再经过`__call`了。

很幸运`newQuery()`方法的修饰符是`public`。

刚好`Model`类有一个静态的`query()`方法,这个方法主要代码就是返回`newQuery()`的值,这也解决了静态调用的问题了。

静态`query()`方法的代码
php 复制代码
/**
     * Begin querying the model.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public static function query()
    {
        return (new static)->newQuery();
    }
相关推荐
CRMEB系统商城4 小时前
CRMEB多商户系统(Java)v2.3公测版发布
java·开发语言·人工智能·小程序·开源·php
修炼室5 小时前
外网环境原生直连校内服务器:基于内网穿透 + SSH 密钥认证的完整实践指南
服务器·ssh·php
BingoGo7 小时前
PHP 在领域驱动(DDD)设计中的核心实践
后端·php
2601_961194029 小时前
考研资料电子版|去哪找|网盘
java·c语言·c++·python·考研·php
嘶哈哈哈10 小时前
嘉立创 EDA 入门实操笔记:从原理图到 PCB 布线、差分对、覆铜与 DRC 检查
开发语言·笔记·php
爱装代码的小瓶子11 小时前
3. 设计buffer模块
linux·服务器·开发语言·c++·php
狗凯之家源码网12 小时前
APP 软件官网整站源码效果实测与价值解析
开源·php
m0_7381207212 小时前
渗透测试基础——PHP 序列化数据结构与反序列化机制详解
android·服务器·网络·数据结构·安全·php
AC赳赳老秦13 小时前
用 OpenClaw 制定技术学习计划:根据目标岗位自动生成学习路线、推荐学习资源
开发语言·c++·人工智能·python·mysql·php·openclaw
宁小法14 小时前
Redis evalsha 可能返回的错误类型
redis·php·lua报错