它们是如何实现的,即Illuminate\Database\Eloquent\Relations\Relation
可以访问所有查询生成器函数?
我看到它们有一个$query属性,但是没有解释它的所有方法是如何在关系中可用的。
发布于 2021-10-20 01:25:22
如果您知道php 魔术法,那么当您初始化一个php对象并尝试调用类中不可用的方法时,就会知道这个方法会被调用。通过使用来自类的__call方法,它们将调用转发到Illuminate\Database\Eloquent\Builder
。我将通过指出代码来非常清楚地解释它。
在laravel框架中有一个名为ForwardsCalls的特性。这个特性在许多类中被用来处理呼叫转发到另一个类。
下面是如何将来自Relation
类的调用转发到Builder
类。初始化新的关系类Builder时,类将是已初始化。因此,当您尝试从reltion类调用方法时,它将调用打电话方法。之后,它将寻找一个可用宏。因此,当找不到宏方法时。然后,它将使用forwardDecoratedCallTo来自ForwardsCalls特性。
因此,forwardDecoratedCallTo将接受3个参数,即$object, $method and $parameters
。鉴于
$object
将是$this->query
,它有一个Illuminate\Database\Eloquent\Builder
实例。$method
将是您尝试从Builder访问的方法。$parameters
将是传递给该方法的所有参数。我将试着演示一下will的例子,而不需要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;
基本测试
dump($classOneobj->classOneMethodOne());
将以classOneMethodOne被称为的方式输出dump($classOneobj->classOneMethodTwo());
将以classOneMethodTwo被称为的方式输出动态呼叫测试
dump($classOneobj->classTwoMethodOne());
将以classTwoMethodOne被称为的方式输出dump($classOneobj->classTwoMethodTwo());
将以classOneMethodTwo被称为的方式输出dump($classOneobj->classTwoMethodThree());
将作为对未定义方法dump($classOneobj->classTwoMethodThree());
的调用输出,因为我已经在ClassOne
中的__call
函数中注释了该方法。如果你还需要澄清,请发表评论
https://stackoverflow.com/questions/69564270
复制相似问题