【问题标题】:PhpStorm: Is there a way to enforce a type on the return statement using an inline PHPDoc annotation?PhpStorm:有没有办法使用内联 PHPDoc 注释在 return 语句上强制类型?
【发布时间】:2021-06-03 19:41:36
【问题描述】:

考虑以下代码:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Car extends Model
{
    public static function getTheFirstCar(string $color): ?self
    {
        /** @var ?self */ // <-- Doesn't apply! Is there any alternative?
        return (new self())->newQuery()->firstWhere('color', '=', $color);
    }
}

代码运行正常;尽管如此,PhpStorm 还是抱怨:

返回值应为'Car|null',
'\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model' 返回

将表达式的结果分配给带注释的变量可以解决警告,但会引入 “冗余” 变量!

/** @var ?self $redundant */
$redundant = (new self())->newQuery()->firstWhere('color', '=', $color);
return $redundant;

那么,PhpStorm 中是否有一种方法可以将 return 语句表达式的值显式地强制为 Car|null,而无需引入冗余变量或指定所有预期的返回类型?

【问题讨论】:

  • 可以在方法上方加上@return ?static|Model。问题本身看起来像this bug
  • @Dmitrii 我不想通过添加与上下文无关的Model 类型来引入歧义(该方法只返回Carnull
  • 你用的是什么phpstorm版本?
  • 我使用的是 2020.3.2,它工作正常。也许你应该更新phpstorm。
  • @Dmitry 我也使用 PhpStorm v2020.3.2 (Build #PS-203.7148.74);请详细说明“什么”适合您? (是返回语句之前的/** @var ?self */(这符合我的需要);或者,添加了与上下文无关的Model 类型——我已经解释过了!)

标签: php laravel phpstorm phpdoc type-annotation


【解决方案1】:

您可以通过在您的声明前添加 @noinspection PhpIncompatibleReturnTypeInspection 注释来取消此警告。
我个人不会这样做,但这是您关于如何“强制执行”的问题的唯一答案" 返回类型并抑制警告 afaik。

    /** @noinspection PhpIncompatibleReturnTypeInspection */
    return (new self())->newQuery()->where('color', '=', $color)->first();

如果您决定尊重警告,那么这可能是它的原因和解决方案: newQuery() 将在模型表上创建一个新查询(很可能是:cars)而不设置适当的模型(Car)。
在内部,您现在在 cars 上运行一个裸查询。因此,您将收到适当的记录,但不是Car 的实例,而是Model 的实例。因此,PhpStorm 期望此处有多种额外的返回类型,并在您的语句中打印此警告,因为它与方法返回类型 ?self 不同。

快速解决方案是将newQuery() 更改为newModelQuery()。这将创建一个新查询并在创建的查询上设置 Model Car 并返回适当的实例或 null

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Car extends Model
{
    public static function getTheFirstCar(string $color): ?self
    {
        return (new self())->newModelQuery()->firstWhere('color', '=', $color);
        // I'd use this statement though:
        // return self::where('color', '=', $color)->first();
    }
}

【讨论】:

  • 一个不错的“原生”解决方案,加上详尽的描述;我真的很感激。谢谢。我也想知道,为什么你宁愿使用“魔术”方法,而不是it causes just another warning
  • 我知道 laravel 外观是一种有争议的方法。我个人喜欢这种方法并且已经习惯了。如果我真的需要一些自动完成功能或想省略警告,那么我只需创建一个 \@method 或 \@property 注释。另一个不错的选择是使用 ide-plugin,但在我最近的项目中,我什至没有考虑将它添加到我的依赖项中。
  • 值得注意的是,newModelQuery 没有注册全局作用域,也不完全类似于 newQuery 的模型集。文档:“获取一个没有任何全局范围或预加载的新查询构建器。”
【解决方案2】:

您需要将文档块添加到您的课程中:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
 * Class Car
 * @package App\Models
 *
 * @method self|Builder newQuery()
 * @method ?self firstWhere($column, $operator = null, $value = null, $boolean = 'and')
 */
class Car extends Model
{
    public static function getTheFirstCar(string $color): ?self
    {
        return (new self())->newQuery()->firstWhere('color', '=', $color);
    }
}

【讨论】:

  • 但是如果你在类级别的文档块中添加@method self|Builder newQuery(),则内联文档块是不必要的。但是OP想用这种方式。
猜你喜欢
  • 2016-11-20
  • 1970-01-01
  • 2020-02-19
  • 1970-01-01
  • 2017-02-06
  • 2019-01-01
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
相关资源
最近更新 更多