I'm trying to override a method (that is actually not a method but a not existing method that triggers callStatic()) from a class using a trait. But from within the method from the trait i need to be able to call the base method from the class. (see code)
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;
}
}
The problem is that the find method is stuck in an infinite loop because it calls the find method on the trait instead of the class using the trait.
This does also not fix the problem:
public static function findWithoutCache($id, $columns = ['*'])
{
return parent::__callStatic('find', [$id, $columns]);
}
How do i get around this problem?
I think you have something else going on, traits can definitely call methods on a parent class that are overridden by the trait, just like you can directly in the inheriting class. Here's an example:
<?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();
Edit:
Based upon your comment about this happening in a Laravel model, you cannot call the find
method statically, you have to have an instance of your model. If you look at the code in the __call
and __callStatic
methods in the Illuminate\\Database\\Eloquent\\Model
class, it becomes clear what is going on:
/**
* 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);
}
Calling find
statically on the parent just calls the method in your trait, but if you call find
on an instance of your model, a Illuminate\\Database\\Eloquent
will be instantiated, it's find
method will be called, and the results will be returned.
Bottom line, Eloquent just doesn't seem to be built to work statically the way you want it to.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.