Я получаю дублированные запросы с помощью директивы Blade. Я проверяю роль пользователя и затем отображаю данные в таблице, поэтому запрос повторяется снова и снова, замедляя работу приложения.
Я зарегистрировал поставщика услуг Blade, и в способе загрузки у меня есть следующее:
Blade::if('admin', function () {
return auth()->check() && auth()->user()->isAdmin();
});
В моей модели User:
public function isAdmin()
{
return $this->hasRole('admin');
}
И на мой взгляд:
@admin
...
@endadmin
Я смотрел на кеширование запроса, но я не вижу способа сделать это для конкретного пользователя, что мне и нужно в этом случае. Есть ли стандартное решение этой проблемы?
Я хотел бы предложить вам использовать экземпляр класса, как AccessService
, который наполнен общими свойствами, такими как is_admin
или же user_role
, Заполните его в промежуточном программном обеспечении http и используйте его. Конечно, лучше расширить его с помощью кеширования.
<?php
namespace App\Services;
use App\User;
class AccessService{
private $user;
private $isAdmin;/**
* @param User $user
*/
public function setUser(User $user) {
$this->user = $user;
$this->isAdmin = $user->isAdmin();
}/**
* @return boolean
*/
public function isAdmin(){
return $this->isAdmin;
}
}
Сервис заполнен промежуточным ПО app\Http\Middleware\Access.php
<?php
namespace App\Http\Middleware;
use App\Services\AccessService;
use Closure;
use Auth;
class Access {
public function handle($request, Closure $next)
{
$accessService = resolve(AccessService::class);
# current user
$user = Auth::user();
if($user) {
$accessService->setUser($user);
}
return $next($request);
}
}
… который зарегистрирован в app\Http\Middleware\Kernel.php
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\App\Http\Middleware\Access::class, // here, right after StartSession
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
Таким образом, вы просто расширяете лезвие, используя AccessService
:
use App\Services\AccessService;
...
Blade::if('admin', function () {
return resolve(AccessService::class)->isAdmin();
});
Или вы можете внедрить службу в шаблон блейд @inject('accessService', 'App\Services\AccessService')
и использовать его как @if($accessService->isAdmin())
Не забудьте зарегистрировать сервис как синглтон в AppServiceProvider.php
,
Я хотел бы предложить сохранить их роль в кеше в ключе, как user:role:{user_id}
Если вы ищете решение для кэширования, более эффективное, чем файловая система, используемая по умолчанию, вы можете использовать Redis.
Если у вас есть подписка на Laracasts, есть отличный курс по Redis: https://laracasts.com/series/learn-laravel-and-redis-through-examples
В противном случае, проверьте Сайт Redis. Laravel легко поддерживает Redis, что делает его легким в использовании.
В моих приложениях Laravel я всегда создаю базовый контроллер, из которого я расширяю другие мои контроллеры.
Одна вещь, которую я делаю в этом базовом контроллере, — это сохранить текущего аутентифицированного пользователя в переменной экземпляра и предоставить этому пользователю глобальный доступ ко всем представлениям. Следующий код может быть не на 100% правильным, так как я пишу его по памяти. Но это должно дать вам общее представление.
namespace App/Http/Controllers;
use Auth;
use View;
use Illuminate\Http\Controller as BaseController;
abstract Controller extends BaseController
{
/**
* @var \App\Models\User
*/
protected $_user;/**
* Create new controller instance.
*
* @return void
*/
public function __construct()
{
$this->_user = Auth::user();
View::share('user', $this->_user);
View::share('isAdmin', $this->_user ? $this->_user->isAdmin() : false);
}
}
Затем, по вашему мнению, или с помощью директивы Blade, вы можете просто получить доступ к значению общего вида.