Laravel birçok ilişkiye kaydetme / güncelleme


89

Biri birçok ilişkiyi nasıl kurtaracağım konusunda bana yardım edebilir mi? Görevlerim var, kullanıcının birçok görevi olabilir ve görev çok sayıda kullanıcıya sahip olabilir ( çoktan çoğa ), başarmak istediğim şey, güncelleme formunda yöneticinin birden fazla kullanıcıyı belirli bir göreve atayabilmesidir. Bu, html çoklu seçim girişi ile yapılır

name="taskParticipants[]"

Buradaki püf noktası, aynı form (giriş) aracılığıyla kullanıcı ekleyebileceğiniz / kaldırabileceğiniz, bu yüzden sync () kullanmam gerekiyor. Belki baştan başlamalıyım ama nereden başlayacağımı bilmiyorum ...

Bu benim Kullanıcı modelim:

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

Görev modeli

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));
        }
    }
}

Bu, tabloların yapısıdır görev kimliği | başlık | son tarih

user_tasks
id|task_id|user_id

Kodumu güncelledim. bağlantı
SuperManSL

4
$workers = Input::get('taskParticipants'); $task->taskParticipants()->sync($workers);ve bu formdan göreve atanan tüm kullanıcıları geçtiğiniz sürece ihtiyacınız olan tek şey bu.
Jarek Tkaczyk

@JarekTkaczyk Teşekkürler, Büyüleyiciydi.
Ryu_hayabusa

Yanıtlar:


200

tldr; sync2. param ile kullanınfalse


Çoktan çoğa ilişki belongsToManyher iki modelde de vardır:

// 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');
}

Yeni ilişki eklemek için attachveya kullanın sync.

İkisi arasındaki fark:

1 attach , pivot tabloya zaten orada olup olmadığını kontrol etmeden yeni satır ekleyecektir. Bu ilişkiyle bağlantılı ek verileriniz olduğunda iyidir, örneğin:

Userve Exampivot tablo ile bağlantılıattempts: id, user_id, exam_id, score

Sanırım bu senin durumunda ihtiyacın olan şey değil:

$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 diğer yandan, ya tüm ilişkileri kaldıracak ve yeniden kuracaktır:

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

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

veya önceki VE yinelenenleri eklemeden yeni ilişkiler kuracaktır:

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

8
Bunun API belgeleri yerine ana belgelerde belgelenmesi güzel olurdu! Devam et. +1.
ceejayoz

Senkron ve 2. parametre ile ikinci çözümü gerçekten çok seviyorum. Aşağıdaki yorumda da söylediğim gibi, detach'ı kullanmamayı göze alamam. Hikaye, yöneticinin kullanıcılara görev atayabilmesidir. Açılır listeden (çoklu) kullanıcı seçer, alan katılımcılardır []. Yani ...: Adım 1: yönetici A görevini üç kullanıcıya atar (yönteminiz çalışır, DB'de 3 kaydımız vardır) Adım 2: yönetici A görevini günceller ve iki kullanıcı ekler (yönteminiz çalışır, DB'de 5 kaydımız var) Adım 3: yönetici A görevini günceller ve 1 kullanıcıyı kaldırır (yönteminiz başarısız olur, 4 yerine 5 kullanıcımız var) güncelleme yöntemim kodum
SuperManSL

1
İlişki sorgunuzu sadece $this->belongsToMany('User')tabloyu alfabetik ve tekil olarak adlandırırsanız (yani task_useryerine user_tasks) basitleştirebilirsiniz
Kousha

@Rok, her zaman ilgili tüm kullanıcıların bir dizisini iletirseniz sync, endişelenmeden ayırma ile kullanın . idİlgili modelden birini geçtiğinizde 'bir kullanıcı için yeni görev eklemek' veya 'bir göreve kullanıcı atamak' istediğinizde 2. parametrenin yanlış olarak ayarlanmasını öneririm .
Jarek Tkaczyk

1
@FabioAntunes , ve listeleriyle syncbir dizi döndürür . hiçbir şey döndürmez, ancak her iki durumda da db çağrılarında beklenmedik bir şey olursa bir istisna elde edersiniz. detachedattachedupdatedattach
Jarek Tkaczyk

109

İşte tüm Eloquent ilişkilerinin nasıl kaydedileceği ve güncelleneceği ile ilgili notlarım.

içinde One One :

Sen kullanmak zorunda HasOne ilk modeli ve üzerinde belongsTo ikinci model üzerinde

ilk modele ( HasOne ) kayıt eklemek için kaydetme  işlevini kullanın

misal:    $post->comments()->save($comment);

ikinci modele kayıt eklemek için ( Aittir ) ilişkilendirme işlevini kullanın 

misal:    $user->account()->associate($account);    $user->save();


içinde birçok One :

Sen kullanmak zorunda hasMany ilk modeli ve üzerinde belongsTo ikinci model üzerinde

İlk tablo (üzerinde kaydı eklemek hasMany ) kullanan tasarrufu  veya saveMany fonksiyonları

misal:    $post->comments()->saveMany($comments);

ikinci modele kayıt eklemek için ( Aittir ) ilişkilendirme işlevini kullanın 

misal:    $user->account()->associate($account);    $user->save();


içinde birçok Çok :

İlk modelde OwnToMany ve ikinci modelde OwnToMany kullanmanız  gerekir .

pivot tabloya kayıt eklemek için ekleme veya senkronizasyon işlevlerini kullanın

  • her iki işlev de tek kimliği veya kimlik dizisini kabul eder 

  • fark, senkronizasyon yoksa kaydın pivot tabloda zaten mevcut olup olmadığını kontrol eder

misal: $user->roles()->attach($roleId);


içinde birçok üzere Polimorfik One :

Ana modelde  MorphMany'yi ve tüm (*** mümkün) modellerde MorphTo'yu kullanmanız  gerekir

diğer tüm modellere kayıt eklemek için kaydetmeyi kullanın 

misal:    $course->tags()->save($tag);

pivot tablo aşağıdaki sütunlara sahip olmalıdır:

. ana model kimliği

. (*** mümkün) kimliği

. (*** mümkün) Tür


içinde Polimorfik Birçok Çok :

Ana modelde  MorphByMany'yi ve tüm (*** mümkün) modellerde MorphToMany'yi kullanmanız  gerekir

diğer tüm modellere kayıt eklemek için kaydetme veya kaydetme işlevini kullanın

misal:    $course->tags()->save($tag);

misal:    $course->tags()->saveMany([$tag_1, $tag_2, $tag_3]);

pivot tablo aşağıdaki sütunlara sahip olmalıdır:

. ana model kimliği

. (*** mümkün) kimliği

. (*** mümkün) Tür


içinde birçok yoluyla Has (kısayol):

İlk masada HasManyThrough kullanmalı ve diğer 2 tabloda normal ilişkilere sahip olmalısınız .

bu ManyToMany ilişkileri için çalışmaz (pivot tablonun olduğu yerlerde)

ancak bunun için güzel ve kolay bir çözüm var.


İşte bu cevaptan esinlenerek yazdığım bir makale. Kontrol etmek önemlidir: https://hackernoon.com/eloquent-relationships-cheat-sheet-5155498c209


Aslında bu cevabı doğru cevaba zaten 40'tan fazla beğeni aldıklarında vermiştim, ama evet bunun benim için ne kadar yararlı olduğunu biliyorum, beğendiğine sevindim :)
Mahmoud Zalt

1
Bir kurtarıcı olduğunuzu bilmenizi dilerim
Chay22

1
bu harika bir cevap.
caro

1
bir mayıs ilişkisine nasıl güncellenir. nasıl ekleneceğini açıkladınız. lütfen güncellemeyi de açıklar mısınız? bunun gibi kayıtları güncellemenin bir yöntemi updateManyvar mı? teşekkürler
Hamidreza

4

syncWithoutDetaching([$id_one, $id_two, $id_three]);aradığınız şey. Aslında [ sync2. param ile false] aynı şeyi yapar!


0

syncFonksiyon çıkan ilişkiler obliterates ve dizinizi ilişkilerinin bütün liste yapar. Bunun attachyerine başkalarını kaldırmadan ilişki eklemek istersiniz .


Eklemeyi kullanamıyorum çünkü bu kodu güncelleme yönteminde kullanıyorum. Hikaye, yöneticinin görevi güncelleyebilmesi ve giriş katılımcılarını [] göreve katılacak kullanıcılarla doldurabilmesidir. Bu yüzden var olup olmadığını kontrol etmem ve silmem (veya yeni kayıt eklememem) veya yoksa eklemem gerekiyor.
SuperManSL
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.