承接 php-pico/caching 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

php-pico/caching

Composer 安装命令:

composer require php-pico/caching

包简介

A PSR-6/PSR-16 compliant caching package.

README 文档

README

A dependency-light PSR-16 (psr/simple-cache) and PSR-6 (psr/cache) cache for PHP 8.5+.

Two facades — the PSR-16 Cache and the PSR-6 CachePool — sit over the same swappable drivers. The facades own key validation, value (de)serialization and TTL handling; each driver only stores and retrieves the resulting string payloads. This keeps drivers thin, interchangeable, and independently testable, and lets both standards share one backend.

Installation

composer require php-pico/caching

PSR-16 (simple cache)

Construct a Cache with the driver of your choice and use it through the standard PSR-16 API:

use PhpPico\Caching\Cache;
use PhpPico\Caching\Driver\Testing\StaticDriver;

$cache = new Cache(new StaticDriver());

$cache->set('user.42', ['name' => 'Ada'], ttl: 3600);
$cache->get('user.42');                 // ['name' => 'Ada']
$cache->has('user.42');                 // true
$cache->delete('user.42');

$cache->setMultiple(['a' => 1, 'b' => 2]);
$cache->getMultiple(['a', 'b', 'c'], default: null);
$cache->deleteMultiple(['a', 'b']);
$cache->clear();

get()/set()/delete()/clear()/has() and the *Multiple variants all behave per the PSR-16 spec. Keys are validated (max 64 chars, [A-Za-z0-9_.]); an illegal key throws a PSR-16 InvalidArgumentException.

PSR-6 (cache item pool)

Construct a CachePool with the same drivers and use the PSR-6 item API. Items are obtained from the pool via getItem()/getItems() — never instantiated directly.

use PhpPico\Caching\CachePool;
use PhpPico\Caching\Driver\Filesystem\FilesystemDriver;

$pool = new CachePool(new FilesystemDriver('/var/cache/app'));

$item = $pool->getItem('user.42');
if (!$item->isHit()) {
    $item->set(['name' => 'Ada'])->expiresAfter(3600);
    $pool->save($item);
}
$item->get();                           // ['name' => 'Ada']

$pool->hasItem('user.42');              // true
$pool->deleteItem('user.42');
$pool->clear();

Expiration is set on the item with expiresAfter(int|\DateInterval|null) or expiresAt(?\DateTimeInterface). getItem() always returns an item (never null) — a miss is an item whose isHit() is false and whose get() is null.

Deferred writes. Queue items and flush them together with commit(). A deferred item is already visible to getItem()/hasItem() before the commit:

$pool->saveDeferred($pool->getItem('a')->set(1));
$pool->saveDeferred($pool->getItem('b')->set(2));

$pool->hasItem('a');                    // true (visible before commit)
$pool->commit();                        // persist both

If you forget commit(), the pool flushes any pending deferred items in its destructor, so they are still persisted when the pool is garbage-collected or the request ends — per PSR-6's guarantee that deferred items are not lost.

Illegal keys throw a Psr\Cache\InvalidArgumentException. Because the exception implements both PSR interfaces, the PSR-16 and PSR-6 facades can share one driver and interoperate — a value written through one reads back through the other.

Drivers

All drivers implement PhpPico\Caching\Driver\Driver and are interchangeable between the PSR-16 Cache and the PSR-6 CachePool.

Driver Backing store Persistence Notes
StaticDriver in-memory array current request only great for tests; nothing survives the request
NoopDriver none never discards writes, always misses — disables caching transparently
FilesystemDriver JSON files on disk durable TTL enforced on read; guards against directory traversal
RedisDriver Redis / Valkey over a socket durable hand-rolled RESP2, TTL via EXAT, optional reconnect
use PhpPico\Caching\Cache;
use PhpPico\Caching\Driver\Testing\NoopDriver;
use PhpPico\Caching\Driver\Testing\StaticDriver;
use PhpPico\Caching\Driver\Filesystem\FilesystemDriver;

new Cache(new StaticDriver());
new Cache(new NoopDriver());
new Cache(new FilesystemDriver('/var/cache/app'));

RedisDriver

RedisDriver speaks the RESP2 protocol directly over a TCP stream — it needs no ext-redis or other extension. Because it only depends on RESP2, it works with Redis, Valkey, and any other RESP2-compatible server (KeyDB, DragonflyDB, etc.). It is validated against Redis 8.x/7.x/6.x and Valkey 9.x/8.x/7.x.

A RedisDriver takes a RedisConnection, built one of two ways.

From connection details — dials Redis lazily on first use:

use PhpPico\Caching\Cache;
use PhpPico\Caching\Driver\Redis\RedisConnection;
use PhpPico\Caching\Driver\Redis\RedisDriver;

$connection = RedisConnection::build(
    host: '127.0.0.1',
    port: 6379,
    timeoutSeconds: 3,
    database: 0,
    reconnectTries: 1,
);

$cache = new Cache(new RedisDriver($connection));

From an existing stream — bring your own socket (e.g. a pre-opened, pooled, or already-authenticated connection):

$stream = stream_socket_client('tcp://127.0.0.1:6379');

$connection = RedisConnection::fromStream($stream, database: 0);
$cache = new Cache(new RedisDriver($connection));

Selecting a database

build() selects its database automatically on first use (a fresh connection starts on db 0, so a SELECT is only sent when database > 0). A connection built from a supplied stream is not auto-selected — call select() yourself:

$connection->select(1);
$connection->currentDatabase();   // 1

Reconnection

On a dropped connection (server restart, failover, idle kill), RedisDriver transparently reconnects and replays the failed command, up to reconnectTries times with a short backoff between attempts. This matters for long-lived runtimes (FrankenPHP, ReactPHP, Swoole, queue workers) where a single connection is reused across many requests; classic per-request PHP-FPM rarely needs it.

Only commands that are safe to run twice are replayed — every command this driver issues is idempotent (GET/SET/DEL/MSET/MSETEX/EXISTS/ FLUSHDB, with writes using an absolute EXAT so a delayed replay does not drift the TTL). A protocol error (a Redis -ERR reply) is never retried. A connection built from a supplied stream cannot re-dial, so it surfaces the failure instead of reconnecting.

Set reconnectTries: 0 to disable reconnection. A transport failure that cannot be recovered throws PhpPico\Caching\Driver\Redis\Exceptions\RedisConnectionException (a subclass of the PSR-16 CacheException).

Custom drivers

Implement PhpPico\Caching\Driver\Driver. Drivers operate on already-serialized string payloads and an absolute ?int $expiresAt timestamp — the facades handle key validation and (de)serialization. The DriverTrait provides naive multi-key operations built on the single-key methods, so a driver only has to implement get/set/delete/clear/has. A new driver works with both the PSR-16 and PSR-6 facades automatically.

Development

composer test     # PHPUnit
composer mago      # static analysis (mago)
composer format    # code style (mago)
composer qa        # format + analyze + test

License

MIT.

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-02

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固