怎么获取模型所关联的模型?

想要在控制器中获取当前模型有哪些模型关联,有什么函数可以提供?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

以下方法通过反射遍历并判断模型类的每一个方法返回值类型是否是Illuminate\Database\Eloquent\Relations\Relation::class模型关联类的子类,来获取已存在的关联关系

use Illuminate\Database\Eloquent\Relations\Relation;

/**
 * 获取模型的关联关系
 * @param string $model
 * @return array
 * @throws \ReflectionException
 */
public static function getModelRelations(string $model): array
{
  $methods = (new \ReflectionClass($model))->getMethods(\ReflectionMethod::IS_PUBLIC);

  return array_reduce($methods, function (array $res, \ReflectionMethod $method) {
  $returnType = is_null($method->getReturnType()) ? null : $method->getReturnType()->getName();

  return class_exists($returnType) && (new \ReflectionClass($returnType))->isSubclassOf(Relation::class)
 ? [...$res, $method->getName()]
 : $res;
 }, []);
}

由于是通过方法的返回值类型来判定,所以必须在模型中的关联方法声明返回值的类型,否则会遗漏,如:

/**
 * @return HasMany 用户列表
 */
public function users(): HasMany
{
    return $this->hasMany(User::class);
}

调用结果如下:

Laravel

3年前 评论
讨论数量: 2
private function getAllRelations(Model $model, $heritage = 'all')
{
    $modelName = get_class($model);
    $types = ['children' => 'Has', 'parents' => 'Belongs', 'all' => ''];
    $heritage = in_array($heritage, array_keys($types)) ? $heritage : 'all';

    $reflectionClass = new \ReflectionClass($model);
    $traits = $reflectionClass->getTraits();
    $traitMethodNames = [];
    foreach ($traits as $name => $trait) {
        $traitMethods = $trait->getMethods();
        foreach ($traitMethods as $traitMethod) {
            $traitMethodNames[] = $traitMethod->getName();
        }
    }
    $currentMethod = collect(explode('::', __METHOD__))->last();
    $filter = $types[$heritage];
    $methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
    $methods = collect($methods)->filter(function ($method) use ($modelName, $traitMethodNames, $currentMethod) {
        $methodName = $method->getName();
        if (!in_array($methodName, $traitMethodNames)
            && strpos($methodName, '__') !== 0 
            && $method->class === $modelName
            && !$method->isStatic() 
            && $methodName != $currentMethod 
        ) {
            $parameters = (new ReflectionMethod($modelName, $methodName))->getParameters();
            return collect($parameters)->filter(function ($parameter) {
                return !$parameter->isOptional();
            })->isEmpty();
        }
        return false;
    })->mapWithKeys(function ($method) use ($model, $filter) {
        $methodName = $method->getName();
        $relation = $model->$methodName(); 
        if (is_subclass_of($relation, Relation::class)) {
            $type = (new ReflectionClass($relation))->getShortName(); 
            if (!$filter || strpos($type, $filter) === 0) {
                return [$methodName => ['class' => get_class($relation->getRelated()), 'relation' => get_class($relation) ] ];
            }
        }
        return [];
    })->toArray();
    return $methods;
}
5年前 评论

以下方法通过反射遍历并判断模型类的每一个方法返回值类型是否是Illuminate\Database\Eloquent\Relations\Relation::class模型关联类的子类,来获取已存在的关联关系

use Illuminate\Database\Eloquent\Relations\Relation;

/**
 * 获取模型的关联关系
 * @param string $model
 * @return array
 * @throws \ReflectionException
 */
public static function getModelRelations(string $model): array
{
  $methods = (new \ReflectionClass($model))->getMethods(\ReflectionMethod::IS_PUBLIC);

  return array_reduce($methods, function (array $res, \ReflectionMethod $method) {
  $returnType = is_null($method->getReturnType()) ? null : $method->getReturnType()->getName();

  return class_exists($returnType) && (new \ReflectionClass($returnType))->isSubclassOf(Relation::class)
 ? [...$res, $method->getName()]
 : $res;
 }, []);
}

由于是通过方法的返回值类型来判定,所以必须在模型中的关联方法声明返回值的类型,否则会遗漏,如:

/**
 * @return HasMany 用户列表
 */
public function users(): HasMany
{
    return $this->hasMany(User::class);
}

调用结果如下:

Laravel

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!