Laravel 在 where 子句静态方法中有列名

Laravel having column name in where clause static method

最近我才意识到 Laravel 在使用驼峰式

加入 where 子句时会生成一个带有列名的静态方法

示例

$user = User::whereName('john')->first(); // added `name` as a column name

当将此代码调用到 SQL 时,它会生成

$user = User::whereName('john')->toSql();

//it returns
select * from `users` where `name` = ?

这确实给出了预期的结果,因为它 returns 一个名为 john 的用户。

我搜索了 Laravel 文档,但找不到此函数或它的定义位置。

我只需要澄清这个方法是好的还是最好的,这样我就可以继续使用它,并且知道这个方法是如何在 Laravel 框架或任何其他方式中生成的

试试这个

$user = User::where('name','john')->first();

这种方法是完全合法的,你没有很好的记录。在 Query\Builder 中,它利用 __call 函数覆盖来生成功能,您可以看到确切的函数 here.

魔法方法和 __call 函数的主题,如果它们变得更好,通常是非常值得商榷的。如果你使用 IDE helper。它实际上会为您键入提示方法,从而减轻它所采用的一些神奇方法,并为您提供流畅的 IDE 体验。

我从本地项目生成的类型提示的示例。

* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\App\Models\User whereEmail($value)

因此我不会担心这不是最好的方法。有多种方法可以完成您正在做的事情,但这是正确的方法之一。

如果您要问负责它工作的代码在哪里,它会在 class Illuminate\Database\Query\Builder

/**
     * Handle dynamic method calls into the method.
     *
     * @param  string  $method
     * @param  array   $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public function __call($method, $parameters)
    {
        if (static::hasMacro($method)) {
            return $this->macroCall($method, $parameters);
        }

        if (Str::startsWith($method, 'where')) {
            return $this->dynamicWhere($method, $parameters);
        }

        static::throwBadMethodCallException($method);
    }

恰好在条件 Str::startsWith($method, 'where') 中将调用重定向到 dynamicWhere()

/**
     * Handles dynamic "where" clauses to the query.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return $this
     */
    public function dynamicWhere($method, $parameters)
    {
        $finder = substr($method, 5);

        $segments = preg_split(
            '/(And|Or)(?=[A-Z])/', $finder, -1, PREG_SPLIT_DELIM_CAPTURE
        );

        // The connector variable will determine which connector will be used for the
        // query condition. We will change it as we come across new boolean values
        // in the dynamic method strings, which could contain a number of these.
        $connector = 'and';

        $index = 0;

        foreach ($segments as $segment) {
            // If the segment is not a boolean connector, we can assume it is a column's name
            // and we will add it to the query as a new constraint as a where clause, then
            // we can keep iterating through the dynamic method string's segments again.
            if ($segment !== 'And' && $segment !== 'Or') {
                $this->addDynamic($segment, $connector, $parameters, $index);

                $index++;
            }

            // Otherwise, we will store the connector so we know how the next where clause we
            // find in the query should be connected to the previous ones, meaning we will
            // have the proper boolean connector to connect the next where clause found.
            else {
                $connector = $segment;
            }
        }

        return $this;
    }

你需要在你的模型中定义这个函数

//controller
$userObj=new \App\User();
$userObj->whereName('john');
//model
function whereName($name){
return $this->where('name',$name)->first();
}

如果您担心这是否是最佳实践,我会说 不是不要使用 这些神奇的方法,为什么:

  1. 当您对该列的使用位置进行全局搜索时,结果中将不会有这些魔术方法(除非您记得再次搜索明确的位置)。
  2. 静态代码分析工具将很难识别这些方法,即使您现在没有使用此类工具,您也可能会在功能中使用它。
  3. 这是一件奇怪的事情,除非您专门为其添加第三方,否则您得不到 IDE 支持。
  4. 这很令人困惑,想象一下,由于某种原因你有一个大写字母的列,你将如何处理它?
  5. 你不能在使用这种方法的地方做批量操作,即 ->where(['name' => 'moh', 'user_id'=> 2]),因此,1. 如果你有很多列要查询,你最终会得到一些行而不是仅仅传递一个数组 2. 如果您有一个要查询的数组,假设它来自前端,那么您最终会使用普通的 where。
  6. 基于前面2点,你的代码可能存在不一致,有时使用魔术方法,有时不使用。
  7. 缺少纪录片