Laravel eloquent: 关系如何从查询生成器继承函数?
Laravel eloquent: How does relation inherit functions from query builder?
他们如何实现 Illuminate\Database\Eloquent\Relations\Relation
可以访问所有查询构建器功能?
我看到他们有一个 $query 属性,但没有解释它的所有方法如何在关系中可用
如果您知道 php magic methods then you will know __call method
当您初始化 php 对象并尝试调用 class 中不可用的方法时,将调用此方法。通过使用 Illuminate\Database\Eloquent\Relations\Relation
class 的 __call 方法 ,他们将呼叫转发给 Illuminate\Database\Eloquent\Builder
。我会通过指出代码来解释得很清楚。
在 laravel 框架中有一个名为 ForwardsCalls 的特征。许多 classes 中使用此特征来处理呼叫转移到另一个 class.
下面是来自 Relation
class 的呼叫如何转发到 Builder
class。在启动新关系时 class Builder class 将是 initialized. So when you try to call a method from reltion class which is not available it will call __call method. After that it will look for a available macros . So when a macros method is not found. Then it will use forwardDecoratedCallTo from ForwardsCalls Trait.
因此 forwardDecoratedCallTo 将接受 3 个参数,即 $object, $method and $parameters
。而
$object
将是 $this->query
,它有一个 Illuminate\Database\Eloquent\Builder
实例。
$method
将是您尝试从 Builder Method 访问的方法。
$parameters
将是传递给该方法的所有参数。
我将尝试演示没有 laravel
中的特征和助手的示例
class ClassTwo {
public function classTwoMethodOne()
{
dd(__FUNCTION__.' has been called');
}
public function classTwoMethodTwo()
{
dd(__FUNCTION__.' has been called');
}
public function classTwoMethodThree()
{
//you cannot call this method dynamically
dd(__FUNCTION__.' has been called');
}
}
class ClassOne {
public function classOneMethodOne()
{
dd(__FUNCTION__.' has been called');
}
public function classOneMethodTwo()
{
dd(__FUNCTION__.' has been called');
}
public function __call($methodName, $arguments)
{
$methodsTobeForwarededtoClassTwo = [
'classTwoMethodOne',
'classTwoMethodTwo',
// 'classTwoMethodThree'
//i have commented this method so you cannot access it
//from dynamic calls
];
if(in_array($methodName,$methodsTobeForwarededtoClassTwo))
{
return (new ClassTwo)->{$methodName}($arguments);
}
dd(sprintf(
'Call to undefined method ClassTwo::%s()', $methodName
));
}
}
所以测试部分来了。
$classOneobj = new ClassOne;
Basic Test
dump($classOneobj->classOneMethodOne());
将输出为 classOneMethodOne 已被调用
dump($classOneobj->classOneMethodTwo());
将输出为 classOneMethodTwo 已被调用
Dynamic Call Test
dump($classOneobj->classTwoMethodOne());
将输出为 classTwoMethodOne 已被调用
dump($classOneobj->classTwoMethodTwo());
将输出为 classOneMethodTwo 已被调用
dump($classOneobj->classTwoMethodThree());
将输出为 Call to undefined method ClassTwo::classTwoMethodThree() 因为我在 __call
函数中评论了那个方法 ClassOne
.
如果您还需要澄清,请post发表评论
他们如何实现 Illuminate\Database\Eloquent\Relations\Relation
可以访问所有查询构建器功能?
我看到他们有一个 $query 属性,但没有解释它的所有方法如何在关系中可用
如果您知道 php magic methods then you will know __call method
当您初始化 php 对象并尝试调用 class 中不可用的方法时,将调用此方法。通过使用 Illuminate\Database\Eloquent\Relations\Relation
class 的 __call 方法 ,他们将呼叫转发给 Illuminate\Database\Eloquent\Builder
。我会通过指出代码来解释得很清楚。
在 laravel 框架中有一个名为 ForwardsCalls 的特征。许多 classes 中使用此特征来处理呼叫转移到另一个 class.
下面是来自 Relation
class 的呼叫如何转发到 Builder
class。在启动新关系时 class Builder class 将是 initialized. So when you try to call a method from reltion class which is not available it will call __call method. After that it will look for a available macros . So when a macros method is not found. Then it will use forwardDecoratedCallTo from ForwardsCalls Trait.
因此 forwardDecoratedCallTo 将接受 3 个参数,即 $object, $method and $parameters
。而
$object
将是$this->query
,它有一个Illuminate\Database\Eloquent\Builder
实例。$method
将是您尝试从 Builder Method 访问的方法。$parameters
将是传递给该方法的所有参数。
我将尝试演示没有 laravel
中的特征和助手的示例class ClassTwo {
public function classTwoMethodOne()
{
dd(__FUNCTION__.' has been called');
}
public function classTwoMethodTwo()
{
dd(__FUNCTION__.' has been called');
}
public function classTwoMethodThree()
{
//you cannot call this method dynamically
dd(__FUNCTION__.' has been called');
}
}
class ClassOne {
public function classOneMethodOne()
{
dd(__FUNCTION__.' has been called');
}
public function classOneMethodTwo()
{
dd(__FUNCTION__.' has been called');
}
public function __call($methodName, $arguments)
{
$methodsTobeForwarededtoClassTwo = [
'classTwoMethodOne',
'classTwoMethodTwo',
// 'classTwoMethodThree'
//i have commented this method so you cannot access it
//from dynamic calls
];
if(in_array($methodName,$methodsTobeForwarededtoClassTwo))
{
return (new ClassTwo)->{$methodName}($arguments);
}
dd(sprintf(
'Call to undefined method ClassTwo::%s()', $methodName
));
}
}
所以测试部分来了。
$classOneobj = new ClassOne;
Basic Test
dump($classOneobj->classOneMethodOne());
将输出为 classOneMethodOne 已被调用dump($classOneobj->classOneMethodTwo());
将输出为 classOneMethodTwo 已被调用
Dynamic Call Test
dump($classOneobj->classTwoMethodOne());
将输出为 classTwoMethodOne 已被调用dump($classOneobj->classTwoMethodTwo());
将输出为 classOneMethodTwo 已被调用dump($classOneobj->classTwoMethodThree());
将输出为 Call to undefined method ClassTwo::classTwoMethodThree() 因为我在__call
函数中评论了那个方法ClassOne
.
如果您还需要澄清,请post发表评论