2022年2月11日13:37:13
觉得laravel orm好用的时候,我一直想去花时间了解是为什么,但是工作一直都挺忙的,最近自己在写一些东西的时候,为了防止调用方式不对
看了下源码:
$counter = AdminLog::where('is_delete', GlobalCode::NORMAL);
我通过静态调用追查源码发现这个类其实是动态方法
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
if ($column instanceof Closure && is_null($operator)) {
$column($query = $this->model->newQueryWithoutRelationships());
$this->query->addNestedWhereQuery($query->getQuery(), $boolean);
} else {
$this->query->where(...func_get_args());
}
return $this;
}
继承的模型的Model 调用的 Builder
Model的call
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return $this->$method(...$parameters);
}
if ($resolver = (static::$relationResolvers[get_class($this)][$method] ?? null)) {
return $resolver($this);
}
return $this->forwardCallTo($this->newQuery(), $method, $parameters);
}
/**
* Handle dynamic static method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
Build的call
public function __call($method, $parameters)
{
if ($method === 'macro') {
$this->localMacros[$parameters[0]] = $parameters[1];
return;
}
if ($this->hasMacro($method)) {
array_unshift($parameters, $this);
return $this->localMacros[$method](...$parameters);
}
if (static::hasGlobalMacro($method)) {
$callable = static::$macros[$method];
if ($callable instanceof Closure) {
$callable = $callable->bindTo($this, static::class);
}
return $callable(...$parameters);
}
if ($this->hasNamedScope($method)) {
return $this->callNamedScope($method, $parameters);
}
if (in_array($method, $this->passthru)) {
return $this->toBase()->{$method}(...$parameters);
}
$this->forwardCallTo($this->query, $method, $parameters);
return $this;
}
/**
* Dynamically handle calls into the query instance.
*
* @param string $method
* @param array $parameters
* @return mixed
*
* @throws \BadMethodCallException
*/
public static function __callStatic($method, $parameters)
{
if ($method === 'macro') {
static::$macros[$parameters[0]] = $parameters[1];
return;
}
if ($method === 'mixin') {
return static::registerMixin($parameters[0], $parameters[1] ?? true);
}
if (! static::hasGlobalMacro($method)) {
static::throwBadMethodCallException($method);
}
$callable = static::$macros[$method];
if ($callable instanceof Closure) {
$callable = $callable->bindTo(null, static::class);
}
return $callable(...$parameters);
}
核心的方法就是 __call,__callStatic的互相使用
public function __call($method, $parameters)
{
return $this->$method(...$parameters);
}
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
这就是核心的部分
举个例子
test.php
<?php
include_once './p.php';
include_once './pp.php';
$a = new pp();
$a->notify(1111);
echo PHP_EOL;
//$a->aa(1111);
//pp::notify(1111);
p.php 父类
<?php
class p
{
public function notify($ddd)
{
print_r(get_class($this) . 'notify111111111');
echo PHP_EOL;
}
public static function refund()
{
echo self::class . 'refund';
}
public function __call($method, $parameters)
{
return $this->$method(...$parameters);
}
public static function __callStatic($method, $parameters)
{
return (new static)->$method(...$parameters);
}
}
pp.php 子类
<?php
class pp extends p
{
// public function notify($ddd)
// {
// print_r(get_class($this) . 'notify111111111');
// echo PHP_EOL;
// }
// public static function refund()
// {
// echo self::class . 'refund';
// }
}
注意事项:
1,继承父类和子类的时候,如果调用子类的方法的时候,子类方法必须要是protect或者更少的权限,因为会报警告
2,继承父类和子类的时候,如果方法是父类的如果方法,父类就不会报警告信息
3,如果子类,或者当前类有public,会先找public,如果没有在调用call,callStatic魔术方法
4,如果你需要设计成这样的 方法,请注意类的权限,不然会有很多小问题