Mam model Eloquent, który ma powiązany model:
public function option() {
return $this->hasOne('RepairOption', 'repair_item_id');
}
public function setOptionArrayAttribute($values)
{
$this->option->update($values);
}
Kiedy tworzę model, niekoniecznie ma on powiązany model. Kiedy ją aktualizuję, mogę dodać opcję lub nie.
Muszę więc sprawdzić, czy powiązany model istnieje, odpowiednio go zaktualizować lub utworzyć:
$model = RepairItem::find($id);
if (Input::has('option')) {
if (<related_model_exists>) {
$option = new RepairOption(Input::get('option'));
$option->repairItem()->associate($model);
$option->save();
$model->fill(Input::except('option');
} else {
$model->update(Input::all());
}
};
Gdzie <related_model_exists>
jest kod, którego szukam.
Odpowiedzi:
W php 7.2+ nie możesz używać
count
obiektu relacji, więc nie ma jednej metody dla wszystkich relacji. Zamiast tego użyj metody zapytania, jak podano poniżej @tremby:ogólne rozwiązanie działające na wszystkich typach relacji ( pre php 7.2 ):
To zadziała dla każdej relacji, ponieważ właściwości dynamiczne zwracają
Model
lubCollection
. Obie implementująArrayAccess
.A więc wygląda to tak:
pojedyncze relacje:
hasOne
/belongsTo
/morphTo
/morphOne
relacje do wielu:
hasMany
/belongsToMany
/morphMany
/morphToMany
/morphedByMany
źródło
count($relation)
to ogólne rozwiązanie dla wszystkich relacji. Będzie działać dlaModel
iCollection
chociażModel
nie ma->count()
metody.Collection
ma swoją własną metodęisEmpty
, aleempty
funkcja ogólna zwraca wartość false dla obiektu (dlatego nie będzie działać dla pustej kolekcji).count($model->relation)
nie działał,morphTo
gdy związek nie miał jeszcze ustawionego skojarzenia. Zagraniczny identyfikator i typ są zerowe, a zapytanie db zbudowane przez Laravela jest fałszywe i rodzi wyjątek. Użyłem$model->relation()->getOtherKey()
jako obejścia.count(): Parameter must be an array or an object that implements Countable
Obiekt Relation przekazuje nieznane wywołania metod do elokwentnego konstruktora zapytań , który jest skonfigurowany do wybierania tylko powiązanych obiektów. Ten Konstruktor z kolei przekazuje nieznane wywołania metod do swojego podstawowego Konstruktora zapytań .
Oznacza to, że możesz użyć metod
exists()
lubcount()
bezpośrednio z obiektu relacji:Zwróć uwagę na nawiasy po
relation
:->relation()
to wywołanie funkcji (pobieranie obiektu relacji), w przeciwieństwie do tego,->relation
który pobiera magiczną właściwość ustawioną dla ciebie przez Laravela (pobieranie powiązanego obiektu / obiektów).Użycie
count
metody na obiekcie relacji (to znaczy użycie nawiasów) będzie znacznie szybsze niż wykonanie$model->relation->count()
lubcount($model->relation)
(chyba że relacja została już chętnie załadowana), ponieważ wykonuje zapytanie zliczające, zamiast pobierać wszystkie dane dla dowolnych powiązanych obiektów z bazy danych, żeby je policzyć. Podobnie używanieexists
nie wymaga również pobierania danych modelu.Zarówno
exists()
icount()
praca na wszystkich typach relacji próbowałem, więc przynajmniejbelongsTo
,hasOne
,hasMany
, ibelongsToMany
.źródło
Wolę używać
exists
metody:RepairItem::find($id)->option()->exists()
aby sprawdzić, czy powiązany model istnieje, czy nie. Działa dobrze na Laravel 5.2
źródło
Po PHP 7.1 Zaakceptowana odpowiedź nie będzie działać dla wszystkich typów relacji.
Ponieważ w zależności od typu relacji, Eloquent zwróci a
Collection
, aModel
lubNull
. A w PHP 7.1count(null)
wyrzuci plikerror
.Aby więc sprawdzić, czy relacja istnieje, możesz użyć:
W przypadku relacji singiel: na przykład
hasOne
ibelongsTo
Dla wielu relacji: Na przykład:
hasMany
ibelongsToMany
źródło
Nie jestem pewien, czy zmieniło się to w Laravel 5, ale zaakceptowana odpowiedź
count($data->$relation)
nie zadziałała dla mnie, ponieważ sam akt uzyskania dostępu do właściwości relacji spowodował jej załadowanie.W końcu prosty
isset($data->$relation)
załatwił mi sprawę.źródło
$data->relation
$
$relation
byłaby nazwa twojego związku, taka$data->posts
lub taka. Przepraszam, jeśli to było mylące, chciałem wyjaśnić, żerelation
nie jest to konkretna właściwość modelu: PMożesz użyć metody relationsLoaded na obiekcie modelu. To uratowało mój bekon, więc mam nadzieję, że pomoże to komuś innemu. Byłem biorąc pod uwagę tę sugestię , kiedy to samo pytanie na Laracasts.
źródło
Jak już powiedział Hemerson Varela w Php 7.1
count(null)
, wyrzucierror
ihasOne
zwróci,null
jeśli nie ma żadnego wiersza. Ponieważ maszhasOne
relację, użyłbymempty
metody do sprawdzenia:Ale to jest zbyteczne. Nie ma potrzeby sprawdzania, czy relacja istnieje, aby określić, czy należy wykonać wywołanie,
update
czycreate
wywołanie. Po prostu użyj metody updateOrCreate . Jest to równoważne z powyższym:źródło
Musiałem całkowicie zmienić kod, kiedy zaktualizowałem moją wersję PHP do 7.2+ z powodu złego użycia funkcji count ($ x). Jest to prawdziwy ból, a także niezwykle przerażający, ponieważ istnieją setki zastosowań, w różnych scenariuszach i nie ma jednej reguły dla wszystkich.
Zasady, których przestrzegałem, aby wszystko refaktoryzować, przykłady:
$ x = Auth :: user () -> posts-> find (6); (sprawdź, czy użytkownik ma post id = 6 używając -> find ())
$ x = Auth :: user () -> profile-> departments; (sprawdź, czy profil ma kilka działów, może mieć wiele działów)
$ x = Auth :: user () -> profile-> get (); (sprawdź, czy użytkownik ma profil po użyciu a -> get ())
Mam nadzieję, że to pomoże, nawet 5 lat po zadaniu pytania ten post o przepływie stosów bardzo mi pomógł!
źródło