Pytanie Wymowne relacje - dołącz (ale nie oszczędzaj) do wielu


Mam ustawione następujące relacje:

class Page {
    public function comments() {
        return $this->hasMany('Comment');
    }
}

class Comment {
    public function page() {
        return $this->belongsTo('Page');
    }
}

Dość bogaty standard. Jedna strona może zawierać wiele komentarzy, a jeden komentarz należy do jednej strony.

Chciałbym móc utworzyć nową stronę:

$page = new Page;

i komentarz

$comment = new Comment;

i dołącz komentarz do strony, bez zapisywania tego

$page->comments->associate($comment);

Próbowałem następujące:

// These are for one-to-many from the MANY side (eg. $comment->page->associate...)
$page->comments->associate($comment);   // Call to undefined method Illuminate\Database\Eloquent\Collection::associate()
$page->comments()->associate($comment); // Call to undefined method Illuminate\Database\Query\Builder::associate()

// These 2 are for many-to-many relations, so don't work
$page->comments->attach($comment);      // Call to undefined method Illuminate\Database\Eloquent\Collection::attach()
$page->comments()->attach($comment);    // Call to undefined method Illuminate\Database\Query\Builder::attach()

// These 2 will (if successful) save to the DB, which I don't want
$page->comments->save($comment);        // Call to undefined method Illuminate\Database\Eloquent\Collection::save()
$page->comments()->save($comment);      // Integrity constraint violation: 1048 Column 'page_id' cannot be null

Naprawdę dziwne jest to, że działanie odwrotne (dołączanie strony do komentarza) działa poprawnie:

$comment->page()->associate($page);

Odpowiednie dokumenty są tutaj ale nie wspominają o dołączaniu do JEDNEJ strony jednego do wielu. Czy to możliwe? (Czuję, że tak powinno być)


16
2018-05-30 09:28


pochodzenie




Odpowiedzi:


Wygląda na to, że chcesz tylko dodać nowy komentarz do kolekcji komentarzy strony - możesz to zrobić w prosty sposób, korzystając z podstawowej metody dodawania kolekcji:

$page = new Page;
$comment = new Comment;
$page->comments->add($comment);

20
2018-05-30 11:57



Idealnie, robi dokładnie to, czego potrzebowałem :) Dzięki - Joe
Jak zapisać później komentarze? - Boedy
@Boedy To osobne pytanie - chodzi tylko o obiekty, które nie są powiązane z bazą danych. Jeśli chcesz zapisać komentarz, musisz najpierw zapisać stronę, a następnie użyć metody> save (), aby je połączyć. To, co robię, nie połączy ich w bazie danych, ponieważ nie mają identyfikatorów; po prostu dodaje obiekt komentarza do kolekcji. - Benubird
Stwierdzając tutaj oczywistość ... należy pamiętać, że wywołanie comments własność w $page uruchomi zapytanie w bazie danych, więc może być wolniejsze niż oczekiwane. - edpaez
Powinieneś także móc użyć $ page-> push (), aby zapisać stronę i wszystkie powiązane komentarze, zamiast zapisywać każdą z nich osobno. - rich remer


Nie możesz tego zrobić, ponieważ nie ma identyfikatorów do połączenia.

Najpierw musisz zapisać rodzica ($page), a następnie zapisz model potomny:

// $page is existing model, $comment don't need to be
$page->comments()->save($comment); // saves the comment

lub odwrotnie, tym razem bez zapisywania:

// again $page exists, $comment don't need to
$comment->page()->associate($page); // doesn't save the comment yet
$comment->save();

6
2018-05-30 10:05



To ma sens, ale jeśli to zrobię $comment->page()->associate($page) następnie dołącza go poprawnie, mimo że strona nie ma identyfikatora - Joe
Nie, nie generuje żadnego błędu, ale nie kojarzy go poprawnie. W rzeczywistości to ustawia page_id do null, ponieważ, jak powiedziałeś, nie ma identyfikatora $pageobiekt. - Jarek Tkaczyk
Nie, kojarzy się poprawnie. The page_id jest rzeczywiście zerowy, ale tablica relacji jest wypełniona - dd($comment) drukuje to: grab.by/xksA - Joe
Nie nazwałbym tego poprawnym, gdyby się nie udało. W rzeczywistości powinien istnieć jakiś błąd, ale Eloquent nie zapewnia żadnych przy tej okazji. - Jarek Tkaczyk
Nie zawiedzie :) Identyfikator strony jest null więc ustawia $background->page_id do wartości null. Następnie dodaje Page w relację. To wszystko ma sens i jest poprawne, nie zawodzi - Joe


według Benubirda chciałem tylko dodać coś, co natknąłem się na to dzisiaj:

Możesz wywołać metodę dodawania w kolekcji takiej jak Benubird. Aby wziąć pod uwagę obawy edpaaz (dodatkowe wystrzelone zapytanie), zrobiłem to:

$collection = $page->comments()->getEager(); // Will return the eager collection
$collection->add($comment) // Add comment to collection

O ile widzę, zapobiegnie to dodatkowemu zapytaniu, ponieważ używamy tylko relacji-obiektu.

W moim przypadku jeden z podmiotów był trwały, podczas gdy pierwsza (na twojej stronie przypadku) nie była (ani nie została utworzona). Ponieważ musiałem przetworzyć kilka rzeczy i chciałem obsłużyć to w sposób obiektowy, chciałem dodać trwały obiekt encji do nietrwałego. Powinien także pracować z nietrwałymi.

Dziękuję Benubird za wskazanie mi właściwego kierunku. Mam nadzieję, że mój dodatek pomaga komuś tak jak dla mnie.

Proszę pamiętać, że jest to mój pierwszy post ze stackoverflow, więc proszę zostawić swoją opinię z pewnym niepokojem.


3
2018-06-21 09:50