本文目录导读:

我将为您提供几种PHP键值存储的实现方案,从简单到复杂。
内存数组实现(最简单)
<?php
class MemoryKVStore {
private $data = [];
public function set($key, $value) {
$this->data[$key] = $value;
}
public function get($key) {
return isset($this->data[$key]) ? $this->data[$key] : null;
}
public function delete($key) {
unset($this->data[$key]);
}
public function has($key) {
return isset($this->data[$key]);
}
public function getAll() {
return $this->data;
}
public function clear() {
$this->data = [];
}
public function count() {
return count($this->data);
}
}
// 使用示例
$store = new MemoryKVStore();
$store->set('username', 'Alice');
$store->set('age', 25);
echo $store->get('username'); // 输出: Alice
?>
文件存储实现
<?php
class FileKVStore {
private $filePath;
private $data = [];
public function __construct($filePath = 'kvstore.json') {
$this->filePath = $filePath;
$this->load();
}
public function set($key, $value) {
$this->data[$key] = $value;
$this->save();
}
public function get($key) {
return isset($this->data[$key]) ? $this->data[$key] : null;
}
public function delete($key) {
if (isset($this->data[$key])) {
unset($this->data[$key]);
$this->save();
return true;
}
return false;
}
public function has($key) {
return isset($this->data[$key]);
}
public function getAll() {
return $this->data;
}
public function clear() {
$this->data = [];
$this->save();
}
private function load() {
if (file_exists($this->filePath)) {
$content = file_get_contents($this->filePath);
$this->data = json_decode($content, true) ?: [];
}
}
private function save() {
$content = json_encode($this->data, JSON_PRETTY_PRINT);
file_put_contents($this->filePath, $content);
}
public function __destruct() {
$this->save();
}
}
// 使用示例
$store = new FileKVStore('storage.json');
$store->set('user1', ['name' => 'Bob', 'age' => 30]);
$store->set('config', ['debug' => true]);
$user = $store->get('user1');
?>
JSON 文件持久化(带缓存优化)
<?php
class JsonKVStore {
private $filePath;
private $data = [];
private $loaded = false;
public function __construct($filePath = 'kvstore.json') {
$this->filePath = $filePath;
}
private function ensureLoaded() {
if (!$this->loaded) {
$this->loadFromFile();
$this->loaded = true;
}
}
private function loadFromFile() {
if (file_exists($this->filePath)) {
$content = file_get_contents($this->filePath);
$this->data = json_decode($content, true);
if (!is_array($this->data)) {
$this->data = [];
}
} else {
$this->data = [];
}
}
public function set($key, $value) {
$this->ensureLoaded();
$this->data[$key] = $value;
$this->persist();
}
public function get($key, $default = null) {
$this->ensureLoaded();
return isset($this->data[$key]) ? $this->data[$key] : $default;
}
public function delete($key) {
$this->ensureLoaded();
if (isset($this->data[$key])) {
unset($this->data[$key]);
$this->persist();
return true;
}
return false;
}
public function getOrSet($key, $callback) {
$this->ensureLoaded();
if (!isset($this->data[$key])) {
$this->data[$key] = is_callable($callback) ? $callback() : $callback;
$this->persist();
}
return $this->data[$key];
}
private function persist() {
$tempFile = $this->filePath . '.tmp';
$content = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
file_put_contents($tempFile, $content, LOCK_EX);
rename($tempFile, $this->filePath); // 原子操作
}
}
// 使用示例
$store = new JsonKVStore('data.json');
// 使用 getOrSet 避免重复设置
$value = $store->getOrSet('timestamp', function() {
return time();
});
?>
SQLite 实现(数据量大时推荐)
<?php
class SqliteKVStore {
private $pdo;
public function __construct($dbPath = 'kvstore.db') {
$this->pdo = new PDO("sqlite:{$dbPath}");
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->pdo->exec("CREATE TABLE IF NOT EXISTS kv_store (
key_text TEXT PRIMARY KEY,
value_text TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)");
}
public function set($key, $value) {
$encoded = json_encode($value);
$stmt = $this->pdo->prepare(
"UPDATE kv_store SET value_text = :value, updated_at = CURRENT_TIMESTAMP WHERE key_text = :key"
);
$stmt->execute([':key' => $key, ':value' => $encoded]);
if ($stmt->rowCount() === 0) {
$stmt = $this->pdo->prepare(
"INSERT INTO kv_store (key_text, value_text) VALUES (:key, :value)"
);
$stmt->execute([':key' => $key, ':value' => $encoded]);
}
}
public function get($key) {
$stmt = $this->pdo->prepare("SELECT value_text FROM kv_store WHERE key_text = :key");
$stmt->execute([':key' => $key]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result) {
return json_decode($result['value_text'], true);
}
return null;
}
public function delete($key) {
$stmt = $this->pdo->prepare("DELETE FROM kv_store WHERE key_text = :key");
$stmt->execute([':key' => $key]);
return $stmt->rowCount() > 0;
}
public function has($key) {
$stmt = $this->pdo->prepare("SELECT COUNT(*) FROM kv_store WHERE key_text = :key");
$stmt->execute([':key' => $key]);
return $stmt->fetchColumn() > 0;
}
public function getAll() {
$stmt = $this->pdo->query("SELECT key_text, value_text FROM kv_store");
$result = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result[$row['key_text']] = json_decode($row['value_text'], true);
}
return $result;
}
public function clear() {
$this->pdo->exec("DELETE FROM kv_store");
}
public function count() {
return $this->pdo->query("SELECT COUNT(*) FROM kv_store")->fetchColumn();
}
public function getMultiple(array $keys) {
$placeholder = implode(',', array_fill(0, count($keys), '?'));
$stmt = $this->pdo->prepare("SELECT key_text, value_text FROM kv_store WHERE key_text IN ($placeholder)");
$stmt->execute($keys);
$result = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result[$row['key_text']] = json_decode($row['value_text'], true);
}
return $result;
}
public function setMultiple(array $data) {
$this->pdo->beginTransaction();
try {
foreach ($data as $key => $value) {
$this->set($key, $value);
}
$this->pdo->commit();
} catch (Exception $e) {
$this->pdo->rollBack();
throw $e;
}
}
}
// 使用示例
$store = new SqliteKVStore('data.db');
$store->set('app_config', ['debug' => true, 'env' => 'production']);
$store->setMultiple([
'user_1' => ['name' => 'Alice', 'age' => 25],
'user_2' => ['name' => 'Bob', 'age' => 30]
]);
?>
Redis 实现(高性能场景)
<?php
class RedisKVStore {
private $redis;
public function __construct($host = '127.0.0.1', $port = 6379) {
$this->redis = new Redis();
$this->redis->connect($host, $port);
}
public function set($key, $value, $ttl = null) {
$encoded = json_encode($value);
if ($ttl) {
return $this->redis->setex($key, $ttl, $encoded);
}
return $this->redis->set($key, $encoded);
}
public function get($key) {
$result = $this->redis->get($key);
return $result !== false ? json_decode($result, true) : null;
}
public function delete($key) {
return $this->redis->del($key) > 0;
}
public function has($key) {
return $this->redis->exists($key);
}
public function getAll() {
$keys = $this->redis->keys('*');
$result = [];
foreach ($keys as $key) {
$result[$key] = $this->get($key);
}
return $result;
}
public function clear() {
return $this->redis->flushDB();
}
public function setExpire($key, $ttl) {
return $this->redis->expire($key, $ttl);
}
}
// 如果安装了 Predis(纯PHP实现)
// require 'vendor/autoload.php';
// class PredisKVStore {
// private $client;
// public function __construct($config = []) {
// $this->client = new Predis\Client($config);
// }
// // 类似的方法
// }
?>
通用接口设计
<?php
interface KVStoreInterface {
public function set($key, $value);
public function get($key);
public function delete($key);
public function has($key);
public function getAll();
public function clear();
}
// 工厂模式
class KVStoreFactory {
public static function create($type = 'memory', $options = []) {
switch ($type) {
case 'memory':
return new MemoryKVStore();
case 'file':
return new FileKVStore($options['path'] ?? 'kvstore.json');
case 'sqlite':
return new SqliteKVStore($options['path'] ?? 'kvstore.db');
case 'redis':
return new RedisKVStore(
$options['host'] ?? '127.0.0.1',
$options['port'] ?? 6379
);
default:
throw new InvalidArgumentException("Unsupported store type: {$type}");
}
}
}
// 使用示例
$store = KVStoreFactory::create('redis');
$store->set('key', 'value');
echo $store->get('key'); // 输出: value
?>
选择建议
| 场景 | 推荐方案 | 特点 |
|---|---|---|
| 临时数据、简单场景 | 内存数组 | 最快,但数据不持久化 |
| 小规模持久化 | 文件存储 | 简单,适合小型应用 |
| 中等规模 | SQLite | 稳定,支持并发 |
| 高并发、分布式 | Redis | 性能最好,支持TTL |
根据您的具体需求选择合适的实现方案即可。