Rumah > pembangunan bahagian belakang > tutorial php > Antara Muka PSR-Caching dalam PHP

Antara Muka PSR-Caching dalam PHP

DDD
Lepaskan: 2025-01-11 16:05:43
asal
1050 orang telah melayarinya

PSR-Caching Interface in PHP

Hello semua!

Adakah aplikasi anda berjalan perlahan disebabkan pertanyaan pangkalan data yang berulang? Atau menghadapi masalah bertukar antara perpustakaan caching yang berbeza? Mari selami PSR-6, piawaian yang menjadikan caching dalam PHP boleh diramal dan boleh ditukar ganti!

Artikel ini adalah sebahagian daripada siri piawaian PHP PSR. Jika anda baru, adalah idea yang baik untuk bermula dengan asas PSR-1.

Apakah masalah yang PSR-6 selesaikan? (2 minit)

Sebelum PSR-6, setiap perpustakaan cache mempunyai cara kerjanya yang tersendiri. Ingin bertukar daripada Memcached kepada Redis? Tulis semula kod anda. Berhijrah dari satu rangka kerja ke rangka kerja yang lain? Ketahui API caching baharu. PSR-6 menyelesaikan masalah ini dengan menyediakan antara muka biasa yang boleh dilaksanakan oleh semua perpustakaan cache.

Antara Muka Teras (5 minit)

Mari kita lihat dua pemain utama:

1. CacheItemPoolInterface

Ini ialah pengurus cache anda. Anggap ia sebagai gudang tempat anda boleh menyimpan dan mendapatkan semula item:

<code class="language-php"><?php namespace Psr\Cache;

interface CacheItemPoolInterface
{
    public function getItem($key);
    public function getItems(array $keys = array());
    public function hasItem($key);
    public function clear();
    public function deleteItem($key);
    public function deleteItems(array $keys);
    public function save(CacheItemInterface $item);
    public function saveDeferred(CacheItemInterface $item);
    public function commit();
}

?></code>
Salin selepas log masuk

2. CacheItemInterface

Ini mewakili satu item dalam cache:

<code class="language-php"><?php namespace Psr\Cache;

interface CacheItemInterface
{
    public function getKey();
    public function get();
    public function isHit();
    public function set($value);
    public function expiresAt($expiration);
    public function expiresAfter($time);
}

?></code>
Salin selepas log masuk

Aplikasi Praktikal (10 minit)

Berikut ialah contoh praktikal daripada asas kod kami:

1. Pelaksanaan item cache

<code class="language-php"><?php namespace JonesRussell\PhpFigGuide\PSR6;

use Psr\Cache\CacheItemInterface;
use DateTimeInterface;
use DateInterval;
use DateTime;

class CacheItem implements CacheItemInterface
{
    private $key;
    private $value;
    private $isHit;
    private $expiration;

    public function __construct(string $key)
    {
        $this->key = $key;
        $this->isHit = false;
    }

    public function getKey(): string
    {
        return $this->key;
    }

    public function get()
    {
        return $this->value;
    }

    public function isHit(): bool
    {
        return $this->isHit;
    }

    public function set($value): self
    {
        $this->value = $value;
        return $this;
    }

    public function expiresAt(?DateTimeInterface $expiration): self
    {
        $this->expiration = $expiration;
        return $this;
    }

    public function expiresAfter($time): self
    {
        if ($time instanceof DateInterval) {
            $this->expiration = (new DateTime())->add($time);
        } elseif (is_int($time)) {
            $this->expiration = (new DateTime())->add(new DateInterval("PT{$time}S"));
        } else {
            $this->expiration = null;
        }
        return $this;
    }

    // Helper method for our implementation
    public function getExpiration(): ?DateTimeInterface
    {
        return $this->expiration;
    }

    // Helper method for our implementation
    public function setIsHit(bool $hit): void
    {
        $this->isHit = $hit;
    }
}</code>
Salin selepas log masuk

2. Pelaksanaan kumpulan cache

<code class="language-php"><?php namespace JonesRussell\PhpFigGuide\PSR6;

use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\CacheItemInterface;
use RuntimeException;

class FileCachePool implements CacheItemPoolInterface
{
    private $directory;
    private $deferred = [];

    public function __construct(string $directory)
    {
        if (!is_dir($directory) && !mkdir($directory, 0777, true)) {
            throw new RuntimeException("Cannot create cache directory: {$directory}");
        }
        $this->directory = $directory;
    }

    public function getItem($key): CacheItemInterface
    {
        $this->validateKey($key);

        if (isset($this->deferred[$key])) {
            return $this->deferred[$key];
        }

        $item = new CacheItem($key);
        $path = $this->getPath($key);

        if (file_exists($path)) {
            try {
                $data = unserialize(file_get_contents($path));
                if (!$data['expiration'] || $data['expiration'] > new DateTime()) {
                    $item->set($data['value']);
                    $item->setIsHit(true);
                    return $item;
                }
                unlink($path);
            } catch (\Exception $e) {
                // Log error and continue with cache miss
            }
        }

        return $item;
    }

    public function getItems(array $keys = []): iterable
    {
        $items = [];
        foreach ($keys as $key) {
            $items[$key] = $this->getItem($key);
        }
        return $items;
    }

    public function hasItem($key): bool
    {
        return $this->getItem($key)->isHit();
    }

    public function clear(): bool
    {
        $this->deferred = [];
        $files = glob($this->directory . '/*.cache');

        if ($files === false) {
            return false;
        }

        $success = true;
        foreach ($files as $file) {
            if (!unlink($file)) {
                $success = false;
            }
        }
        return $success;
    }

    public function deleteItem($key): bool
    {
        $this->validateKey($key);
        unset($this->deferred[$key]);

        $path = $this->getPath($key);
        if (file_exists($path)) {
            return unlink($path);
        }
        return true;
    }

    public function deleteItems(array $keys): bool
    {
        $success = true;
        foreach ($keys as $key) {
            if (!$this->deleteItem($key)) {
                $success = false;
            }
        }
        return $success;
    }

    public function save(CacheItemInterface $item): bool
    {
        $path = $this->getPath($item->getKey());
        $data = [
            'value' => $item->get(),
            'expiration' => $item->getExpiration()
        ];

        try {
            if (file_put_contents($path, serialize($data)) === false) {
                return false;
            }
            return true;
        } catch (\Exception $e) {
            return false;
        }
    }

    public function saveDeferred(CacheItemInterface $item): bool
    {
        $this->deferred[$item->getKey()] = $item;
        return true;
    }

    public function commit(): bool
    {
        $success = true;
        foreach ($this->deferred as $item) {
            if (!$this->save($item)) {
                $success = false;
            }
        }
        $this->deferred = [];
        return $success;
    }

    private function getPath(string $key): string
    {
        return $this->directory . '/' . sha1($key) . '.cache';
    }

    private function validateKey(string $key): void
    {
        if (!is_string($key) || preg_match('#[{}()/@:\\]#', $key)) {
            throw new InvalidArgumentException(
                'Invalid key: ' . var_export($key, true)
            );
        }
    }
}</code>
Salin selepas log masuk

Penggunaan praktikal (5 minit)

Mari lihat cara menggunakannya dalam kod sebenar:

<code class="language-php">// 基本用法
$pool = new FileCachePool('/path/to/cache');

try {
    // 存储值
    $item = $pool->getItem('user.1');
    if (!$item->isHit()) {
        $userData = $database->fetchUser(1); // 您的数据库调用
        $item->set($userData)
             ->expiresAfter(3600); // 1 小时
        $pool->save($item);
    }
    $user = $item->get();
} catch (\Exception $e) {
    // 优雅地处理错误
    log_error('缓存操作失败:' . $e->getMessage());
    $user = $database->fetchUser(1); // 回退到数据库
}</code>
Salin selepas log masuk

Perangkap Biasa (3 minit)

  1. Pengesahan Kunci
  2. Ralat pengendalian

Apa yang seterusnya?

Esok, kita akan membincangkan PSR-7 (Antaramuka Mesej HTTP). Jika anda berminat dengan caching yang lebih ringkas, nantikan artikel PSR-16 (Simple Caching) kami yang akan datang, yang menawarkan alternatif yang lebih mudah kepada PSR-6.

Sumber

  • Spesifikasi Rasmi PSR-6
  • Pangkalan kod sampel kami (v0.6.0 - pelaksanaan PSR-6)
  • Komponen caching Symfony
  • Cache PHP

Atas ialah kandungan terperinci Antara Muka PSR-Caching dalam PHP. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan