2013-10-23 20 views
28

Câu hỏi lý thuyết về Laravel ở đây.Làm thế nào bạn quên các mô hình Eloquent được lưu trong Laravel?

Vì vậy Ví dụ về bộ nhớ đệm tôi muốn làm là:

Article::with('comments')->remember(5)->get(); 

Lý tưởng nhất là tôi muốn có một sự kiện cho Điều cập nhật khi ID của một thể hiện của mô hình đó (đó là đã được lưu trữ) là cập nhật Tôi muốn quên rằng chìa khóa (ngay cả khi đó là toàn bộ kết quả của truy vấn đó là quên thay vì chỉ là một ví dụ mô hình), nó có thể làm như vậy?

Nếu không có cách nào để thực hiện điều này một cách hợp lý một cách hợp lý?

+0

không lý thuyết, btw. –

+0

Không phải bây giờ nó đã được trả lời nhưng tại thời điểm đó là vì không có tài liệu về việc sử dụng các khóa bộ nhớ cache với hùng hồn –

Trả lời

59

Vì vậy, tôi đang tìm kiếm câu trả lời cho cùng một câu hỏi như OP nhưng không thực sự hài lòng với các giải pháp. Vì vậy, tôi bắt đầu chơi xung quanh với điều này gần đây và đi qua mã nguồn của khuôn khổ, tôi phát hiện ra rằng phương pháp remember() chấp nhận tham số thứ hai được gọi là key và vì một lý do nào đó nó chưa được ghi trên site của chúng (Hoặc tôi đã bỏ lỡ điều đó?) .

Bây giờ tốt về điều này, Trình tạo cơ sở dữ liệu sử dụng cùng một trình điều khiển bộ nhớ cache được cấu hình theo app/config/cache.php Hoặc tôi nên nói cùng một hệ thống bộ nhớ cache đã được ghi ở đây - Cache. Vì vậy, nếu bạn vượt qua min và chìa khóa để remember(), bạn có thể sử dụng cùng một khóa để xóa bộ nhớ cache sử dụng Cache::forget() phương pháp và trên thực tế, bạn có khá nhiều có thể sử dụng tất cả các phương pháp Cache niêm yết trên Sở official site, như Cache::get(), Cache::add(), Cache::put() vv Nhưng tôi không khuyên bạn nên sử dụng những phương pháp khác trừ khi bạn biết những gì bạn đang làm.

Đây là một ví dụ để bạn và những người khác hiểu ý tôi.

Article::with('comments')->remember(5, 'article_comments')->get();

Bây giờ kết quả truy vấn trên sẽ được lưu trữ và sẽ được liên kết với phím article_comments mà sau đó có thể được sử dụng để xóa nó bất cứ lúc nào (Trong trường hợp của tôi, tôi làm điều đó khi tôi cập nhật).

Vì vậy, bây giờ nếu tôi muốn xóa bộ nhớ cache đó bất kể thời gian nó ghi nhớ. Tôi chỉ có thể làm điều đó bằng cách gọi Cache::forget('article_comments'); và nó sẽ hoạt động như mong đợi.

Hy vọng điều này sẽ giúp mọi người :)

+3

Câu trả lời hay, cảm ơn bạn Đối với những người không rõ ràng, lập luận đầu tiên cần nhớ là số phút để lưu vào bộ nhớ cache http: // laravel .com/api/source-class-Illuminate.Database.Query.Builder.html # 881-893 – Makita

+1

Không có vấn đề và cảm ơn cho liên kết –

+0

câu hỏi hay này và câu trả lời hữu ích nên có upvote :) – antoniputra

12

Tôi nghĩ một cách tốt để làm giống như this:

$value = Cache::remember('users', $minutes, function() 
{ 
    return DB::table('users')->get(); 
}); 

và sau đó sử dụng Model Observers để phát hiện sự kiện cập nhật mô hình

class UserObserver { 

    public function saving($model) 
    { 
     // 
    } 

    public function saved($model) 
    { 
     // forget from cache 
     Cache::forget('users'); 
    } 

} 

User::observe(new UserObserver); 
+0

Khi tôi chạy DB :: table ('users') -> get(); điều này sẽ không nhận được trường hợp của một mô hình Eloquent nó, nó sẽ chỉ nhận được kết quả của truy vấn như là một mảng của các đối tượng chung? Tôi nghĩ tôi có thể trả về kết quả của truy vấn mô hình Eloquent thay vì truy vấn DB trực tiếp đúng không? –

+0

Tôi tin rằng bạn nên sử dụng 'User :: whereSomething ('something') -> get()' nếu bạn muốn cache bộ sưu tập Eloquent của các đối tượng và nếu bạn muốn lưu trữ các thuộc tính để chuyển đổi nó thành một mảng như: ' Người dùng :: whereSomething ('something') -> get() -> toArray() '. –

0

Hiện tại không có cách dễ dàng. Tuy nhiên tôi tìm thấy cách giải quyết này, cho đến nay đã làm việc cho tôi.

Trước tiên, bạn phải mở rộng Illuminate\Database\Query\Builder.

<?php 

class ModifiedBuilder extends Illuminate\Database\Query\Builder { 
    protected $forgetRequested = false; 

    public function forget() 
    { 
     $this->forgetRequested = true; 
    } 

    public function getCached($columns = array('*')) 
    { 
     if (is_null($this->columns)) $this->columns = $columns; 

     list($key, $minutes) = $this->getCacheInfo(); 

     // If the query is requested ot be cached, we will cache it using a unique key 
     // for this database connection and query statement, including the bindings 
     // that are used on this query, providing great convenience when caching. 
     $cache = $this->connection->getCacheManager(); 

     $callback = $this->getCacheCallback($columns); 

     if($this->forgetRequested) { 
      $cache->forget($key); 
      $this->forgetRequested = false; 
     } 

     return $cache->remember($key, $minutes, $callback); 
    } 
} 

Sau đó, bạn phải tạo lớp mới mở rộng Mô hình Eloquent.

<?php 

class BaseModel extends Eloquent { 
    protected function newBaseQueryBuilder() { 
     $conn = $this->getConnection(); 

     $grammar = $conn->getQueryGrammar(); 

     return new ModifiedBuilder($conn, $grammar, $conn->getPostProcessor()); 
    } 
} 

Bây giờ khi tạo mô hình hùng hồn, thay vì mở rộng Eloquent Models mở rộng mới được tạo ra BaseModel.

Bây giờ bạn có thể remember kết quả truy vấn như bình thường.

YourModel::remember(10)->get(); 

Khi bạn muốn loại bỏ các kết quả lưu trữ tất cả các bạn phải làm là

YourModel::forget()->get(); 

Nếu bạn còn nhớ kết quả trước đó, sau khi thanh toán bù trừ các kết quả lưu trữ, mô hình sẽ tiếp tục nhớ kết quả cho điều đó khoảng thời gian.

Hy vọng điều này sẽ hữu ích.

+0

Trong phương thức getCached, biến $ key được khởi tạo ở đâu? –

+0

Nó được truy xuất trong hàm 'getCacheInfo()' và khoá được tạo trong hàm 'generateCacheKey()' trong ['Illuminate/Database/Query/Builder.php'] (https://github.com/laravel/framework/) blob/master/src/Illuminate/Cơ sở dữ liệu/Truy vấn/Builder.php). Dường như bạn có thể đặt khóa của riêng mình bằng cách sử dụng phương thức 'remember()' theo API. Tuy nhiên nó dường như bị bỏ qua trong hàm 'getCacheKey()'. – tharumax

+0

Phương pháp tôi đã đề cập ở trên hoạt động khá tốt đối với các truy vấn đơn giản và hầu hết các mối quan hệ. Tuy nhiên, khi bảng tổng hợp có mặt (nhiều trong nhiều mối quan hệ nó không hoạt động như mong đợi) – tharumax

0

Tôi đã thử nghiệm chế độ gỡ lỗi. Vì vậy, tôi thấy rằng nếu bạn đặt một thử nghiệm cho app.debug trong một hàm tạo, bạn có thể xóa bộ đệm ẩn được liên kết với một khóa. Tiết kiệm bạn phải lặp lại mã cho mọi chức năng.

class Events { 
    public function __construct() { 
     if (\Config::get('app.debug')) { 
      Cache::forget('events'); 
     } 
    } 

    public static function all() { 
     $events = \DB::table('events as e') 
      ->select('e.*') 
      ->where('enabled', 1) 
      ->remember(30, 'events') 
      ->get(); 

     return $events; 
    } 
} 
Các vấn đề liên quan