从特征重写Class方法,并在特征中再次调用它

时间:2018-10-15 13:51:05

标签: php oop object traits software-design

我试图使用特质从类重写方法(实际上不是方法,而是触发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]);
    }

我该如何解决这个问题?

1 个答案:

答案 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类中__callStaticIlluminate\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}}方法将被调用,并返回结果。

最重要的是,雄辩似乎并未以您想要的方式静态地工作。