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