Laraveleloquent中的三个表如何建立关联?
How to establish a relationship between three tables in Laravel eloquent?
我正在尝试从与我当前使用的模型没有直接关系的 table 检索数据。
我的数据结构:
Table: posts
- id - 整数
- 标题 - 字符串
Table: post_stacks
- id - 整数
- post_id - 整数
- stack_id - 整数
Table:堆叠
- id - 整数
- body - 字符串
- url - 字符串
我的 eloquent 模型来自 Post.php (posts table),我正在尝试获取与我的 [=113= 关联的所有堆栈](来自堆栈 table)。我只想在 Post.php 而不是我的枢轴 table (post_stacks) 上声明我的关系。
我已经尝试 hasManyThrough
但我的 table 的结构不 "fit" 要求 Laravel 要求因为我需要在我的堆栈上使用外键 table.
这是我当前的实现:
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 的 methods/relationships 之一建立关系?
谢谢!
你能在 Stack 模型上声明关系吗?您只排除了在数据透视 table 上添加关系。如果是:
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 如何确定关系:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
对于加入 tables 的关系:
to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order.
文档的这一部分将解释每种关系类型以及 Eloquent 如何发生它们:
https://laravel.com/docs/5.4/eloquent-relationships#defining-relationships
我正在尝试从与我当前使用的模型没有直接关系的 table 检索数据。
我的数据结构:
Table: posts
- id - 整数
- 标题 - 字符串
Table: post_stacks
- id - 整数
- post_id - 整数
- stack_id - 整数
Table:堆叠
- id - 整数
- body - 字符串
- url - 字符串
我的 eloquent 模型来自 Post.php (posts table),我正在尝试获取与我的 [=113= 关联的所有堆栈](来自堆栈 table)。我只想在 Post.php 而不是我的枢轴 table (post_stacks) 上声明我的关系。
我已经尝试 hasManyThrough
但我的 table 的结构不 "fit" 要求 Laravel 要求因为我需要在我的堆栈上使用外键 table.
这是我当前的实现:
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 的 methods/relationships 之一建立关系?
谢谢!
你能在 Stack 模型上声明关系吗?您只排除了在数据透视 table 上添加关系。如果是:
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 如何确定关系:
Remember, Eloquent will automatically determine the proper foreign key column on the Comment model. By convention, Eloquent will take the "snake case" name of the owning model and suffix it with _id. So, for this example, Eloquent will assume the foreign key on the Comment model is post_id.
对于加入 tables 的关系:
to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order.
文档的这一部分将解释每种关系类型以及 Eloquent 如何发生它们:
https://laravel.com/docs/5.4/eloquent-relationships#defining-relationships