我试图使用特质从类重写方法(实际上不是方法,而是触发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而不是使用trait的类上调用find方法。
这也不能解决问题:
public static function findWithoutCache($id, $columns = ['*'])
{
return parent::__callStatic('find', [$id, $columns]);
}
我该如何解决这个问题?
答案 0 :(得分:0)
我认为您还有其他事情,特质绝对可以在父类上调用被特质覆盖的方法,就像您可以直接在继承类中一样。这是一个示例:
<?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
,则会实例化一个Illuminate\Database\Eloquent
,它是{{ 1}}方法将被调用,并返回结果。
最重要的是,雄辩似乎并未以您想要的方式静态地工作。