关于laravel 使用__call,__callStatic实现静态,动态方法互相调用
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,如果你需要设计成这样的 方法,请注意类的权限,不然会有很多小问题
QQ一群 247823727
QQ二群 166427999
博客文件如果不能下载请进群下载
如果公司项目有技术瓶颈问题,请联系↓↓
如果需要定制系统开发服务,请联系↓↓
技术服务QQ: 903464207
QQ二群 166427999
博客文件如果不能下载请进群下载
如果公司项目有技术瓶颈问题,请联系↓↓
如果需要定制系统开发服务,请联系↓↓
技术服务QQ: 903464207