laravel 如何在没有模型示例的情况下以编程方式获取关系数据?

gijlo24d  于 2023-01-27  发布在  其他
关注(0)|答案(1)|浏览(116)

我有下面的工作代码,它提供了一个模型类型的集合,每个模型类型都有给定的关系值(比如id为1、2或3的标记):

<?php

public function getEntitiesWithRelationValues($entityType, $relations = []) {
    $related = new EloquentCollection();
    $locale = App::getLocale();

    $entityType = new $entityType(); // bad?
    // $entityType = new ReflectionClass($entityType); // not working

    foreach ($relations as $relation => $modelKeys) {
        if ($entityType->{$relation}()->exists()) {
            

            $relatedClass = get_class($entityType->{$relation}()->getRelated());
            $relationPrimaryKeyName = ($instance = new $relatedClass)->getQualifiedKeyName();
            $relationEntities = $entityType::where('published->' . $locale, true)
                ->whereHas($relation, function (Builder $query) use($modelKeys, $relationPrimaryKeyName) {
                    $query->whereIn($relationPrimaryKeyName, $modelKeys);
                })
                ->get()
                ->sortKeysDesc()
                ->take(10)
                ;

            $related = $related->concat($relationEntities->except($related->modelKeys()));
        }
    }
    return $related;
}

我觉得$entityType = new $entityType();是错误的代码,因为我不想创建一个新的模型。反射类抛出错误“ReflectionClass undefined method {$relation}"。我如何在不实际加载/示例化模型的情况下获得模型类型的关系数据?
几周前我问了一些类似的here,但在那种情况下,我确实加载了一个模型。

vbopmzt1

vbopmzt11#

您可以考虑以下解决方案:
1.实际上,使用Model示例作为getEntitiesWithRelationValues()函数的输入,因为无论如何,您都要检索特定示例的关系,对吗?
1.为模型创建属性:

public static $relationNames = ['tags', 'posts', 'comments'];

1.使用MyModel::$relationNames在代码中检索该属性,并调用所需的任何函数。

使用反射的替代解决方案

下面的代码片段使用反射来查找User::class的所有公共方法,然后根据它是否是\Illuminate\Database\Eloquent\Relations\Relation的子类来过滤返回类型。注意,您需要专门使用新的语言结构体(如public function myMethod() : MyReturnType { })来注解返回类型。

use App\Models\User;
use Illuminate\Database\Eloquent\Relations\Relation;

$relationshipMethods = collect(
(new ReflectionClass(User::class))
    ->getMethods(\ReflectionMethod::IS_PUBLIC)
)
->filter(function(\ReflectionMethod $method) {
    // The `?` makes the code work for methods without an explicit return type.
    return is_subclass_of($method->getReturnType()?->getName(), Relation::class);
})->values();

// $relationshipMethods now is a collection with \ReflectionMethod objects.

相关问题