Красноречивый: Как синхронизировать отношения один-ко-многим, не удаляя ничего (FK обнуляется)? - PullRequest
0 голосов
/ 18 октября 2018

В филиале может быть ноль (*) или только один план отдыха.План праздника может быть «привязан» (присоединен) к нулю или множеству ветвей.

(*) это очень важно: это Foreign Key, которое может быть null

enter image description here

Модель

Вот мой Branch Модель:

class Branch extends Model
{
    protected $table = 'branch';
    protected $fillable = ['name', 'holiday_plan_id'];
    public $timestamps = false;

    public function holidayPlan()
    {
        return $this->hasOne('App\HolidayPlan', 'id', 'holiday_plan_id');
    }
}

А вот иmy HolidayPlan Модель:

class HolidayPlan extends Model
{
    protected $table = 'holiday_plan';
    protected $fillable = ['name'];
    public $timestamps = false;

    public function branches()
    {
        return $this->hasMany('App\Branch', 'holiday_plan_id', 'id');
    }
}

Просмотр

Теперь я хочу связать / отменить привязку плана праздника к различным филиалам

$branches = Branch::all();
$plan = HolidayPlan::find(1);

@foreach($branches as $branch)
<label>
    <input type="checkbox" name="branch[]"
        value="{{ $branch->id }}"{{ ($branch->holiday_plan_id == $plan->id) ? ' checked' : '' }}>
    {{ $branch->name }}
</label>
@endforeach

Контроллер

public function linkBranches($planId, Request $request) // post
{
    $plan = HolidayPlan::where('id', $planId)->first();
    $branches = Branch::findMany($request->input('branch'));
    //
    $this->solution1($plan, $branches); // see next
    //
    return redirect()->back();
}

Возможные решения (не работают)

private function solution1(HolidayPlan $plan, $branches)
{
    $plan->branches()->sync($branches); // Not working because this function is for Many-to-Many relations
}

private function solution2(HolidayPlan $plan, $branches)
{
    $plan->branches()->delete(); // This will delete my branches, which is not what I want to do, of course
    $plan->branches()->saveMany($branches);
}

private function solution3(HolidayPlan $plan, $branches)
{
    foreach($plan->branches as $branch) {
        $branch->holiday_plan_id = null;
        $branch->save();
    }
    $plan->branches()->saveMany($branches); // Not working; I don't know why: strange behavior. Maybe because of locks; I'm not sure. One time it detaches all branches, and only next time it attaches them again.
}

Наконец

На самом деле, необработанный SQL будет выглядеть следующим образом:

UPDATE branch SET holiday_plan_id = NULL WHERE holiday_plan_id = 1;
UPDATE branch SET holiday_plan_id = 1 WHERE branch.id IN (2, 5, 7)/* for example */;

Но как это сделать с помощью функций и отношений Eloquent (без использования sql)?


Редактировать

Я отредактировал свои Branch модельные отношения, однако solution3 все еще не работает (когда я пытаюсь добавить уже существующий holiday_plan_id, он не добавляет его = он становится нулевым):

public function holidayPlan()
{
    return $this->belongsTo('App\HolidayPlan', 'holiday_plan_id');
}

1 Ответ

0 голосов
/ 18 октября 2018

Временное решение:

public function solution4(HolidayPlan $plan, $inputBranches)
{
    $oldLinks = $plan->branches;
    $plan->branches()->saveMany($inputBranches);
    foreach ($oldLinks as $oldLink) {
        if (! $inputBranches->contains($oldLink)) {
            $oldLink->holiday_plan_id = null;
            $oldLink->save();
        }
    }
}
...