PHPackages                             erikwang2013/etcd - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. erikwang2013/etcd

ActiveLibrary[HTTP &amp; Networking](/categories/http)

erikwang2013/etcd
=================

PHP etcd v3 client with gRPC + HTTP dual transport. Supports Laravel, Hyperf, ThinkPHP, Webman.

v1.0.2(2mo ago)1202↓88.9%MITPHPPHP &gt;=8.1

Since May 13Pushed 2mo agoCompare

[ Source](https://github.com/erikwang2013/etcd)[ Packagist](https://packagist.org/packages/erikwang2013/etcd)[ Docs](https://erik.xyz)[ RSS](/packages/erikwang2013-etcd/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (2)Versions (3)Used By (0)

erikwang2013/etcd
=================

[](#erikwang2013etcd)

PHP etcd v3 客户端 — gRPC + HTTP 双模传输，全功能 API，支持 **Laravel / Hyperf / ThinkPHP / Webman**。

要求
--

[](#要求)

- PHP &gt;= 8.1
- etcd v3.x 服务端
- PSR-18 + PSR-17 HTTP 客户端（HTTP 传输必需，各框架通常自带）

安装
--

[](#安装)

```
composer require erikwang2013/etcd
```

快速开始
----

[](#快速开始)

```
use Erikwang2013\Etcd\EtcdClient;

$etcd = new EtcdClient(['endpoints' => ['127.0.0.1:2379']]);

// 写入
$etcd->kv()->put('/app/config', '{"debug":true}');

// 读取
$result = $etcd->kv()->get('/app/config');
print_r($result['kvs'][0]);  // ['key' => '/app/config', 'value' => '{"debug":true}', ...]

// 找不到时抛异常
$kv = $etcd->kv()->getOrFail('/app/config');

// 前缀扫描
$all = $etcd->kv()->getByPrefix('/app/');
echo "共 {$all['count']} 条\n";

// 删除
$etcd->kv()->delete('/app/config');
$etcd->kv()->deleteByPrefix('/cache/');

// 带租约写入（60 秒后自动删除）
$lease = $etcd->lease()->grant(60);
$etcd->kv()->put('/session/123', 'active', ['lease' => $lease['ID']]);

// 续约
$etcd->lease()->keepAlive($lease['ID']);
```

配置
--

[](#配置)

```
$etcd = new EtcdClient([
    'endpoints' => ['192.168.1.10:2379', '192.168.1.11:2379'],  // 多节点
    'transport' => 'auto',  // auto（默认）| http | grpc
    'timeout'   => 5.0,     // 秒
    'retry'     => 3,       // 连接失败重试次数
    'auth'      => [        // 可选，Basic Auth
        'user'     => 'root',
        'password' => 'secret',
    ],
]);
```

### 环境变量

[](#环境变量)

不传配置时自动读取环境变量：

变量默认值说明`ETCD_ENDPOINTS``127.0.0.1:2379`逗号分隔的多节点地址`ETCD_TRANSPORT``auto`auto / http / grpc`ETCD_TIMEOUT``5.0`请求超时（秒）`ETCD_RETRY``2`连接重试次数`ETCD_USER`—etcd 用户名`ETCD_PASSWORD`—etcd 密码API 参考
------

[](#api-参考)

### KV — 键值操作

[](#kv--键值操作)

```
// 写入
$etcd->kv()->put('key', 'value', [
    'lease'       => 12345,    // 绑定租约 ID
    'prevKv'      => true,     // 返回写入前的旧值
    'ignoreValue' => false,
    'ignoreLease' => false,
]);

// 读取单键
$etcd->kv()->get('/exact/key');

// 找不到即抛异常
$kv = $etcd->kv()->getOrFail('/exact/key');

// 前缀扫描
$etcd->kv()->getByPrefix('/prefix/');

// 范围查询（完整参数）
$etcd->kv()->get('/start', [
    'rangeEnd'    => '/startz',      // 范围结束 key
    'limit'       => 100,             // 最大返回条数
    'revision'    => 42,              // 快照版本号
    'sortOrder'   => 'ascend',        // none | ascend | descend
    'sortTarget'  => 'key',           // key | version | create | mod | value
    'serializable'=> true,            // 跳过 Raft 共识（更快，可能过期）
    'keysOnly'    => true,            // 只返回 key，不返回 value
    'countOnly'   => false,           // 只返回计数
]);

// 删除
$etcd->kv()->delete('/key');
$etcd->kv()->deleteByPrefix('/prefix/');
$etcd->kv()->delete('/key', ['prevKv' => true]);  // 同时返回被删的值

// 事务（原子 CAS）
$etcd->kv()->txn(
    compare: [
        ['result' => 0, 'target' => 3, 'key' => '/counter', 'value' => '100']
    ],
    success: [
        ['request_put' => ['key' => '/counter', 'value' => '101']]
    ],
    failure: [
        ['request_put' => ['key' => '/counter', 'value' => '1']]
    ]
);

// 压缩历史版本（释放存储空间）
$etcd->kv()->compact(1000);
```

**比较目标（target）常量：** `0`=VERSION, `1`=CREATE, `2`=MOD, `3`=VALUE, `4`=LEASE
**比较结果（result）常量：** `0`=EQUAL, `1`=GREATER, `2`=LESS, `3`=NOT\_EQUAL

### Watch — 变更监听

[](#watch--变更监听)

```
// 监听单个 key（阻塞模式，建议在协程/独立进程中运行）
$etcd->watch()->watch('/config/key', function (array $events) {
    foreach ($events as $event) {
        // $event: ['type' => 'PUT'|'DELETE', 'kv' => [...], 'prev_kv' => [...]|null]
        echo "{$event['type']} {$event['kv']['key']} = {$event['kv']['value']}\n";
    }
});

// 监听前缀下所有 key 的变更
$etcd->watch()->watchPrefix('/config/', $callback, [
    'startRevision' => 100,       // 从指定版本开始
    'prevKv'        => true,      // DELETE 事件返回原值
    'progressNotify'=> true,      // 定期发送空事件（心跳）
]);
```

**断线重连：** Watch 连接断开时自动从上一次收到的 revision 续订，不会丢失事件。

### Lease — 租约

[](#lease--租约)

```
// 创建租约
$lease = $etcd->lease()->grant(300);             // 300 秒 TTL
$lease = $etcd->lease()->grant(300, 99999);      // 指定租约 ID

// 续约（单次）
$result = $etcd->lease()->keepAlive($lease['ID']);
echo "TTL 剩余: {$result['TTL']} 秒";

// 查看租约状态
$info = $etcd->lease()->timeToLive($lease['ID']);
$info = $etcd->lease()->timeToLive($lease['ID'], true);  // 含绑定的 key 列表

// 列出所有活跃租约
$leases = $etcd->lease()->list();

// 撤销租约（绑定的所有 key 立即删除）
$etcd->lease()->revoke($lease['ID']);
```

**典型场景：** 服务注册时创建租约 + 写入 key，定时调用 `keepAlive()` 心跳续约；服务停止后租约到期自动清理。

### Auth — 认证与权限

[](#auth--认证与权限)

```
$auth = $etcd->auth();

// === 用户管理 ===
$auth->user()->add('alice', 'password123');          // 创建用户
$auth->user()->get('alice');                         // 查看用户及其角色
$auth->user()->list();                               // 列出所有用户
$auth->user()->changePassword('alice', 'newpass');    // 修改密码
$auth->user()->grantRole('alice', 'admin');          // 授权角色
$auth->user()->revokeRole('alice', 'admin');         // 撤销角色
$auth->user()->delete('alice');                      // 删除用户

// === 角色管理 ===
$auth->role()->add('reader');                        // 创建角色
$auth->role()->get('reader');                        // 查看角色权限
$auth->role()->list();                               // 列出所有角色

// 授予权限（permType: 0=READ, 1=WRITE, 2=READWRITE）
$auth->role()->grantPermission('reader', 0, '/data/', "\0");   // 对 /data/ 前缀的读权限
$auth->role()->grantPermission('writer', 2, '/data/', "\0");   // 读写权限
$auth->role()->revokePermission('reader', '/data/', "\0");     // 撤销权限
$auth->role()->delete('reader');

// === 认证开关 ===
$auth->enable();           // 开启认证
$auth->disable();          // 关闭认证
$status = $auth->status(); // ['enabled' => true, 'authRevision' => 5]
```

**注意：** 开启认证后，客户端必须配置 `auth.user` 和 `auth.password` 才能继续操作。

### Cluster — 集群管理

[](#cluster--集群管理)

```
// 查看集群成员
$members = $etcd->cluster()->memberList();

// 添加成员
$etcd->cluster()->memberAdd(['http://node3:2380']);        // 添加 Voting 成员
$etcd->cluster()->memberAdd(['http://node4:2380'], true);  // 添加 Learner 成员

// 修改成员 peer URL
$etcd->cluster()->memberUpdate(123456, ['http://newnode:2380']);

// Learner 提升为 Voter
$etcd->cluster()->memberPromote(789012);

// 移除成员
$etcd->cluster()->memberRemove(345678);
```

### Maintenance — 运维

[](#maintenance--运维)

```
// 查看节点状态
$status = $etcd->maintenance()->status();
// ['version' => '3.5.0', 'dbSize' => 24576, 'leader' => 123, 'raftIndex' => 1000, ...]

// 告警管理
$alarms = $etcd->maintenance()->alarm();                    // 查看告警
$etcd->maintenance()->alarm(action: 2, alarm: 1);           // 清除 NOSPACE 告警

// 碎片整理（回收存储空间）
$etcd->maintenance()->defragment();

// KV 哈希校验
$hash = $etcd->maintenance()->hash();

// 获取快照（返回二进制数据，写入文件即可）
$snapshot = $etcd->maintenance()->snapshot();
file_put_contents('/backup/etcd-snapshot.db', $snapshot);
```

传输模式
----

[](#传输模式)

模式状态依赖适用场景**HTTP**可用PSR-18 + PSR-17零扩展依赖，即刻可用**gRPC**骨架ext-grpc + grpc/grpc + google/protobuf高性能、原生流式**auto**默认自动检测有 gRPC 则用 gRPC，否则 HTTP`auto` 模式检测逻辑：

1. `extension_loaded('grpc')` — C 扩展已加载？
2. `class_exists('Grpc\BaseStub')` — `grpc/grpc` composer 包已安装？

两者都满足才走 gRPC，否则回退 HTTP。

### 手动配置 PSR-18 HTTP 客户端

[](#手动配置-psr-18-http-客户端)

```
use Erikwang2013\Etcd\Transport\HttpTransport;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;

$transport = new HttpTransport(['127.0.0.1:2379'], ['timeout' => 3.0]);
$transport->setHttpClient(
    new Client(['timeout' => 3]),
    new HttpFactory(),
    new HttpFactory()
);
```

框架集成
----

[](#框架集成)

### Laravel

[](#laravel)

安装即用。composer.json 的 `extra.laravel` 自动发现 ServiceProvider 和 Facade。

```
// Facade 方式
use Etcd;
Etcd::kv()->put('/foo', 'bar');
$val = Etcd::kv()->get('/foo');

// 依赖注入方式
use Erikwang2013\Etcd\EtcdClient;

class MyService
{
    public function __construct(private EtcdClient $etcd) {}

    public function work(): void
    {
        $this->etcd->kv()->put('/key', 'value');
    }
}
```

发布配置文件：

```
php artisan vendor:publish --tag=etcd-config
# → config/etcd.php
```

`.env` 配置：

```
ETCD_ENDPOINTS=10.0.0.1:2379,10.0.0.2:2379
ETCD_USER=root
ETCD_PASSWORD=secret
```

### Hyperf

[](#hyperf)

安装即用。Hyperf 自动发现 `ConfigProvider`。

```
use Erikwang2013\Etcd\EtcdClient;
use Hyperf\Di\Annotation\Inject;

class MyService
{
    #[Inject]
    private EtcdClient $etcd;

    public function work(): void
    {
        $this->etcd->kv()->put('/key', 'value');
    }
}

// 或者直接 make
$etcd = make(EtcdClient::class);
```

发布配置：

```
php bin/hyperf.php vendor:publish erikwang2013/etcd
# → config/autoload/etcd.php
```

### ThinkPHP

[](#thinkphp)

1. 安装后，在 `app/service.php` 中注册：

```
return [
    Erikwang2013\Etcd\Adapter\ThinkPHP\Service::class,
];
```

2. 创建 `config/etcd.php` 配置文件。

使用：

```
// Facade 方式
use think\facade\Etcd;
Etcd::kv()->put('/key', 'value');

// 容器方式
app('etcd')->kv()->get('/key');
```

### Webman

[](#webman)

安装即用，无需额外配置。

```
use Erikwang2013\Etcd\EtcdClient;

$etcd = EtcdClient::instance();
$etcd->kv()->put('/key', 'value');
```

如需自定义配置，编辑 `plugin/erikwang2013/etcd/config/etcd.php`。

异常处理
----

[](#异常处理)

```
use Erikwang2013\Etcd\Exception\{
    EtcdException,
    ConnectionException,
    AuthException,
    KeyNotFoundException,
};

try {
    $etcd->kv()->put('/key', 'value');
} catch (ConnectionException $e) {
    // etcd 节点无法连接（网络故障、宕机）
} catch (AuthException $e) {
    // 认证失败（用户名密码错误）
} catch (KeyNotFoundException $e) {
    // getOrFail() 时 key 不存在
} catch (EtcdException $e) {
    // 其他 etcd 服务端错误
}
```

目录结构
----

[](#目录结构)

```
src/
├── EtcdClient.php              # 顶层门面
├── Transport/                  # 传输层
│   ├── TransportInterface.php  #   传输抽象接口
│   ├── TransportSelector.php   #   自动选择逻辑
│   ├── HttpTransport.php       #   HTTP JSON 传输（完整可用）
│   └── GrpcTransport.php       #   gRPC 传输（骨架）
├── Kv/KvClient.php             # KV 键值操作
├── Watch/WatchClient.php       # Watch 变更监听
├── Lease/LeaseClient.php       # Lease 租约管理
├── Auth/                       # Auth 认证授权
│   ├── AuthClient.php          #   开关/状态
│   ├── UserClient.php          #   用户 CRUD
│   └── RoleClient.php          #   角色 CRUD + 权限
├── Cluster/ClusterClient.php   # Cluster 集群管理
├── Maintenance/                # Maintenance 运维操作
├── Exception/                  # 异常层次
├── Protobuf/                   # 消息桩（60+ 类）
└── Adapter/                    # 框架适配器
    ├── Laravel/                #   ServiceProvider + Facade
    ├── Hyperf/                 #   ConfigProvider
    ├── ThinkPHP/               #   Service + Facade
    └── Webman/                 #   Plugin

```

开源不易，欢迎支持
---------

[](#开源不易欢迎支持)

微信支付宝[![微信](./docs/weixinpay.png "微信")](./docs/weixinpay.png)[![支付宝](./docs/alipay.png "支付宝")](./docs/alipay.png)---

License
-------

[](#license)

MIT — Copyright (c) 2026 [erik](https://erik.xyz)

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance86

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

71d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/9014941?v=4)[erik](/maintainers/erikwang2013)[@erikwang2013](https://github.com/erikwang2013)

---

Top Contributors

[![erikwang2013](https://avatars.githubusercontent.com/u/9014941?v=4)](https://github.com/erikwang2013 "erikwang2013 (8 commits)")

---

Tags

laravelhyperfthinkphpetcdetcd-clientwebmanetcd-v3

### Embed Badge

![Health badge](/badges/erikwang2013-etcd/health.svg)

```
[![Health](https://phpackages.com/badges/erikwang2013-etcd/health.svg)](https://phpackages.com/packages/erikwang2013-etcd)
```

###  Alternatives

[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k16](/packages/tempest-framework)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

85036.3k](/packages/flow-php-flow)[drupal/core-recommended

Locked core dependencies; require this project INSTEAD OF drupal/core.

6942.5M425](/packages/drupal-core-recommended)[laudis/neo4j-php-client

Neo4j-PHP-Client is the most advanced PHP Client for Neo4j

185702.8k44](/packages/laudis-neo4j-php-client)[bushlanov-dev/max-bot-api-client-php

Max Bot API Client library

486.3k](/packages/bushlanov-dev-max-bot-api-client-php)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
