Cache
Η Cache [keš]
επιταχύνει την εφαρμογή σας αποθηκεύοντας δεδομένα
που αποκτήθηκαν με κόπο μία φορά για μελλοντική χρήση. Θα δείξουμε:
- πώς να χρησιμοποιήσετε την cache
- πώς να αλλάξετε την αποθήκη
- πώς να ακυρώσετε σωστά την cache
Η χρήση της cache στο Nette είναι πολύ εύκολη, ενώ καλύπτει και πολύ προηγμένες ανάγκες. Είναι σχεδιασμένη για απόδοση και 100% ανθεκτικότητα. Στη βάση θα βρείτε προσαρμογείς για τις πιο συνηθισμένες αποθήκες backend. Επιτρέπει την ακύρωση βάσει tags, την λήξη βάσει χρόνου, έχει προστασία έναντι cache stampede κ.λπ.
Εγκατάσταση
Κατεβάστε και εγκαταστήστε τη βιβλιοθήκη χρησιμοποιώντας το εργαλείο Composer:
composer require nette/caching
Βασική Χρήση
Ο πυρήνας της εργασίας με την cache, ή την προσωρινή μνήμη, είναι το
αντικείμενο Nette\Caching\Cache.
Δημιουργούμε ένα στιγμιότυπό του και περνάμε στον κατασκευαστή την
λεγόμενη αποθήκη ως παράμετρο. Αυτό είναι ένα αντικείμενο που
αντιπροσωπεύει τον τόπο όπου τα δεδομένα θα αποθηκευτούν φυσικά (βάση
δεδομένων, Memcached, αρχεία στον δίσκο, …). Έχουμε πρόσβαση στην αποθήκη
αφήνοντάς την να περάσει μέσω dependency injection με τον τύπο
Nette\Caching\Storage
. Όλα τα απαραίτητα θα τα μάθετε στην ενότητα Αποθήκες.
Στην έκδοση 3.0, το interface είχε ακόμα το πρόθεμα I
, οπότε
το όνομα ήταν Nette\Caching\IStorage
. Επιπλέον, οι σταθερές της κλάσης
Cache
γράφονταν με κεφαλαία γράμματα, οπότε για παράδειγμα
Cache::EXPIRE
αντί για Cache::Expire
.
Για τα παρακάτω παραδείγματα, ας υποθέσουμε ότι έχουμε δημιουργήσει
ένα alias Cache
και στην μεταβλητή $storage
την αποθήκη.
use Nette\Caching\Cache;
$storage = /* ... */; // στιγμιότυπο του Nette\Caching\Storage
Η cache είναι στην πραγματικότητα ένα key–value store, δηλαδή διαβάζουμε και γράφουμε δεδομένα υπό κλειδιά, όπως και με τους συσχετιστικούς πίνακες. Οι εφαρμογές αποτελούνται από μια σειρά ανεξάρτητων τμημάτων και αν όλα χρησιμοποιούσαν μία αποθήκη (φανταστείτε έναν κατάλογο στον δίσκο), αργά ή γρήγορα θα προέκυπτε σύγκρουση κλειδιών. Το Nette Framework λύνει το πρόβλημα χωρίζοντας ολόκληρο τον χώρο σε namespaces (υποκαταλόγους). Κάθε τμήμα του προγράμματος χρησιμοποιεί τότε τον δικό του χώρο με ένα μοναδικό όνομα και δεν μπορεί πλέον να υπάρξει καμία σύγκρουση.
Το όνομα του χώρου αναφέρεται ως η δεύτερη παράμετρος του κατασκευαστή της κλάσης Cache:
$cache = new Cache($storage, 'Full Html Pages');
Τώρα μπορούμε να χρησιμοποιήσουμε το αντικείμενο $cache
για να
διαβάσουμε και να γράψουμε στην προσωρινή μνήμη. Η μέθοδος load()
χρησιμοποιείται και για τα δύο. Το πρώτο όρισμα είναι το κλειδί και το
δεύτερο είναι ένα PHP callback που καλείται όταν το κλειδί δεν βρίσκεται
στην cache. Το callback παράγει την τιμή, την επιστρέφει και αποθηκεύεται
στην cache:
$value = $cache->load($key, function () use ($key) {
$computedValue = /* ... */; // απαιτητικός υπολογισμός
return $computedValue;
});
Αν η δεύτερη παράμετρος δεν καθοριστεί $value = $cache->load($key)
, θα
επιστραφεί null
αν το στοιχείο δεν υπάρχει στην cache.
Είναι υπέροχο που οποιαδήποτε σειριοποιήσιμη δομή μπορεί να αποθηκευτεί στην cache, όχι μόνο συμβολοσειρές. Και το ίδιο ισχύει ακόμη και για τα κλειδιά.
Ένα στοιχείο διαγράφεται από την προσωρινή μνήμη χρησιμοποιώντας τη
μέθοδο remove()
:
$cache->remove($key);
Η αποθήκευση ενός στοιχείου στην προσωρινή μνήμη μπορεί επίσης να
γίνει με τη μέθοδο $cache->save($key, $value, array $dependencies = [])
. Ωστόσο,
προτιμάται η παραπάνω μέθοδος χρησιμοποιώντας το load()
.
Memoization
Memoization σημαίνει την προσωρινή αποθήκευση του αποτελέσματος μιας κλήσης συνάρτησης ή μεθόδου, ώστε να μπορείτε να το χρησιμοποιήσετε την επόμενη φορά χωρίς να υπολογίζετε ξανά το ίδιο πράγμα.
Μέθοδοι και συναρτήσεις μπορούν να κληθούν με memoization χρησιμοποιώντας
το call(callable $callback, ...$args)
:
$result = $cache->call('gethostbyaddr', $ip);
Η συνάρτηση gethostbyaddr()
καλείται έτσι μόνο μία φορά για κάθε
παράμετρο $ip
, και την επόμενη φορά η τιμή επιστρέφεται από
την cache.
Είναι επίσης δυνατό να δημιουργηθεί ένα memoized wrapper γύρω από μια μέθοδο ή συνάρτηση που μπορεί να κληθεί αργότερα:
function factorial($num)
{
return /* ... */;
}
$memoizedFactorial = $cache->wrap('factorial');
$result = $memoizedFactorial(5); // υπολογίζει την πρώτη φορά
$result = $memoizedFactorial(5); // τη δεύτερη φορά από την cache
Λήξη & Ακύρωση
Με την αποθήκευση στην cache, είναι απαραίτητο να αντιμετωπιστεί το ζήτημα του πότε τα προηγουμένως αποθηκευμένα δεδομένα καθίστανται άκυρα. Το Nette Framework προσφέρει έναν μηχανισμό για τον περιορισμό της εγκυρότητας των δεδομένων ή την ελεγχόμενη διαγραφή τους (στην ορολογία του framework “ακύρωση”).
Η εγκυρότητα των δεδομένων ορίζεται τη στιγμή της αποθήκευσης
χρησιμοποιώντας την τρίτη παράμετρο της μεθόδου save()
, π.χ.:
$cache->save($key, $value, [
$cache::Expire => '20 minutes',
]);
Ή χρησιμοποιώντας την παράμετρο $dependencies
που περνιέται με
αναφορά στο callback της μεθόδου load()
, π.χ.:
$value = $cache->load($key, function (&$dependencies) {
$dependencies[Cache::Expire] = '20 minutes';
return /* ... */;
});
Ή χρησιμοποιώντας την 3η παράμετρο στη μέθοδο load()
, π.χ.:
$value = $cache->load($key, function () {
return ...;
}, [Cache::Expire => '20 minutes']);
Στα επόμενα παραδείγματα, θα υποθέσουμε τη δεύτερη παραλλαγή και
συνεπώς την ύπαρξη της μεταβλητής $dependencies
.
Λήξη
Η απλούστερη λήξη είναι ένα χρονικό όριο. Έτσι αποθηκεύουμε δεδομένα στην cache με ισχύ 20 λεπτών:
// δέχεται επίσης τον αριθμό των δευτερολέπτων ή UNIX timestamp
$dependencies[Cache::Expire] = '20 minutes';
Αν θέλαμε να παρατείνουμε την περίοδο ισχύος με κάθε ανάγνωση, αυτό μπορεί να επιτευχθεί ως εξής, αλλά προσέξτε, το overhead της cache αυξάνεται:
$dependencies[Cache::Sliding] = true;
Είναι χρήσιμη η δυνατότητα να λήξουν τα δεδομένα τη στιγμή που αλλάζει ένα αρχείο ή κάποιο από τα περισσότερα αρχεία. Αυτό μπορεί να χρησιμοποιηθεί, για παράδειγμα, κατά την αποθήκευση δεδομένων που προκύπτουν από την επεξεργασία αυτών των αρχείων στην cache. Χρησιμοποιήστε απόλυτες διαδρομές.
$dependencies[Cache::Files] = '/path/to/data.yaml';
// ή
$dependencies[Cache::Files] = ['/path/to/data1.yaml', '/path/to/data2.yaml'];
Μπορούμε να αφήσουμε ένα στοιχείο στην cache να λήξει τη στιγμή που
λήγει ένα άλλο στοιχείο (ή κάποιο από τα περισσότερα άλλα). Αυτό μπορεί
να χρησιμοποιηθεί όταν αποθηκεύουμε, για παράδειγμα, ολόκληρη τη
σελίδα HTML στην cache και τα τμήματά της κάτω από άλλα κλειδιά. Μόλις
αλλάξει ένα τμήμα, ακυρώνεται ολόκληρη η σελίδα. Αν έχουμε αποθηκεύσει
τα τμήματα κάτω από κλειδιά π.χ. frag1
και frag2
,
χρησιμοποιούμε:
$dependencies[Cache::Items] = ['frag1', 'frag2'];
Η λήξη μπορεί επίσης να ελεγχθεί χρησιμοποιώντας προσαρμοσμένες
συναρτήσεις ή στατικές μεθόδους, οι οποίες αποφασίζουν πάντα κατά την
ανάγνωση αν το στοιχείο είναι ακόμα έγκυρο. Έτσι, για παράδειγμα,
μπορούμε να αφήσουμε ένα στοιχείο να λήξει κάθε φορά που αλλάζει η
έκδοση της PHP. Δημιουργούμε μια συνάρτηση που συγκρίνει την τρέχουσα
έκδοση με την παράμετρο, και κατά την αποθήκευση προσθέτουμε μεταξύ
των εξαρτήσεων έναν πίνακα της μορφής
[όνομα συνάρτησης, ...ορίσματα]
:
function checkPhpVersion($ver): bool
{
return $ver === PHP_VERSION_ID;
}
$dependencies[Cache::Callbacks] = [
['checkPhpVersion', PHP_VERSION_ID] // λήξη όταν checkPhpVersion(...) === false
];
Όλα τα κριτήρια μπορούν φυσικά να συνδυαστούν. Η cache θα λήξει τότε όταν τουλάχιστον ένα κριτήριο δεν πληρείται.
$dependencies[Cache::Expire] = '20 minutes';
$dependencies[Cache::Files] = '/path/to/data.yaml';
Ακύρωση με χρήση tags
Ένα πολύ χρήσιμο εργαλείο ακύρωσης είναι τα λεγόμενα tags. Μπορούμε να αντιστοιχίσουμε σε κάθε στοιχείο της cache μια λίστα από tags, που είναι οποιεσδήποτε συμβολοσειρές. Ας υποθέσουμε ότι έχουμε μια HTML σελίδα με ένα άρθρο και σχόλια, την οποία θα αποθηκεύσουμε στην cache. Κατά την αποθήκευση, καθορίζουμε τα tags:
$dependencies[Cache::Tags] = ["article/$articleId", "comments/$articleId"];
Ας μεταφερθούμε στη διαχείριση. Εδώ βρίσκουμε μια φόρμα για την
επεξεργασία του άρθρου. Μαζί με την αποθήκευση του άρθρου στη βάση
δεδομένων, καλούμε την εντολή clean()
, η οποία διαγράφει από την cache
τα στοιχεία σύμφωνα με το tag:
$cache->clean([
$cache::Tags => ["article/$articleId"],
]);
Ομοίως, στο σημείο προσθήκης νέου σχολίου (ή επεξεργασίας σχολίου), δεν παραλείπουμε να ακυρώσουμε το σχετικό tag:
$cache->clean([
$cache::Tags => ["comments/$articleId"],
]);
Τι πετύχαμε με αυτό; Ότι η HTML cache μας θα ακυρώνεται (διαγράφεται) κάθε
φορά που αλλάζει το άρθρο ή τα σχόλια. Όταν επεξεργάζεται το άρθρο με ID =
10, γίνεται αναγκαστική ακύρωση του tag article/10
και η HTML σελίδα που
φέρει το εν λόγω tag διαγράφεται από την cache. Το ίδιο συμβαίνει κατά την
εισαγωγή νέου σχολίου κάτω από το σχετικό άρθρο.
Τα tags απαιτούν το λεγόμενο Journal.
Ακύρωση με χρήση προτεραιότητας
Μπορούμε να ορίσουμε μια προτεραιότητα για μεμονωμένα στοιχεία στην cache, με βάση την οποία θα μπορούν να διαγραφούν όταν, για παράδειγμα, η cache υπερβεί ένα συγκεκριμένο μέγεθος:
$dependencies[Cache::Priority] = 50;
Διαγράφουμε όλα τα στοιχεία με προτεραιότητα ίση ή μικρότερη από 100:
$cache->clean([
$cache::Priority => 100,
]);
Οι προτεραιότητες απαιτούν το λεγόμενο Journal.
Διαγραφή της cache
Η παράμετρος Cache::All
διαγράφει τα πάντα:
$cache->clean([
$cache::All => true,
]);
Μαζική ανάγνωση
Για μαζικές αναγνώσεις και εγγραφές στην cache χρησιμοποιείται η
μέθοδος bulkLoad()
, στην οποία περνάμε έναν πίνακα κλειδιών και
λαμβάνουμε έναν πίνακα τιμών:
$values = $cache->bulkLoad($keys);
Η μέθοδος bulkLoad()
λειτουργεί παρόμοια με το load()
και με τη
δεύτερη παράμετρο callback, στην οποία περνιέται το κλειδί του παραγόμενου
στοιχείου:
$values = $cache->bulkLoad($keys, function ($key, &$dependencies) {
$computedValue = /* ... */; // απαιτητικός υπολογισμός
return $computedValue;
});
Χρήση με PSR-16
Για να χρησιμοποιήσετε την Nette Cache με το interface PSR-16, μπορείτε να
χρησιμοποιήσετε τον προσαρμογέα PsrCacheAdapter
. Επιτρέπει την
απρόσκοπτη ενσωμάτωση μεταξύ της Nette Cache και οποιουδήποτε κώδικα ή
βιβλιοθήκης που αναμένει μια cache συμβατή με PSR-16.
$psrCache = new Nette\Bridges\Psr\PsrCacheAdapter($storage);
Τώρα μπορείτε να χρησιμοποιήσετε το $psrCache
ως PSR-16 cache:
$psrCache->set('key', 'value', 3600); // αποθηκεύει την τιμή για 1 ώρα
$value = $psrCache->get('key', 'default');
Ο προσαρμογέας υποστηρίζει όλες τις μεθόδους που ορίζονται στο PSR-16,
συμπεριλαμβανομένων των getMultiple()
, setMultiple()
, και
deleteMultiple()
.
Caching εξόδου
Μπορείτε να συλλάβετε και να αποθηκεύσετε στην cache την έξοδο πολύ κομψά:
if ($capture = $cache->capture($key)) {
echo ... // εκτυπώνουμε δεδομένα
$capture->end(); // αποθηκεύουμε την έξοδο στην cache
}
Σε περίπτωση που η έξοδος είναι ήδη αποθηκευμένη στην cache, η μέθοδος
capture()
την εκτυπώνει και επιστρέφει null
, οπότε η συνθήκη
δεν εκτελείται. Διαφορετικά, αρχίζει να συλλαμβάνει την έξοδο και
επιστρέφει το αντικείμενο $capture
, με το οποίο τελικά αποθηκεύουμε
τα εκτυπωμένα δεδομένα στην cache.
Στην έκδοση 3.0, η μέθοδος ονομαζόταν $cache->start()
.
Caching στο Latte
Το caching στα πρότυπα Latte είναι πολύ εύκολο, αρκεί
να περιβάλλετε ένα μέρος του προτύπου με τα tags {cache}...{/cache}
. Η cache
ακυρώνεται αυτόματα τη στιγμή που αλλάζει το πρότυπο προέλευσης
(συμπεριλαμβανομένων τυχόν ενσωματωμένων προτύπων εντός του μπλοκ
cache). Τα tags {cache}
μπορούν να ενσωματωθούν το ένα μέσα στο άλλο, και
όταν ένα ενσωματωμένο μπλοκ ακυρωθεί (για παράδειγμα, με ένα tag),
ακυρώνεται και το γονικό μπλοκ.
Στο tag είναι δυνατό να αναφερθούν κλειδιά στα οποία θα συνδεθεί η cache
(εδώ η μεταβλητή $id
) και να οριστεί η λήξη και τα tags για ακύρωση
{cache $id, expire: '20 minutes', tags: [tag1, tag2]}
...
{/cache}
Όλα τα στοιχεία είναι προαιρετικά, οπότε δεν χρειάζεται να καθορίσουμε ούτε λήξη, ούτε tags, ούτε καν κλειδιά.
Η χρήση της cache μπορεί επίσης να εξαρτηθεί από συνθήκη
χρησιμοποιώντας το if
– το περιεχόμενο θα αποθηκευτεί στην cache
μόνο αν η συνθήκη πληρείται:
{cache $id, if: !$form->isSubmitted()}
{$form}
{/cache}
Αποθήκες
Μια αποθήκη είναι ένα αντικείμενο που αντιπροσωπεύει τον τόπο όπου τα δεδομένα αποθηκεύονται φυσικά. Μπορούμε να χρησιμοποιήσουμε μια βάση δεδομένων, έναν διακομιστή Memcached, ή την πιο προσιτή αποθήκη, που είναι τα αρχεία στον δίσκο.
Αποθήκη | Περιγραφή |
---|---|
FileStorage | προεπιλεγμένη αποθήκη με αποθήκευση σε αρχεία στον δίσκο |
MemcachedStorage | χρησιμοποιεί τον διακομιστή Memcached |
MemoryStorage | τα δεδομένα είναι προσωρινά στη μνήμη |
SQLiteStorage | τα δεδομένα αποθηκεύονται σε βάση δεδομένων SQLite |
DevNullStorage | τα δεδομένα δεν αποθηκεύονται, κατάλληλο για testing |
Μπορείτε να αποκτήσετε πρόσβαση στο αντικείμενο αποθήκης αφήνοντάς
το να περάσει μέσω dependency
injection με τον τύπο Nette\Caching\Storage
. Ως προεπιλεγμένη αποθήκη, το Nette
παρέχει το αντικείμενο FileStorage που αποθηκεύει δεδομένα στον
υποκατάλογο cache
στον κατάλογο για προσωρινά αρχεία.
Μπορείτε να αλλάξετε την αποθήκη στη διαμόρφωση:
services:
cache.storage: Nette\Caching\Storages\DevNullStorage
FileStorage
Γράφει την cache σε αρχεία στον δίσκο. Η αποθήκη
Nette\Caching\Storages\FileStorage
είναι πολύ καλά βελτιστοποιημένη για
απόδοση και κυρίως εξασφαλίζει πλήρη ατομικότητα των λειτουργιών. Τι
σημαίνει αυτό; Ότι κατά τη χρήση της cache, δεν μπορεί να συμβεί να
διαβάσουμε ένα αρχείο που δεν έχει ακόμη γραφτεί πλήρως από άλλο νήμα,
ή να το διαγράψει κάποιος “κάτω από τα χέρια μας”. Η χρήση της cache είναι
επομένως απολύτως ασφαλής.
Αυτή η αποθήκη έχει επίσης ενσωματωμένη μια σημαντική λειτουργία που εμποδίζει την ακραία αύξηση της χρήσης της CPU τη στιγμή που η cache διαγράφεται ή δεν έχει ακόμη θερμανθεί (δηλ. δημιουργηθεί). Πρόκειται για πρόληψη έναντι του cache stampede. Συμβαίνει ότι σε μία στιγμή συγκεντρώνεται μεγαλύτερος αριθμός ταυτόχρονων αιτημάτων που θέλουν το ίδιο πράγμα από την cache (π.χ. το αποτέλεσμα ενός ακριβού ερωτήματος SQL) και επειδή δεν υπάρχει στην προσωρινή μνήμη, όλες οι διεργασίες αρχίζουν να εκτελούν το ίδιο ερώτημα SQL. Η φόρτωση έτσι πολλαπλασιάζεται και μπορεί ακόμη και να συμβεί καμία διεργασία να μην προλάβει να απαντήσει εντός του χρονικού ορίου, η cache να μην δημιουργηθεί και η εφαρμογή να καταρρεύσει. Ευτυχώς, η cache στο Nette λειτουργεί έτσι ώστε κατά τη διάρκεια πολλαπλών ταυτόχρονων αιτημάτων για ένα στοιχείο, το παράγει μόνο το πρώτο νήμα, τα υπόλοιπα περιμένουν και στη συνέχεια χρησιμοποιούν το παραγόμενο αποτέλεσμα.
Παράδειγμα δημιουργίας FileStorage:
// η αποθήκη θα είναι ο κατάλογος '/path/to/temp' στον δίσκο
$storage = new Nette\Caching\Storages\FileStorage('/path/to/temp');
MemcachedStorage
Ο διακομιστής Memcached είναι ένα σύστημα αποθήκευσης
υψηλής απόδοσης σε κατανεμημένη μνήμη, του οποίου ο προσαρμογέας είναι
ο Nette\Caching\Storages\MemcachedStorage
. Στη διαμόρφωση, αναφέρουμε τη διεύθυνση
IP και τη θύρα, αν διαφέρει από την προεπιλεγμένη 11211.
Απαιτεί την επέκταση PHP memcached
.
services:
cache.storage: Nette\Caching\Storages\MemcachedStorage('10.0.0.5')
MemoryStorage
Το Nette\Caching\Storages\MemoryStorage
είναι μια αποθήκη που αποθηκεύει
δεδομένα σε έναν πίνακα PHP, και επομένως χάνονται με τον τερματισμό του
αιτήματος.
SQLiteStorage
Η βάση δεδομένων SQLite και ο προσαρμογέας Nette\Caching\Storages\SQLiteStorage
προσφέρουν έναν τρόπο αποθήκευσης της cache σε ένα μόνο αρχείο στον
δίσκο. Στη διαμόρφωση, αναφέρουμε τη διαδρομή προς αυτό το αρχείο.
Απαιτεί τις επεκτάσεις PHP pdo
και pdo_sqlite
.
services:
cache.storage: Nette\Caching\Storages\SQLiteStorage('%tempDir%/cache.db')
DevNullStorage
Μια ειδική υλοποίηση αποθήκης είναι η Nette\Caching\Storages\DevNullStorage
, η
οποία στην πραγματικότητα δεν αποθηκεύει καθόλου δεδομένα. Είναι
επομένως κατάλληλη για testing, όταν θέλουμε να εξαλείψουμε την επίδραση
της cache.
Χρήση της cache στον κώδικα
Κατά τη χρήση της cache στον κώδικα, έχουμε δύο τρόπους για να το
κάνουμε. Ο πρώτος είναι να αφήσουμε την αποθήκη να περάσει μέσω dependency injection και να
δημιουργήσουμε ένα αντικείμενο Cache
:
use Nette;
class ClassOne
{
private Nette\Caching\Cache $cache;
public function __construct(Nette\Caching\Storage $storage)
{
$this->cache = new Nette\Caching\Cache($storage, 'my-namespace');
}
}
Η δεύτερη επιλογή είναι να αφήσουμε το αντικείμενο Cache
να
περάσει απευθείας:
class ClassTwo
{
public function __construct(
private Nette\Caching\Cache $cache,
) {
}
}
Το αντικείμενο Cache
δημιουργείται στη συνέχεια απευθείας στη
διαμόρφωση με αυτόν τον τρόπο:
services:
- ClassTwo( Nette\Caching\Cache(namespace: 'my-namespace') )
Journal
Το Nette αποθηκεύει τα tags και τις προτεραιότητες στο λεγόμενο journal. Για
αυτό χρησιμοποιείται συνήθως το SQLite και το αρχείο journal.s3db
και
απαιτούνται οι επεκτάσεις PHP pdo
και pdo_sqlite
.
Μπορείτε να αλλάξετε το journal στη διαμόρφωση:
services:
cache.journal: MyJournal
Υπηρεσίες DI
Αυτές οι υπηρεσίες προστίθενται στον DI container:
Όνομα | Τύπος | Περιγραφή |
---|---|---|
cache.journal |
Nette\Caching\Storages\Journal | journal |
cache.storage |
Nette\Caching\Storage | αποθήκη |
Απενεργοποίηση της cache
Μία από τις επιλογές για την απενεργοποίηση της cache στην εφαρμογή είναι να ορίσετε ως αποθήκη την DevNullStorage:
services:
cache.storage: Nette\Caching\Storages\DevNullStorage
Αυτή η ρύθμιση δεν επηρεάζει το caching των προτύπων στο Latte ή τον DI container, καθώς αυτές οι βιβλιοθήκες δεν χρησιμοποιούν τις υπηρεσίες nette/caching και διαχειρίζονται την cache τους ανεξάρτητα. Εξάλλου, η cache τους δεν χρειάζεται να απενεργοποιηθεί στη λειτουργία ανάπτυξης.