Laravel บันทึก / อัปเดตหลาย ๆ ความสัมพันธ์


89

ใครสามารถช่วยฉันเกี่ยวกับวิธีการรักษาความสัมพันธ์หลาย ๆ คน? ฉันมีงานผู้ใช้สามารถมีงานหลายอย่างและงานสามารถมีผู้ใช้หลายคน (หลายคนถึงหลายคน) สิ่งที่ฉันต้องการบรรลุคือในการอัปเดตผู้ดูแลระบบสามารถกำหนดผู้ใช้หลายคนให้กับงานเฉพาะได้ สิ่งนี้ทำได้ผ่าน html อินพุตที่เลือกหลายรายการ

name="taskParticipants[]"

สิ่งที่จับได้คือด้วยรูปแบบเดียวกัน (อินพุต) ที่คุณสามารถเพิ่ม / ลบผู้ใช้ได้นั่นคือเหตุผลที่ฉันต้องใช้ sync () บางทีฉันควรเริ่มจากจุดเริ่มต้น แต่ไม่รู้จะเริ่มตรงไหน ...

นี่คือรูปแบบผู้ใช้ของฉัน:

public function tasks()
{
    return $this->belongsToMany('Task','user_tasks');
}

รูปแบบงาน

public function taskParticipants()
{
    return $this->belongsToMany('User','user_tasks');
}

TaskController

public function update($task_id)
{
    if (Input::has('taskParticipants'))
    {
        foreach(Input::get('taskParticipants') as $worker)
        {
            $task2 = $task->taskParticipants->toArray();
            $task2 = array_add($task2,$task_id,$worker);
            $task->taskParticipants()->sync(array($task2));
        }
    }
}

นี่คือโครงสร้างของ รหัสงานตาราง | ชื่อเรื่อง | กำหนดเวลา

user_tasks
id|task_id|user_id

ฉันได้อัปเดตรหัสของฉันแล้ว ลิงค์
SuperManSL

4
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);และนั่นคือทั้งหมดที่คุณต้องการตราบเท่าที่คุณผ่านจากรูปแบบนั้นผู้ใช้ทั้งหมดที่มอบหมายให้กับงาน
Jarek Tkaczyk

@JarekTkaczyk ขอบคุณมันวิเศษมาก
Ryu_hayabusa

คำตอบ:


201

tldr; ใช้syncกับพาราตัวที่ 2false


ความสัมพันธ์แบบกลุ่มbelongsToManyต่อกลุ่มอยู่ในทั้งสองรุ่น:

// Task model
public function users()
{
  return $this->belongsToMany('User', 'user_tasks'); // assuming user_id and task_id as fk
}

// User model
public function tasks()
{
  return $this->belongsToMany('Task', 'user_tasks');
}

เพื่อเพิ่มความสัมพันธ์ใหม่ใช้attachหรือsync.

ความแตกต่างระหว่างทั้งสองคือ:

1 attachจะเพิ่มแถวใหม่ในตาราง Pivot โดยไม่ตรวจสอบว่ามีอยู่แล้วหรือไม่ เป็นการดีเมื่อคุณมีข้อมูลเพิ่มเติมที่เชื่อมโยงกับความสัมพันธ์นั้นเช่น:

UserและExamเชื่อมโยงกับตาราง Pivotattempts: id, user_id, exam_id, score

ฉันคิดว่านี่ไม่ใช่สิ่งที่คุณต้องการในสถานการณ์ของคุณ:

$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]

$user->tasks()->attach([5,6,7]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,5,6,7]

2 syncบนมืออื่น ๆ ที่อาจจะลบความสัมพันธ์และพวกเขาตั้งขึ้นใหม่:

$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6]

$user->tasks()->sync([1,2,3]);
// then
$user->tasks()->getRelatedIds(); // [1,2,3]

หรือจะตั้งค่าความสัมพันธ์ใหม่โดยไม่แยก AND ก่อนหน้านี้โดยไม่ต้องเพิ่มรายการที่ซ้ำกัน:

$user->tasks()->sync([5,6,7,8], false); // 2nd param = detach
// then
$user->tasks()->getRelatedIds(); // [1,2,3,4,5,6,7,8]

8
คงจะดีไม่น้อยหากมีการบันทึกไว้ในเอกสารหลักแทนที่จะเป็นเอกสาร API! ร็อค +1.
ceejayoz

ฉันชอบโซลูชันที่สองที่มีพารามิเตอร์ sync และ 2nd มาก อย่างที่ฉันพูดในการแสดงความคิดเห็นฉันไม่สามารถที่จะไม่ใช้การถอดออกได้ เรื่องคือ admin สามารถมอบหมายงานให้กับผู้ใช้ได้ เขาเลือกผู้ใช้จากรายการแบบเลื่อนลง (หลายรายการ) ฟิลด์คือผู้เข้าร่วม [] ดังนั้น ... : ขั้นตอนที่ 1: ผู้ดูแลระบบมอบหมายงาน A ให้กับผู้ใช้สามคน (วิธีการของคุณใช้ได้ผลเรามี 3 ระเบียนใน DB) ขั้นตอนที่ 2: ผู้ดูแลระบบอัปเดตงาน A และเพิ่มผู้ใช้สองคน (วิธีของคุณใช้ได้ผลเรามี 5 ระเบียนใน DB) ขั้นตอนที่ 3: ผู้ดูแลระบบอัปเดตงาน A และลบผู้ใช้ 1 คน (วิธีของคุณล้มเหลวเรายังมีผู้ใช้ 5 คนแทนที่จะเป็น 4) วิธีการอัปเดตรหัสของฉัน
SuperManSL

1
คุณสามารถลดความซับซ้อนของแบบสอบถามความสัมพันธ์ของคุณเพียงแค่$this->belongsToMany('User')ถ้าคุณใช้ชื่อตารางตามตัวอักษรและเอกพจน์ ( task_userแทนuser_tasks)
Kousha

@Rok หากคุณส่งอาร์เรย์ของผู้ใช้ที่เกี่ยวข้องทั้งหมดให้ใช้syncโดยไม่ต้องกังวล ฉันขอแนะนำให้ใช้พารามิเตอร์ชุดที่ 2 เป็นเท็จเมื่อใดก็ตามที่คุณต้องการ "เพิ่มงานใหม่สำหรับผู้ใช้" หรือ "กำหนดผู้ใช้ให้กับงาน" เมื่อคุณส่งผ่านidโมเดลที่เกี่ยวข้องเพียงรายการเดียว
Jarek Tkaczyk

1
@FabioAntunes syncส่งกลับอาร์เรย์ที่มีdetached, attachedและupdatedรายการ attachไม่ส่งคืนอะไรเลย แต่ในทั้งสองกรณีคุณจะได้รับข้อยกเว้นหากมีสิ่งที่ไม่คาดคิดเกิดขึ้นในการโทร db
Jarek Tkaczyk

109

นี่คือบันทึกย่อของฉันเกี่ยวกับวิธีการบันทึกและอัปเดตความสัมพันธ์ Eloquent ทั้งหมด

ในหนึ่งต่อหนึ่ง :

คุณต้องใช้HasOneในรุ่นแรกและBelongsToในรุ่นที่สอง

ในการเพิ่มบันทึกในรุ่นแรก ( HasOne ) ให้ใช้ ฟังก์ชันบันทึก

ตัวอย่าง:    $post->comments()->save($comment);

ในการเพิ่มบันทึกในรุ่นที่สอง ( BelongsTo ) ให้ใช้  ฟังก์ชันการเชื่อมโยง

ตัวอย่าง:    $user->account()->associate($account);    $user->save();


ในหนึ่งถึงหลาย :

คุณต้องใช้HasManyในรุ่นแรกและรุ่นBelongsToในรุ่นที่สอง

เพื่อเพิ่มเรกคอร์ดในตารางแรก ( HasMany ) ให้ใช้ฟังก์ชันsave  หรือsaveMany

ตัวอย่าง:    $post->comments()->saveMany($comments);

ในการเพิ่มบันทึกในรุ่นที่สอง ( BelongsTo ) ให้ใช้  ฟังก์ชันการเชื่อมโยง

ตัวอย่าง:    $user->account()->associate($account);    $user->save();


ในหลายต่อหลาย :

คุณต้องใช้  BelongsToManyในรุ่นแรกและBelongsToManyในรุ่นที่สอง

ในการเพิ่มระเบียนบนตาราง Pivot ให้ใช้ฟังก์ชันแนบหรือซิงค์

  • ทั้งสองฟังก์ชั่นยอมรับ ID เดียวหรืออาร์เรย์ของ ID 

  • ความแตกต่างคือการแนบตรวจสอบว่ามีเรกคอร์ดอยู่แล้วในตาราง Pivot หรือไม่ในขณะที่ไม่ซิงค์

ตัวอย่าง: $user->roles()->attach($roleId);


ในPolymorphic One to Many :

คุณต้องใช้  MorphManyในโมเดลหลักและ  MorphToในทุกรุ่น (*** สามารถ)

เพื่อเพิ่มบันทึกในรุ่นอื่น ๆ ทั้งหมดให้ใช้การ  บันทึก

ตัวอย่าง:    $course->tags()->save($tag);

ตาราง Pivot ควรมีคอลัมน์ต่อไปนี้:

. รหัสรุ่นหลัก

. (*** สามารถ) ID

. (*** สามารถ) พิมพ์


ในPolymorphic Many to Many :

คุณต้องใช้  MorphByManyในโมเดลหลักและ  MorphToManyในทุกรุ่น (*** สามารถ)

ในการเพิ่มบันทึกในรุ่นอื่น ๆ ทั้งหมดให้ใช้การบันทึกหรือsaveMany

ตัวอย่าง:    $course->tags()->save($tag);

ตัวอย่าง:    $course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);

ตาราง Pivot ควรมีคอลัมน์ต่อไปนี้:

. รหัสรุ่นหลัก

. (*** สามารถ) ID

. (*** สามารถ) พิมพ์


ในHas Many Through (ทางลัด):

คุณต้องใช้HasManyThroughบนตารางแรกและมีความสัมพันธ์ปกติกับอีก 2 ตาราง

สิ่งนี้ใช้ไม่ได้กับความสัมพันธ์ManyToMany (โดยที่มีตาราง Pivot)

อย่างไรก็ตามมีทางออกที่ดีและง่ายสำหรับสิ่งนั้น


นี่คือบทความที่ฉันเขียนโดยได้รับแรงบันดาลใจจากคำตอบนี้ สิ่งสำคัญในการตรวจสอบ: https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209


ฉันวางคำตอบนี้ไว้จริงๆแล้วเมื่อพวกเขามีมากกว่า 40
ไลค์

1
ฉันขอให้คุณรู้ว่าคุณเป็นผู้ช่วยให้รอด
Chay22

1
นี่คือคำตอบที่ดี
caro

1
วิธีการอัปเดตความสัมพันธ์ คุณอธิบายวิธีการเพิ่ม คุณช่วยอธิบายการอัปเดตด้วยได้ไหม มีวิธีการอัปเดตระเบียนupdateManyเช่นนั้นหรือไม่? ขอบคุณ
Hamidreza

4

syncWithoutDetaching([$id_one, $id_two, $id_three]);คือสิ่งที่คุณกำลังมองหา จริงๆแล้วมันทำสิ่งที่แน่นอน [ syncด้วยพารามิเตอร์ที่ 2 false]!


0

syncฟังก์ชั่น obliterates ความสัมพันธ์ออกและทำให้อาร์เรย์ของรายชื่อทั้งหมดของความสัมพันธ์ คุณต้องการattachเพิ่มความสัมพันธ์โดยไม่ต้องลบผู้อื่นออก


ฉันไม่สามารถใช้ไฟล์แนบได้เนื่องจากฉันใช้รหัสนี้ในวิธีอัปเดต เรื่องราวคือผู้ดูแลระบบสามารถอัปเดตงานและกรอกข้อมูลผู้เข้าร่วม [] กับผู้ใช้ที่จะเข้าร่วมในงาน ดังนั้นฉันต้องตรวจสอบว่ามีอยู่หรือไม่และลบ (หรือไม่เพื่อเพิ่มระเบียนใหม่) หรือถ้าไม่มีให้เพิ่ม
SuperManSL
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.