接着要来给 Todo 加上与 User 的关联,区分各 User 建立的 Todo。
一个 User 拥有多个 Todo ,所以是一对多的关联。
跟前面一样先建立 migration 帮 Todo 加上 user_id 栏位。
sail artisan make:migration update_todo_relate_user --table todos
/database/migrations/2021_10_01_105954_update_todo_relate_user.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateTodoRelateUser extends Migration
{
public function up()
{
Schema::table('todos', function (Blueprint $table) {
// 加上 user_id
$table->unsignedBigInteger('user_id');
});
}
public function down()
{
Schema::table('todos', function (Blueprint $table) {
$table->dropColumn('user_id');
});
}
}
接着在 User Model 中加入关联
/app/Models/User.php
@@ -9,6 +9,7 @@ use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\UserSetting;
+use App\Models\Todo;
class User extends Authenticatable
{
@@ -50,4 +51,9 @@ class User extends Authenticatable
{
return $this->hasOne(UserSetting::class);
}
+
+ public function todos()
+ {
+ return $this->hasMany(Todo::class);
+ }
}
写法跟一对一关联相同,只是改成 hasMany 方法,简单明了。
如果想要更改关联栏位名称,写法与 hasOne 相同。
hasMany(<模型名称>,<目标模型的外键名称>,<模型关联键名称>)
至於从 Todo 反查询一对多关联的方法一样是 belongsTo
/app/Models/Todo.php
@@ -4,6 +4,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
+use App\Models\User;
class Todo extends Model
{
@@ -12,4 +13,9 @@ class Todo extends Model
protected $fillable = [
'name',
];
+
+ public function user()
+ {
+ return $this->belongsTo(User::class);
+ }
}
接着要让 Todo 资料在新增的同时归属於 User ,要改写 TodoController 的 store 方法。
/app/Http/Controllers/TodoController.php
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\Todo;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
class TodoController extends Controller
{
@@ -39,13 +40,15 @@ class TodoController extends Controller
*/
public function store(Request $request)
{
$data = $request->all();
$todo = new Todo;
$todo->name = $data['name'];
- $todo->save();
+ $user = Auth::user();
+ $user->todos()->save($todo);
}
原本 $todo->save() 的方法改为先用 $user->todos() 建立关联的 Query Builder 後再 save ,这样新建的 todo 就会自动带入 user_id 的资料。
也可以直接用 create() 建立,都是 Query Builder 的应用可以视情况使用。
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
use App\Models\Todo;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
class TodoController extends Controller
{
@@ -39,13 +40,12 @@ class TodoController extends Controller
*/
public function store(Request $request)
{
$data = $request->all();
- $todo = new Todo;
- $todo->name = $data['name'];
- $todo->save();
+ $user = Auth::user();
+ $user->todos()->create([
+ 'name' => $data['name'],
+ ]);
}
save 或是 create 方法都有批量新增的版本,可以一次建立多笔关联资料
$user->todos()->saveMany([
new Todo(['name' => 'todo 1']),
new Todo(['name' => 'todo 2']),
]);
$user->todos()->createMany([
['name' => 'todo 1'],
['name' => 'todo 2'],
]);
读取的方式跟一对一关联时相同
$user->todos
所以来改写 TodoController 的 index 方法,变成只回传登入用户的 todos
@@ -13,11 +14,9 @@ class TodoController extends Controller
* @return \Illuminate\Http\Response
*/
public function index()
- {
- $todos = Todo::get();
-
+ {
return inertia('Dashboard', [
- 'todos' => $todos,
+ 'todos' => Auth::user()->todos,
]);
}
这样就好了,可以试试不同帐号的画面上会显示不同的 todo 清单。
目前介绍了一对一,一对多的建立关联资料方法,一般使用情况下关联资料建立後就不会再变更所属了,最多就是编辑资料。
不过偶尔会有需要移除关联或是改变所属的状况,这边先介绍一对一跟一对多情况的写法,两者是相同的,之後多对多的写法另外介绍。
移除关联表示将资料中的外键清除,这样查询关联时就不会再查到他了,不过资料本身还是保留的。
首先要注意如果允许资料可以没有关联的话,在 Migration 时要将外键设定成 nullable,不然清除外键的时候会抵触资料库设定然後报错。
$table->unsignedBigInteger('user_id')->nullable(); //允许没有关联
$table->foreign('user_id')->references('id')->on('users');
然後,会由 belongsTo 的那一方发起移除关联,使用的是 dissociate 方法。
$todo->user()->dissociate();
$todo->save();
因为一对一跟一对多关联中从属的那一方都是用 belongsTo 方法,所以两者都可以用 dissociate 移除关联。
跟移除关联相同,变更关联也是由 belongsTo 那一方的 Model 发起变更,使用 associate 方法。
$todo = Todo::find(1);
$todo->user()->associate($user);
$todo->save();
不管 todo 原先有没有所属都会被更新所属的 user 。
<<: [Day18]程序菜鸟自学C++资料结构演算法 – 线性搜寻法(Linear Search)与二分搜寻法(Half-Interval Search)
>>: Day 27:专案07 - 天气小助理01 | 气象资料API
完全参考,此处为整理笔记 [有趣面试题] 网页效能问题改善之 Debounce & Thro...
Metrics - 观察系统的健康指标 系列文章 (1/6) - Metrics 与 Metricb...
这其实是遇到无法用大量汇入~ 却又想要将指定资料表汇入到另一个资料库的SQL方式@@ 因为在独立环境...
因为之後要用到,今天就简单阅读了这个, 投影片和内容都是来自台大李弘毅教授的youtube http...
元件介绍 Skeleton 是一个骨架载入元件(Skeleton Screen Loading),跟...