在魔术方法__callStatic中对Trait函数进行别名定义
P粉226642568
2023-07-31 11:46:23
<p>我有一个Queryable trait,它使用__callStatic方法创建一个Builder的新实例,并在其上运行调用的函数(如果存在)。它返回Builder以便链式查询(类似于Eloquent)。<br /><br />现在我正在尝试实现一个需要find()函数的接口,但是在Queryable trait的phpDoc中声明了find()函数(@method static static find(mixed $primaryKeyValue)),这就创建了冲突:</p><p><code></code></p>
<blockquote>
<p>Queryable的find(primaryKeyValue: mixed)的声明必须与StorageInterface->find(primaryKeyValue: mixed)兼容,无法创建接口方法。</p>
</blockquote>
<p>为了解决这个冲突,我尝试使用类似于trait别名的方式(use Queryable { Queryable::find as queryFind; })来解决,但是接着我遇到了...</p>
<blockquote>
<p>编译错误:为appFrameworkTraitsQueryable::find定义了一个别名,但是该方法不存在。</p>
</blockquote>
<p>我似乎找不到解决办法,能有位高手帮帮我吗? :)(我相信这与类上的某种存在检查有关,因为它是一个魔术方法,但我也不知道如何修复它..)</p>
<pre class="brush:php;toolbar:false;"><?php
namespace appFrameworkTraits;
use appFrameworkDatabaseBuilder;
use appFrameworkDatabasePaginator;
/*** @方法静态 int count()
* @method static static|数组;首先(int $金额 = 1)
* @method static static|数组;最后(int $金额 = 1)
* @method 静态字符串 getQuery()
* @method 静态字符串 getRawQuery()
* @method 静态字符串 getPrimaryKey()
* @method static static find(混合$primaryKeyValue)
* @method静态数组;全部()
* @method静态数组;得到()
* @method static Paginator paginate()
* @method static Builder table(string $tableName)
* @method static Builder PrimaryKey(字符串 $primaryKey)
* @method static Builder perPage(int $perPageAmount)
* @method static Builder 其中(字符串$column,混合$operatorOrValue = null,混合$value = null)
* @method static Builder whereIn(字符串$列,数组$搜索)
* @method static Builder whereNotNull(string $column)
* @method static Builder select(...$columns)
* @method static Builder with(string $relation, Closure $closure)
* @method static Builder orderBy(string $column, string $direction = 'desc')
* @method static Builder limit(int $amount)
* @method static Builder 偏移量(int $amount)*/
trait Queryable
{
public static function __callStatic(string $name, array $arguments)
{
$functions = get_class_methods(Builder::class);
if (in_array($name, $functions)) {
$builder = new Builder(static::class);
return $builder->$name(...$arguments);
}
$selfFunctions = get_class_methods($calledClass = static::class);
if (!in_array($name, $selfFunctions)) {
throw new BadMethodCallException("Static method '{$name}' does not exist on {$calledClass}.");
}
return static::$name(...$arguments);
}
}
class BaseModel extends stdClass implements QueryableInterface, StorableInterface
{
use Queryable {
Queryable::find as queryFind;
}
public function find(mixed $primaryKeyValue): static
{
return self::queryFind($primaryKeyValue);
}
}
<?php
namespace appStorageMethods;
interface StorableInterface
{
function getObject(mixed $primaryKeyValue): static;
function find(mixed $primaryKeyValue): static;
function save(): static;
}</pre>
<p><br /></p>
Trait方法可以被“重命名”:(实际上是一个别名)
Reference
简单示例:
<?php Trait myTrait { public static function __callStatic ($method, $arguments) { $className = self::class; return (new $className ())->$method(...$arguments); } private function find() { echo "\naaaaaaaaaaaaa\n"; return $this; } } interface MyInterface { public function find(); } class Test Implements MyInterface { Use myTrait { find as myFind; } public function find() { echo "\nxxxxxx\n"; } } Test::myFind()->find();