繁体   English   中英

获取 Eloquent 模型关系数组

[英]Get array of Eloquent model's relations

我正在尝试获取所有模型关联的数组。 我有以下 model:

class Article extends Eloquent 
{
    protected $guarded = array();

    public static $rules = array();

    public function author() 
    {
        return $this->belongsTo('Author');
    }

    public function category() 
    {
        return $this->belongsTo('Category');
    }
}

从此 model 中,我试图获得以下关系数组:

array(
    'author',
    'category'
)

我正在寻找一种方法来自动将该阵列从 model 中拉出。

我在 Eloquent model 上找到RelationsToArray 方法的定义,它似乎返回了模型关系的数组。 它似乎使用了 Eloquent model 的 $this->relations 属性。 但是,此方法返回一个空数组,并且关系属性是一个空数组,尽管我的关系设置正确。

如果不存储 model 关系,那么 $this->relations 用于什么? 有什么方法可以自动获取模型关系的数组吗?

这是不可能的,因为只有在通过使用with (用于预先加载)或使用模型中定义的关系公共方法请求时才加载关系,例如,如果使用以下关系创建Author模型

public function articles() {
    return $this->hasMany('Article');
}

当您像这样调用此方法时:

$author = Author::find(1);
$author->articles; // <-- this will load related article models as a collection

另外,正如我所说with ,当你使用这样的东西时:

$article = Article::with('author')->get(1);

在这种情况下,第一篇文章(id为1)将加载它的相关模型Author ,您可以使用

$article->author->name; // to access the name field from related/loaded author model

因此,如果不使用适当的方法加载关系,就不可能神奇地获得关系,但是一旦加载了关系(相关模型),您就可以使用这样的方法来获取关系:

$article = Article::with(['category', 'author'])->first();
$article->getRelations(); // get all the related models
$article->getRelation('author'); // to get only related author model

要将它们转换为array您可以使用toArray()方法,例如:

dd($article->getRelations()->toArray()); // dump and die as array

relationsToArray()方法适用于加载了相关模型的模型。 此方法将相关模型转换为数组形式,其中toArray()方法将模型(有关系)的所有数据转换为数组,源代码如下:

public function toArray()
{
     $attributes = $this->attributesToArray();

     return array_merge($attributes, $this->relationsToArray());
}

它在转换为数组后合并模型属性及其相关模型的属性,然后返回它。

用这个:

class Article extends Eloquent 
{
    protected $guarded = array();

    public static $rules = array();

    public $relationships = array('Author', 'Category');

    public function author() {
        return $this->belongsTo('Author');
    }

    public function category() {
        return $this->belongsTo('Category');
    }
}

所以在课外你可以做这样的事情:

public function articleWithAllRelationships()
{
    $article = new Article;
    $relationships = $article->relationships;
    $article = $article->with($relationships)->first();
}

GruBhub,非常感谢您的评论。 我已经更正了你提到的错字。

你是对的,运行未知方法是危险的,因此我在执行后添加了回滚。

非常感谢来自 laracasts 的 phildawson, https: //laracasts.com/discuss/channels/eloquent/get-all-model-relationships

您可以使用以下特征:

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Relations\Relation;

trait EloquentRelationshipTrait
{
/**
 * Get eloquent relationships
 *
 * @return array
 */
public static function getRelationships()
{
    $instance = new static;

    // Get public methods declared without parameters and non inherited
    $class = get_class($instance);
    $allMethods = (new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC);
    $methods = array_filter(
        $allMethods,
        function ($method) use ($class) {
            return $method->class === $class
                   && !$method->getParameters()                  // relationships have no parameters
                   && $method->getName() !== 'getRelationships'; // prevent infinite recursion
        }
    );

    \DB::beginTransaction();

    $relations = [];
    foreach ($methods as $method) {
        try {
            $methodName = $method->getName();
            $methodReturn = $instance->$methodName();
            if (!$methodReturn instanceof Relation) {
                continue;
            }
        } catch (\Throwable $th) {
            continue;
        }

        $type = (new \ReflectionClass($methodReturn))->getShortName();
        $model = get_class($methodReturn->getRelated());
        $relations[$methodName] = [$type, $model];
    }

    \DB::rollBack();

    return $relations;
}

}

然后你可以在任何模型中实现它。

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
use App\Traits\EloquentRelationshipTrait;

class User extends Authenticatable
{
    use Notifiable, HasApiTokens, EloquentRelationshipTrait;

最后使用 (new User)->getRelationships() 或 User::getRelationships() 你会得到:

[
 "notifications" => [
   "MorphMany",
   "Illuminate\Notifications\DatabaseNotification",
 ],
 "readNotifications" => [
   "MorphMany",
   "Illuminate\Notifications\DatabaseNotification",
 ],
 "unreadNotifications" => [
   "MorphMany",
   "Illuminate\Notifications\DatabaseNotification",
 ],
 "clients" => [
   "HasMany",
   "Laravel\Passport\Client",
 ],
 "tokens" => [
   "HasMany",
   "Laravel\Passport\Token",
 ],
]

我已经发布了package以便从 model 中获取所有 eloquent 关系。 这样的 package 包含帮助器“rel”来执行此操作。

在此处输入图像描述

只需运行(需要 Composer 2.x :):

require pablo-merener/eloquent-relationships

如果您在 laravel 9 上,您可以运行工匠命令model:show

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM