2015-09-10 13 views
5

A User ma jeden (lub zero) Company, a Company należy do jednego i tylko jednego User. Próbuję zapisać firmę dla użytkownika, ale dodaje ona nowy wpis do bazy danych za każdym razem, gdy ponownie uruchomię metodę składowania. Jest to relacja jeden do jednego, więc ja na przykład save metoda na metoda na User.Zapisywanie relacji jeden do jednego w Laravel

Więc Company ma jedną metodę user():

public function user() { 
    return $this->belongsTo(User::class, 'user_id'); 
} 

I User ma jedną metodę company():

public function company() { 
    return $this->hasOne(Company::class, 'user_id'); 
} 

próbuję zapisać (tak utworzenia lub aktualizacji) firmę użytkownika tak (w sterowniku):

$company = new Company(); 
$company->name = 'Test'; 
User::findOrFail(1)->company()->save($company); 

Po raz pierwszy uruchomię ten kod, który tworzy wpis w bazie danych (OK), ale drugi raz dodaje nowy wpis dla tego samego użytkownika (Nie OK). Myślałem, że zaktualizuje tylko wpis w bazie danych.

Czy to błąd (lub coś, czego nie rozumiem w relacji jeden do jednego) w Laravel lub czy robię coś nie tak? (myślę i mam nadzieję, że to drugi cel)

+0

Sprawdź tę odpowiedź, to może pomóc: http://stackoverflow.com/a/20764237/5122070 –

+0

Dzięki, ale nie jestem pewien, że to naprawdę pomaga do tego konkretnego problemu. Mój problem jest bardziej szczegółowy. Chodzi o zapisywanie (tworzenie lub aktualizowanie) bezpośrednio w relacji –

Odpowiedz

8

Tworzenie i aktualizowanie trzeba traktować inaczej. Najpierw sprawdź istnienie atrybutu firmy.

$user = User::with('company')->findOrFail(1); 
if ($user->company === null) 
{ 
    $company = new Company(['name' => 'Test']); 
    $user->company()->save($company); 
} 
else 
{ 
    $user->company->update(['name' => 'Test']); 
} 

Zauważ, że hasOne() nie gwarantuje, że będziesz miał jeden-do-jeden związek, to po prostu informacją wymowny sposób tworzenia kwerendy. Działa nawet ty masz wiele Company odnoszą się do tego samego User, w takim przypadku, gdy zadzwonisz $user->company otrzymasz pierwszy Company w zestawie danych wyników z bazy danych.

+0

Ok dzięki. "Zauważ, że hasOne() nie gwarantuje, że będziesz mieć relację jeden-do-jednego, po prostu mówi Epokaże jak utworzyć zapytanie" -> Bardzo pomocne, Teraz jest wystarczająco jasne. –

0

robisz źle tutaj

$company = new Company(); 
$company->name = 'Test'; 
User::findOrFail(1)->company()->save($company); 

Nie mówią którym wiersz zaktualizować

Więc twój kod musi być zmodyfikowane w ten sposób:

$companyId jest firma zaktualizować

$company = new Company(); 
$company->name = 'Test'; 
User::findOrFail(1)->company()->find($companyId)->save($company); 
+0

Ale nie znam identyfikatora firmy w tym momencie, chcę tylko zaktualizować wartości firmy dla jednego użytkownika (bez konieczności dbania o możliwą poprzednią). Maby to niemożliwe, ale wydaje się to dziwne, że 'save()' nie dba o typ relacji (tutaj, jest harcoded na jeden do jednego) –

+0

@ rap-2-h masz formularz, w którym przekazujesz informacje o firmie.Jeśli użytkownik ma informacje o firmie, to będzie identyfikator, jeśli nie, to zostawiłeś id, aby opróżnić, a kiedy umieścisz formularz, otrzymasz identyfikator. Teraz, jeśli istnieje wartość id, którą znajdziesz i zaktualizujesz lub wstawisz. –

+0

Ok dzięki. Wiem, że jest to rozwiązanie polegające na użyciu ukrytego pola w formularzu, ale moje pytanie brzmi: czy powinniśmy robić takie rzeczy? Laravel wie, że może to być tylko jedna firma dla jednego użytkownika, więc dlaczego dodaje nową firmę, gdy ją zapisuję. Wydaje się dziwne (jakby nie szanowało tego, co jest zadeklarowane), więc myślę, że robię złą drogę. –

4
$user = User::findOrFail(1); 
$company = $user->company ?: new Company; 
$company->name = 'Test'; 
$user->company()->save($company); 
+0

Podobnie w ten sposób! Szybko i czysto! +1 :) –

Powiązane problemy