Moi użytkownicy mogą mieć jedną z następujących ról: admin, wydawca i twórca. Kiedy są wydawcą lub twórcą, mogą tylko uzyskać dostęp do postów, w których przypisano im klient X.

Zwykle zrobiłbym następujące czynności, aby uzyskać wszystkie posty:

$posts = \App\Models\Posts::with('Customer')->all();

Ale teraz muszę filtrować zgodnie z rolą. Próbuję uniknąć kilku warunków (jak próbka poniżej), ponieważ w przyszłości mogę dodać więcej logiki kodu:

if (Admin)
 // Get all
else
 // Get all where customer is assigned to user

Uwaga: Użytkownicy administratora nie muszą być przypisywani do żadnego klienta, mają dostęp do wszystkiego.

Miałem nadzieję, że Laravel byłby w stanie zrozumieć niestandardową funkcję, która ma być używana w elokwentnym, jak:

$posts = \App\Models\Posts::with('Customer')->filtered()->all();

Funkcja filtrowana musi spojrzeć w rolę i identyfikator klienta, coś w rodzaju:

public function filtered($userId, $customerId)
{
    // Has always access to everything
    if (\App\User::isAdmin())
        return true;

    return \App\Models\UsersCustomers::where('user_id', $userId)
        ->where('customer_id', $customerId)
        ->exists();
}

Jestem świadomy zakresów https://llavel.com/docs/5.5/elovent# query-scopes ale mam trudności z dowiedzeniem się, jak poprawnie wdrożyć.

1
Linesofcode 5 wrzesień 2020, 16:37

1 odpowiedź

Najlepsza odpowiedź

Rozwiązany .

Jak dokument stwierdza https://llavel.com/docs/5.5/elovent#query- zakresy.

Global SCOPES umożliwiają dodawanie ograniczeń do wszystkich zapytań dla danego modelu

Problem z globalnymi zakresami, przynajmniej w moim przypadku, jest to, że jeśli są posty przypisane do niektórych klientów, użytkownik X ma dostęp, ale później dostęp zostanie usunięty, zwróci, zwróci stronę 404.

Więc zamiast globalnych zakresów, kończę się za pomocą lokalnych zakresów https://llavel.com /docs/5.5/eloquent#Local-scopes.

Lokalne zakresy umożliwiają zdefiniowanie wspólnych zestawów ograniczeń, które można łatwo ponownie wykorzystać w całej aplikacji. Na przykład może być konieczne często pobieranie wszystkich użytkowników, którzy są uważane za "popularne"

W klasie modelu klientów stworzyłem następującą funkcję:

public function scopeHasAccess($query)
{
    // Access to everything
    if (\App\User::isAdmin())
        return $query;

    $userId = \Auth::id();    
    
    return $query->whereRaw("(SELECT COUNT(id) FROM users_customers WHERE user_id = '{$userId}' AND customer_id = customers.id) > 0");
}

Umożliwia to używanie funkcji takiej jak ten \App\Models\Customers::where('type', $type)->hasAccess()->get();, ale także w bardziej złożonym zapytaniu:

\App\Models\Posts::with('Related')
    ->with('Customer')
    ->where('types', $types)
    ->whereHas('Customer', function($query)
    {
        $query->hasAccess();
    });
    ->get();
0
Linesofcode 5 wrzesień 2020, 15:14