如何在处理 eloquent 关系的同时 Union/Merge 具有精确模式但不同数据的三个数据库表?
How to Union/Merge three database tables with exact schema but different data while taking care of eloquent relationships?
在我的 Laravel 应用程序中,我有三个具有完全相同 structure/schema 的数据库 table,然后有一个包含所有用户的 'users' table .
所有三个 table 都具有以下结构...
table1
id user_id 描述 updated_at created_at
1 1 这很好 xxxxxxxxxx xxxxxxxxx
2 2 对它是 xxxxxxxxxx xxxxxxxxx
table2
id user_id 描述 updated_at created_at
1 3 另一个文本 xxxxxxxxxx xxxxxxxxx
2 4 还有更多 xxxxxxxxxx xxxxxxxxx
table3
id user_id 描述 updated_at created_at
1 5 更好 xxxxxxxxxx xxxxxxxxx
2 6 好的 xxxxxxxxxx xxxxxxxxx
现在我真的很想将数据保存在这些单独的 table 中。但是,有时我需要在同一视图中显示这三个 table 中的所有这些条目,最好是 orderedBy created_at 字段。
我使用以下代码合并这些 tables:
$table2 = DB::table('table2');
$table3 = DB::table('table3');
$query = DB::table('table1')
->union($table1)
->union($table3)
->get();
出现的问题是 eloquent 关系不起作用,Blade 中的这个语句中断了。 {{$comment->user->name}}
.
我只想 union/merge 所有这三个 table 并且最好能够建立关系或找到其他方式,以便我可以获得用户的姓名拥有 union/merged 结果中的特定条目。并且还有 union/merged 结果按 created_at 列排序。
如有任何帮助,我们将不胜感激。
谢谢
假设您要合并 3 个实体的结果:director
、teacher
、student
,所有这三个实体都具有关系 role
:
你可以load the relationships first and then merge the collections using one of their many methods:
$directors = Director::with('role')->get();
$teachers = Teacher::with('role')->get();
$students = Student::with('role')->get();
$users = $directors
->merge($teachers)
->merge($students);
然后你可以访问关系:
dd($users->first()->role->name);
观察
如果您 return 使用 compact
方法而不是 with()
方法将此值添加到您的视图中,请记住以下几点:
return view('my_view', compact('users'));
然后您将一个关联数组传递给您的视图,因此为了访问关系中的值,您需要执行以下操作:
@foreach ($users as $user)
<h1> {{ $user['role']['name'] }} </h1>
@endforeach
串联
(按照您的方式操作)
到它在collections。在这里,我急于加载用户,但您不必这样做。不过,它将大大提高性能。请注意,由于您的设计选择,这是 3 个不同的查询,每个查询都执行一个连接。
$table1 = Table1::with('user')->all();
$table2 = Table2::with('user')->all();
$table3 = Table3::with('user')->all();
$tables = $table1->merge($table2)->merge($table3);
$tables = $tables->sortBy('create_at');
数据库和 OOP 设计
(这是你应该怎么做)
为什么要将它们分开 table?大多数人通常认为不规范化是糟糕的设计。如果两个 object 具有相同的 fields/members,则它们是 object.
的相同种类
如果objects有相同的字段,它们应该是object的同一种类型,你应该为object的类型添加一个标志来获取。所以不用三个 table 和
- id
- user_id
- 描述
- updated_at
- created_at
你会有一个 table 字段:
- id
- user_id
- 描述
- 类型
- updated_at
- created_at
确保将 index
放在 type
上,这样 不会影响性能 将它们全部放在同一个 table .然后让它们全部按 created_at 排序(注意一个查询,一个连接):
$tables = Table::->orderBy('created_at')->with('user')->get();
要破解一个:
$table1 = Table::where('type','=',1)->with('user')->get();
$table2 = Table::where('type','=',2)->with('user')->get();
$table3 = Table::where('type','=',3)->with('user')->get();
全部搞定,打散:
$tables = Table::->orderBy('created_at')->with('user')->get()->groupBy('type');
如果 object 的 "types" 中的一个(或多个)有新字段,那么您将开始 inheritance。
在我的 Laravel 应用程序中,我有三个具有完全相同 structure/schema 的数据库 table,然后有一个包含所有用户的 'users' table .
所有三个 table 都具有以下结构...
table1
id user_id 描述 updated_at created_at
1 1 这很好 xxxxxxxxxx xxxxxxxxx
2 2 对它是 xxxxxxxxxx xxxxxxxxx
table2
id user_id 描述 updated_at created_at
1 3 另一个文本 xxxxxxxxxx xxxxxxxxx
2 4 还有更多 xxxxxxxxxx xxxxxxxxx
table3
id user_id 描述 updated_at created_at
1 5 更好 xxxxxxxxxx xxxxxxxxx
2 6 好的 xxxxxxxxxx xxxxxxxxx
现在我真的很想将数据保存在这些单独的 table 中。但是,有时我需要在同一视图中显示这三个 table 中的所有这些条目,最好是 orderedBy created_at 字段。
我使用以下代码合并这些 tables:
$table2 = DB::table('table2');
$table3 = DB::table('table3');
$query = DB::table('table1')
->union($table1)
->union($table3)
->get();
出现的问题是 eloquent 关系不起作用,Blade 中的这个语句中断了。 {{$comment->user->name}}
.
我只想 union/merge 所有这三个 table 并且最好能够建立关系或找到其他方式,以便我可以获得用户的姓名拥有 union/merged 结果中的特定条目。并且还有 union/merged 结果按 created_at 列排序。
如有任何帮助,我们将不胜感激。
谢谢
假设您要合并 3 个实体的结果:director
、teacher
、student
,所有这三个实体都具有关系 role
:
你可以load the relationships first and then merge the collections using one of their many methods:
$directors = Director::with('role')->get();
$teachers = Teacher::with('role')->get();
$students = Student::with('role')->get();
$users = $directors
->merge($teachers)
->merge($students);
然后你可以访问关系:
dd($users->first()->role->name);
观察
如果您 return 使用 compact
方法而不是 with()
方法将此值添加到您的视图中,请记住以下几点:
return view('my_view', compact('users'));
然后您将一个关联数组传递给您的视图,因此为了访问关系中的值,您需要执行以下操作:
@foreach ($users as $user)
<h1> {{ $user['role']['name'] }} </h1>
@endforeach
串联
(按照您的方式操作)
到它在collections。在这里,我急于加载用户,但您不必这样做。不过,它将大大提高性能。请注意,由于您的设计选择,这是 3 个不同的查询,每个查询都执行一个连接。
$table1 = Table1::with('user')->all();
$table2 = Table2::with('user')->all();
$table3 = Table3::with('user')->all();
$tables = $table1->merge($table2)->merge($table3);
$tables = $tables->sortBy('create_at');
数据库和 OOP 设计
(这是你应该怎么做)
为什么要将它们分开 table?大多数人通常认为不规范化是糟糕的设计。如果两个 object 具有相同的 fields/members,则它们是 object.
的相同种类如果objects有相同的字段,它们应该是object的同一种类型,你应该为object的类型添加一个标志来获取。所以不用三个 table 和
- id
- user_id
- 描述
- updated_at
- created_at
你会有一个 table 字段:
- id
- user_id
- 描述
- 类型
- updated_at
- created_at
确保将 index
放在 type
上,这样 不会影响性能 将它们全部放在同一个 table .然后让它们全部按 created_at 排序(注意一个查询,一个连接):
$tables = Table::->orderBy('created_at')->with('user')->get();
要破解一个:
$table1 = Table::where('type','=',1)->with('user')->get();
$table2 = Table::where('type','=',2)->with('user')->get();
$table3 = Table::where('type','=',3)->with('user')->get();
全部搞定,打散:
$tables = Table::->orderBy('created_at')->with('user')->get()->groupBy('type');
如果 object 的 "types" 中的一个(或多个)有新字段,那么您将开始 inheritance。