php - 从特征覆盖类方法并在特征中再次调用它
问题描述
我正在尝试从使用特征的类中覆盖一个方法(实际上不是一个方法,而是一个不存在的触发 callStatic() 的方法)。但是从特征的方法中,我需要能够从类中调用基方法。(见代码)
namespace Foundation\Traits;
use Foundation\Cache\ModelCache;
trait Cacheable
{
public static function find($id, $columns = ['*'])
{
if ((bool)config('model.caching')) {
$model = ModelCache::findOrRequery($id, get_called_class());
return self::filterFromColumns($model, $columns);
}
return self::findWithoutCache($id, $columns);
}
public static function findWithoutCache($id, $columns = ['*'])
{
return parent::find($id, $columns);
}
private static function filterFromColumns($model, $columns)
{
if ($columns !== ['*']) {
return collect($model)->first($columns);
}
return $model;
}
}
问题是 find 方法陷入了无限循环,因为它在 trait 上调用 find 方法,而不是在使用 trait 的类上调用。
这也不能解决问题:
public static function findWithoutCache($id, $columns = ['*'])
{
return parent::__callStatic('find', [$id, $columns]);
}
我该如何解决这个问题?
解决方案
我认为您还有其他事情要做,特征绝对可以调用父类上被特征覆盖的方法,就像您可以直接在继承类中一样。这是一个例子:
<?php
trait MyTrait
{
public static function find()
{
echo 'MyTrait::find'.PHP_EOL;
self::findWithoutCache();
}
public static function findWithoutCache()
{
echo 'MyTrait::findWithoutCache'.PHP_EOL;
parent::find();
}
}
class MyBaseClass
{
public static function find()
{
echo 'MyBaseClass::find'.PHP_EOL;
}
}
class MyClass extends MyBaseClass
{
use MyTrait;
}
$myClass = new MyClass();
$myClass::find();
编辑:
根据您对 Laravel 模型中发生的这种情况的评论,您不能find
静态调用该方法,您必须拥有模型的实例。如果您查看类中的__call
和__callStatic
方法中 的代码Illuminate\Database\Eloquent\Model
,就会清楚发生了什么:
/**
* Handle dynamic method calls into the model.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
$query = $this->newQuery();
return call_user_func_array([$query, $method], $parameters);
}
/**
* Handle dynamic static method calls into the method.
*
* @param string $method
* @param array $parameters
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
$instance = new static;
return call_user_func_array([$instance, $method], $parameters);
}
在父对象上静态调用find
只是调用特征中的方法,但是如果你调用find
模型的实例,aIlluminate\Database\Eloquent
将被实例化,它的find
方法将被调用,并返回结果。
最重要的是,Eloquent 似乎并没有按照您想要的方式静态工作。
推荐阅读
- html - 使用 Angular 6+ 捕获选择选项值
- reactjs - 将自定义类/样式传递给 Gatsby (React) 中的样式化组件
- php - 如何从 Wappalyzer 隐藏 Yii Web 框架名称?
- linux - crontab 日志目录?
- java - 如何使用 Double 数据类型减少流
- python - Conda vtk 已安装,但 python 显示 - 没有名为 vtk 的模块
- javascript - TypeError:无法读取未定义的 react-redux-toastr 的属性“确认”
- python - Pandas 将 csv 转换为 dict
- firebase - 我的 Firebase Cloud Firestore 数据库是安全的还是易受攻击的?
- xcode - 无法上传 .ipa 文件:通信错误。请使用诊断模式检查连接