Relacje, wiele zapytań do bazy

Relacje, wiele zapytań do bazy
ST
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0

Cześć, mam do Was pytanie związane z Laravel i relacjami, załóżmy że mam na stronie zakładkę Drużyny (którą tworzą ludzie), w niej oczywiście jest lista członków, czyli: Drużyna -> lista członków, no i teraz konkretnie muszę ich wyświetlić oraz ich status (a ich status jest określany przez obecność user_id w tabeli online_users [id, user_id]), moje rozwiązanie to relacja User -> OnlineUsers jednak to generuje na 30 członków w drużynie aż 30 zapytań! Jakieś pomysły jak zredukować ich ilość do minimum?

jurek1980
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3581
5

Pokaż modele i relacje jakie masz utworzone. Jak wywołujesz zapytanie ?
Jeśli zrobisz coś w stylu:

Kopiuj
$data = Teams::where('id','=',$id)
            ->with('users')
            ->with('onlineUsers')
            ->get();

Powinien zadziałać Eager Loading i powinieneś mieć zredukowane zapytania do 3.
Zobacz w dokumentacji:
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading

serek
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1506
0

A po co dodatkowo tabela, by trzymać userów, co są online? Trochę przeinżynierowane to. Starczy trzymać w tabeli users datę ostatniego wejścia usera na stronę. I potem porównać z aktualną.

ST
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0
jurek1980 napisał(a):

Pokaż modele i relacje jakie masz utworzone. Jak wywołujesz zapytanie ?

Jeśli zrobisz coś w stylu:

Kopiuj
$data = Teams::where('id','=',$id)
            ->with('users')
            ->with('onlineUsers')
            ->get();

Powinien zadziałać Eager Loading i powinieneś mieć zredukowane zapytania do 3.
Zobacz w dokumentacji:
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading

Sprawdzę Twoje rozwiązanie i dam znać (obecnie jestem na etapie przepisywania strony więc chwile to zajmie, po prostu pamiętam, że miałem tutaj z tym problem).

serek napisał(a):

A po co dodatkowo tabela, by trzymać userów, co są online? Trochę przeinżynierowane to. Starczy trzymać w tabeli users datę ostatniego wejścia usera na stronę. I potem porównać z aktualną.

Strona / baza danych jest połączona z aplikacją, która w ten sposób zapisuje obecnie aktywnych użytkowników.

ST
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0

Ok, napotkałem przeszkodę w innej sytuacji, może ktoś byłby w stanie mi pomóc, mam klase Guild, ona relacje do GuildRank a z niej idzie relacja do GuildMembership (wszędzie hasMany) no i wszystko działa poprawnie:

title

jednak gdy dodałem eager loading w klasie gdzie wczytuje Guild

title

zapytanie zmienia guild_id w NULL
title

dokładniej w tej części guild_id zmienia się w NULL

Kopiuj
return $this->hasMany(GuildMembership::class, 'rank_id')->where('guild_id', $this->guild_id);

jakieś pomysły dlaczego?

jurek1980
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3581
0

Trochę dziwne to rozwiązanie.
Dlaczego używasz czegoś takiego:

Kopiuj
return $this->hasMany(GuildMembership::class, 'rank_id')->where('guild_id', $this->guild_id);

Piszę teraz z pamięci ale chyba pierwsze hasMany zwróci instancję relacji i wywołanie na czymś takim where pewnie zwróci null.
To jest część Twojej relacji czy jakiegoś zapytania?

Pokaż dokładnie gdzie używasz tego eagerloadingu. To with przy view to załączenie zmiennej do widoku.

ST
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0

W ten sposób pobieram liste członków drużyny, guild_ranks to ich kategorie (np. menadżer, vice-menadżer, zwykły użytkownik), guild_membership to lista członków (user_id, rank_id ( czyli kategoria )) i stąd będę w stanie przejść do ostatniego modelu czyli klasy Player (po user_id)

Widok:

Kopiuj
@foreach($guild->ranks as $rank)
    @foreach($rank->members as $member)
        <tr>
            <td>{{ $rank->getName() }}</td>
            <td>-- tutaj byloby {{ $member->player->COS }} itd</td>
            <td>2</td>
        </tr>
    @endforeach
@endforeach

Kontroler:

Kopiuj
public function index(Guild $guild)
{
    $guild->load('ranks.members');
    return view('community.guilds.show')->with(compact('guild'));
}

Model Guild:

Kopiuj
public function ranks() {
    return $this->hasMany(GuildRank::class, 'guild_id', 'id');
}

Model GuildRank:

Kopiuj
public function members() {
    return $this->hasMany(GuildMembership::class, 'rank_id')->where('guild_id', $this->guild_id);
}

Czyli wszystkie się sypie (wstawia mi null zamiast guild_id) w momencie dodania

Kopiuj
$guild->load('ranks.members');

do kontrolera :x chcę po prostu zredukować ilość zapytań przykładowo z 3 na 1 (zależnie od ilości kategorii)

jurek1980
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3581
1

Może się mylę ale powtórzę, to nie wygląda na poprawną relację:

Kopiuj
public function members() {
    return $this->hasMany(GuildMembership::class, 'rank_id')->where('guild_id', $this->guild_id);
}

Filtruj z użyciem where na wynikach zapytania.

ST
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0

Rzeczywiście, chyba masz racje, dzięki!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.