如何在Laravel雄辩中建立三个表之间的关系?

时间:2017-06-17 20:24:42

标签: php laravel laravel-5.4 laravel-eloquent

我正在尝试从与我目前使用的模型没有直接关系的表中检索数据。

我的数据结构:

表:帖子

  • id - 整数
  • title - string

表: post_stacks

  • id - 整数
  • post_id - 整数
  • stack_id - 整数

表:堆叠

  • id - 整数
  • body - string
  • url - string

我雄辩的模型来自Post.php(posts表),我正在尝试获取与我的帖子相关的所有堆栈(来自堆栈表)。我想仅在Post.php而不是我的数据透视表(post_stacks)上声明我的关系。

我已经尝试hasManyThrough但是我的表的结构不符合Laravel所要求的要求,因为我需要在Stacks表上使用外键。

这是我目前的实施:

post.php中

class Post extends Model
{

    protected $dates = [
      'created_at',
      'updated_at'
    ];

    public function user()
    {
        return $this->belongsTo(\App\User::class, 'user_id', 'id');
    }

    public function post_stacks()
    {
        return $this->hasMany(\App\PostStack::class);
    }

    public function post_os()
    {
        return $this->hasMany(\App\PostOS::class, 'post_id', 'id');
    }

    public function post_tags()
    {
        return $this->hasMany(\App\PostTag::class , 'post_id', 'id');
    }

    public function getCreatedAtAttribute($value)
    {
        return Carbon::parse($value)->toFormattedDateString();
    }

}

PostController.php

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();

        foreach($posts as $post){
            $post->user;
            $post->created_at;
            $posts_os = $post->post_os;
            $post_stacks = $post->post_stacks;
            $post_tags = $post->post_tags;

            foreach($posts_os as $post_os){
                $os = OS::where('id', $post_os->os_id)->first();
                $post_os['body'] = $os['body'];
            }

            foreach($post_stacks as $post_stack){
                $stack = Stack::where('id', $post_stack->stack_id)->first();
                $post_stack['url'] = $stack['url'];
                $post_stack['body'] = $stack['body'];
            }

            foreach($post_tags as $post_tag){
                $tag = Tag::where('id', $post_tag->tag_id)->first();
                $post_tag['body'] = $tag['body'];
            }
        }

        return response()->json($posts);
    }

}

我的JSON数据回复

[  
   {  
      "id":1,
      "title":"Laravel + XAMPP",
      "user_id":1,
      "description":"I'll take you through the entire process of setting up a development environment for Laravel using XAMPP.",
      "created_at":"Jun 12, 2017",
      "updated_at":"2017-06-12 08:55:02",
      "user":{  
         "id":1,
         "name":"EpIEhg7ciO",
         "email":"AiyZXrubVG@gmail.com",
         "created_at":"2017-06-12 08:55:02",
         "updated_at":"2017-06-12 08:55:02"
      },
      "post_os":[  
         {  
            "id":1,
            "post_id":1,
            "os_id":1,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"Windows"
         }
      ],
      "post_stacks":[  
         {  
            "id":1,
            "post_id":1,
            "stack_id":1,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "url":"laravel.svg",
            "body":"Laravel"
         },
         {  
            "id":2,
            "post_id":1,
            "stack_id":2,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "url":"xampp.svg",
            "body":"XAMPP"
         }
      ],
      "post_tags":[  
         {  
            "id":1,
            "post_id":1,
            "tag_id":1,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"laravel"
         },
         {  
            "id":2,
            "post_id":1,
            "tag_id":2,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"xampp"
         }
      ]
   },
   {  
      "id":2,
      "title":"Laravel + Vagrant",
      "user_id":1,
      "description":"I'll take you through the entire process of setting up a development environment for Laravel using Vagrant.",
      "created_at":"Jun 12, 2017",
      "updated_at":"2017-06-12 08:55:02",
      "user":{  
         "id":1,
         "name":"EpIEhg7ciO",
         "email":"AiyZXrubVG@gmail.com",
         "created_at":"2017-06-12 08:55:02",
         "updated_at":"2017-06-12 08:55:02"
      },
      "post_os":[  
         {  
            "id":2,
            "post_id":2,
            "os_id":1,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"Windows"
         },
         {  
            "id":3,
            "post_id":2,
            "os_id":2,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"Mac OS X"
         },
         {  
            "id":4,
            "post_id":2,
            "os_id":3,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"Linux"
         }
      ],
      "post_stacks":[  
         {  
            "id":3,
            "post_id":2,
            "stack_id":1,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "url":"laravel.svg",
            "body":"Laravel"
         },
         {  
            "id":4,
            "post_id":2,
            "stack_id":3,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "url":"vagrant.png",
            "body":"Vagrant"
         }
      ],
      "post_tags":[  
         {  
            "id":3,
            "post_id":2,
            "tag_id":1,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"laravel"
         },
         {  
            "id":4,
            "post_id":2,
            "tag_id":3,
            "created_at":"2017-06-12 08:55:02",
            "updated_at":"2017-06-12 08:55:02",
            "body":"vagrant"
         }
      ]
   }
]

我的JSON数据正是我想要的。我只是认为我的PostController实现效率低下并且运行了太多查询。我运行太多查询并具有嵌套循环。我是否可以使用Laravel的方法/关系之一建立关系?

谢谢!

1 个答案:

答案 0 :(得分:2)

你能在Stack模型上声明关系吗?您只排除了在数据透视表上添加关系。如果是这样的话:

class Post extends Model
{
    public function stacks()
    {
        return $this->hasMany(\App\Stack::class);
    }
}

class Stack extends Model
{
    public function posts()
    {
        return $this->belongsToMany(\App\Post::class);
    }
}

通过PostStack模型中定义的字段,这应该是Eloquent使关系工作所需的全部内容。此外,您可以访问pivot属性,允许您:

$post->pivot->somePropertyOnStack

修改

摘录文档,让您大致了解雄辩如何决定关系:

  

请记住,Eloquent会自动确定Comment模型上的正确外键列。按照惯例,Eloquent将采取"蛇案例"拥有模型的名称,并以_id为后缀。因此,对于此示例,Eloquent将假定Comment模型上的外键是post_id。

与加入表格的关系:

  

确定关系表的连接表,Eloquent将按字母顺序加入两个相关的模型名称。

这部分文档将解释每种关系类型以及Eloquent如何发生它们:

https://laravel.com/docs/5.4/eloquent-relationships#defining-relationships