PHP项目Laravel关联更新与批量赋值

wen PHP项目 3

Laravel 关联更新与批量赋值详解

基础关联更新

一对多关联更新

// 基本关联更新
$user = User::find(1);
$user->posts()->update(['status' => 'published']);
// 带条件更新
$user->posts()->where('status', 'draft')
              ->update(['published_at' => now()]);

多对多关联更新(中间表)

$user = User::find(1);
// 附加角色(带中间表数据)
$user->roles()->attach($roleId, ['expires_at' => now()->addMonth()]);
// 更新中间表数据
$user->roles()->updateExistingPivot($roleId, [
    'expires_at' => now()->addMonths(6),
    'status' => 'active'
]);
// 同步关联(只保留给定的ID)
$user->roles()->sync([
    1 => ['status' => 'active'],
    2 => ['status' => 'inactive'],
]);

关联模型批量赋值(create)

安全批量赋值

// 定义模型填充规则
class Post extends Model
{
    protected $fillable = ['title', 'content', 'user_id'];
    // 或使用不可填充
    // protected $guarded = ['id', 'is_admin'];
}
// 通过关联创建
$user = User::find(1);
$post = $user->posts()->create([ => '新文章',
    'content' => '内容...'
]);
// 批量创建
$postsData = [
    ['title' => '文章1', 'content' => '内容1'],
    ['title' => '文章2', 'content' => '内容2'],
];
$user->posts()->createMany($postsData);

批量赋值限制规则

class User extends Model
{
    // 可批量赋值的字段
    protected $fillable = ['name', 'email', 'password'];
    // 或排除不可填充字段
    protected $guarded = ['id', 'is_admin'];
    // 自定义赋值逻辑
    public function setPasswordAttribute($value)
    {
        $this->attributes['password'] = bcrypt($value);
    }
}

高级关联更新技巧

使用关联事件

// 模型事件
class User extends Model
{
    protected static function booted()
    {
        static::updating(function ($user) {
            // 更新前的逻辑
            Log::info('用户信息更新', $user->getDirty());
        });
        static::updated(function ($user) {
            // 更新后触发关联更新
            $user->posts()->update(['cached_user_name' => $user->name]);
        });
    }
}

关联更新嵌套

// 手动事务处理
DB::transaction(function () {
    $user = User::find(1);
    // 更新主模型
    $user->update([
        'name' => '新名字',
        'email' => 'new@email.com'
    ]);
    // 更新关联模型
    $user->posts()->update(['author_name' => '新名字']);
    $user->profile()->update(['bio' => '新简介']);
    // 同步关联并更新中间表
    $user->roles()->sync([
        1 => ['status' => 'active', 'updated_at' => now()],
        2 => ['status' => 'inactive']
    ]);
});
// 使用宽松更新中跳过验证
$user->posts()->get()->each(function ($post) {
    $post->category_id = 1;
    $post->save(['timestamps' => false]);
});

前端批量赋值防护

使用FormRequest验证

class UpdateUserRequest extends FormRequest
{
    public function authorize()
    {
        return $this->user()->can('update', $this->user);
    }
    public function rules()
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email,' . $this->user->id,
            'password' => 'nullable|string|min:8',
            'roles' => 'array|exists:roles,id'
        ];
    }
    public function messages()
    {
        return [
            'name.required' => '姓名不能为空',
            'email.email' => '邮箱格式不正确'
        ];
    }
}
// 控制器中使用
public function update(User $user, UpdateUserRequest $request)
{
    $user->update($request->validated());
    // 更新关联角色
    if ($request->has('roles')) {
        $user->roles()->sync($request->roles);
    }
    return redirect()->route('users.show', $user);
}

JSON字段批量赋值

class Post extends Model
{
    protected $casts = [
        'meta' => 'array',
        'tags' => 'json'
    ];
    protected $fillable = ['title', 'content', 'meta', 'tags'];
}
// 更新JSON字段
$user->posts()->where('id', 1)->update([
    'meta->views' => 100,
    'meta->likes' => 50
]);
// 使用JSON更新
$user->posts->each(function ($post) {
    $post->update([
        'meta' => array_merge($post->meta, ['shared' => true])
    ]);
});

性能优化建议

// 批量更新而不是循环
// 不推荐
$user->posts->each(function ($post) {
    $post->status = 'published';
    $post->save();
});
// 推荐
$user->posts()->where('draft', true)
              ->update(['status' => 'published']);
// 选择性加载关联数据
$users = User::with(['posts' => function ($query) {
    $query->select('id', 'title', 'status')
          ->where('status', 'active');
}])->get();

这些方法覆盖了 Laravel 中关联更新的主要场景,根据实际需求选择合适的方式,记得在处理大量数据时考虑性能影响。

PHP项目Laravel关联更新与批量赋值

抱歉,评论功能暂时关闭!