如何在处理 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 个实体的结果:directorteacherstudent,所有这三个实体都具有关系 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