2016-07-07 7 views
1

В моем приложении я использую систему аутентификации Laravel, и я использую инъекцию зависимостей (или фасад) для доступа к зарегистрированному пользователю. Я, как правило, чтобы сделать вход в доступном пользователе через мой базовый контроллер, так что я могу получить доступ к нему легко в моих детских классов:Laravel кэширование аутентифицированных отношений пользователя

class Controller extends BaseController 
{ 
    protected $user; 

    public function __construct() 
    { 
     $this->user = \Auth::user(); 
    } 
} 

Моего пользователь имеет ряд различных отношений, которые я, как правило, нетерпеливые нагрузки, как это:

$this->user->load(['relationshipOne', 'relationshipTwo']); 

Как и в этом проекте, я ожидаю, что получаю постоянно высокие объемы трафика, я хочу, чтобы приложение выполнялось как можно плавно и эффективно, поэтому я ищу для реализации некоторого кэширования.

Я в идеале должен быть в состоянии избежать повторного запроса базы данных, особенно для связанных записей пользователя. Как таковой, мне нужно изучить кэширование объекта пользователя после загрузки отношений.

у меня была идея сделать что-то вроде этого:

public function __construct() 
{ 
    $userId = \Auth::id(); 
    if (!is_null($userId)) { 
     $this->user = \Cache::remember("user-{$userId}", 60, function() use($userId) { 
      return User::with(['relationshipOne', 'relationshipTwo'])->find($userId); 
     }); 
    } 
} 

Однако я не уверен действительно ли это безопасно полагаться на того или нет \Auth::id() возвращает ненулевое значение, чтобы пройти аутентификацию. Кто-нибудь сталкивался с подобными проблемами?

ответ

0

Я предлагаю вам использовать такой пакет, как следующий. https://github.com/spatie/laravel-responsecache

Он кэширует ответ, и вы можете использовать его не только для объекта пользователя.

0

Ну, после некоторого беспорядка, я придумал для себя какое-то решение, которое, как я думал, я поделюсь.

Я думал, что я откажусь от кэширования фактического объекта User, и просто позвольте аутентификации произойти как обычно и просто сосредоточиться на попытке кэшировать отношения пользователя. Это чувствует себя довольно грязный способ сделать это, так как моя логика в модели:

class User extends Model 
{ 
    // .. 

    /** 
    * This is the relationship I want to cache 
    */ 
    public function related() 
    { 
     return $this->hasMany(Related::class); 
    } 

    /** 
    * This method can be used when we want to utilise a cache 
    */ 
    public function getRelated() 
    { 
     return \Cache::remember("relatedByUser({$this->id})", 60, function() { 
      return $this->related; 
     }); 
    } 

    /** 
    * Do something with the cached relationship 
    */ 
    public function totalRelated() 
    { 
     return $this->getRelated()->count(); 
    } 
} 

В моем случае, мне нужно, чтобы иметь возможность кэшировать соответствующие элементы внутри User модели, потому что у меня были некоторые методы внутри пользователь, который будет использовать эти отношения. Как и в довольно тривиальном примере метода totalRelated выше (мой проект немного сложнее).

Конечно, если бы я не имел внутренние методы, как, что на моей User модели было бы столь же легко назвать отношения из-за моей модели и кэш, что (в контроллере, например)

class MyController extends Controller 
{ 
     public function index() 
     { 
      $related = \Cache::remember("relatedByUser({$this->user->id})", 60, function() { 
       return $this->user->related; 
      }); 

      // Do something with the $related items... 
     } 
} 

Опять же, это не похоже на лучшее решение для меня, и я открыт, чтобы попробовать другие предложения.

Приветствия


Edit: Я пошел еще дальше и реализовали несколько методов на мой родитель Model класс, чтобы помочь с кэшированием отношений и реализованы методы геттер для всех моих relatonships, которые принимают $useCache параметр, чтобы сделать вещи немного более гибким:

класс Parent Модель:

class Model extends BaseModel 
{ 
    /** 
    * Helper method to get a value from the cache if it exists, or using the provided closure, caching the result for 
    * the default cache time. 
    * 
    * @param $key 
    * @param Closure|null $callback 
    * @return mixed 
    */ 
    protected function cacheRemember($key, Closure $callback = null) 
    { 
     return Cache::remember($key, Cache::getDefaultCacheTime(), $callback); 
    } 

    /** 
    * Another helper method to either run a closure to get a value, or if useCache is true, attempt to get the value 
    * from the cache, using the provided key and the closure as a means of getting the value if it doesn't exist. 
    * 
    * @param $useCache 
    * @param $key 
    * @param Closure $callback 
    * @return mixed 
    */ 
    protected function getOrCacheRemember($useCache, $key, Closure $callback) 
    { 
     return !$useCache ? $callback() : $this->cacheRemember($key, $callback); 
    } 
} 

Мой класс Пользователь:

class User extends Model 
{ 
    public function related() 
    { 
     return $this->hasMany(Related::class); 
    } 

    public function getRelated($useCache = false) 
    { 
     return $this->getOrCacheRemember($useCache, "relatedByUser({$this->id})", function() { 
      return $this->related; 
     }); 
    } 
} 

Использование:

$related = $user->getRelated(); // Gets related from the database 
$relatedTwo = $user->getRelated(true); // Gets related from the cache if present (Or from database and caches result) 
Смежные вопросы