{"id":36988104,"url":"https://github.com/ikilobyte/pulsar-client-php","last_synced_at":"2026-01-13T23:24:29.040Z","repository":{"id":45528264,"uuid":"513352533","full_name":"ikilobyte/pulsar-client-php","owner":"ikilobyte","description":"PHP Native Client library for Apache Pulsar","archived":false,"fork":false,"pushed_at":"2025-11-10T06:26:19.000Z","size":492,"stargazers_count":60,"open_issues_count":7,"forks_count":14,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-11-10T07:24:55.739Z","etag":null,"topics":["pulsar","pulsar-client","pulsar-client-php","pulsar-php"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ikilobyte.png","metadata":{"files":{"readme":"README-CN.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-07-13T02:18:27.000Z","updated_at":"2025-11-10T06:25:55.000Z","dependencies_parsed_at":"2023-10-25T09:49:37.421Z","dependency_job_id":"0782d511-397f-4a7b-b25f-9681c4828bdb","html_url":"https://github.com/ikilobyte/pulsar-client-php","commit_stats":{"total_commits":94,"total_committers":3,"mean_commits":"31.333333333333332","dds":0.2021276595744681,"last_synced_commit":"94873278c7acfe4287e51d2d6e7e0cd6885c3541"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"purl":"pkg:github/ikilobyte/pulsar-client-php","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikilobyte%2Fpulsar-client-php","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikilobyte%2Fpulsar-client-php/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikilobyte%2Fpulsar-client-php/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikilobyte%2Fpulsar-client-php/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ikilobyte","download_url":"https://codeload.github.com/ikilobyte/pulsar-client-php/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ikilobyte%2Fpulsar-client-php/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28404497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T21:51:37.118Z","status":"ssl_error","status_checked_at":"2026-01-13T21:45:14.585Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pulsar","pulsar-client","pulsar-client-php","pulsar-php"],"created_at":"2026-01-13T23:24:28.536Z","updated_at":"2026-01-13T23:24:29.033Z","avatar_url":"https://github.com/ikilobyte.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PHP Native Pulsar Client\n\n# 目录\n\n* [目录](#目录)\n    * [关于](#关于)\n    * [依赖](#依赖)\n    * [安装](#安装)\n    * [生产者](#生产者)\n    * [消费者](#消费者)\n    * [Schema](#Schema)\n    * [Reader](#Reader)\n    * [可选项配置](#可选项配置)\n    * [License](#License)\n\n## 关于\n\n[English](README.md) | 中文\n\n这是一个用php实现的[Apache Pulsar](https://pulsar.apache.org)客户端库，基于[PulsarApi.proto](src/PulsarApi.proto)\n，且支持Swoole协程环境\n\n功能\n\n- Support URL (`pulsar://` 、 `pulsar+ssl://` 、 `http://` 、 `https://`)\n- Multi topic consumers\n- TLS connection\n- Automatic reconnection (Only Consumer)\n- Message batching\n- Message Properties\n- Compression with `zstd`, `zlib`\n- Authentication with `jwt`, `basic`\n\n## 依赖\n\n* PHP \u003e=7.1\n* ZLib Extension（如果你想使用`zlib`压缩）\n* Zstd Extension（如果你想使用`zstd`压缩）\n* Swoole Extension（如果你想在swoole中使用）\n    * 只需要配置`SWOOLE_HOOK_SOCKETS、SWOOLE_HOOK_STREAM_FUNCTION` 或者 `SWOOLE_HOOK_ALL`\n\n## 提示\n\n* 如果出现以下报错，请安装`gmp`或`bcmath`扩展来解决\n\n```bash\nNegative integers are only supported with GMP or BC (64bit) intextensions. \n```\n\n## 安装\n\n```bash\ncomposer require ikilobyte/pulsar-client-php\n```\n\n## 生产者\n\n```php\n\u003c?php\n\nuse Pulsar\\Authentication\\Jwt;\nuse Pulsar\\Compression\\Compression;\nuse Pulsar\\Producer;\nuse Pulsar\\ProducerOptions;\n\nrequire_once __DIR__ . '/vendor/autoload.php';\n\n$options = new ProducerOptions();\n\n// If permission authentication is available\n// Only JWT authentication is currently supported\n$options-\u003esetAuthentication(new Jwt('token')); \n\n$options-\u003esetConnectTimeout(3);\n$options-\u003esetTopic('persistent://public/default/demo');\n$options-\u003esetCompression(Compression::ZLIB);\n$producer = new Producer('pulsar://localhost:6650', $options);\n// or use pulsar proxy address\n//$producer = new Producer('http://localhost:8080', $options);\n\n$producer-\u003econnect();\n\nfor ($i = 0; $i \u003c 10; $i++) {\n    $messageID = $producer-\u003esend(sprintf('hello %d',$i));\n    \n    $messageID = $producer-\u003esend(sprintf('hello %d',$i),[\n        MessageOptions::PROPERTIES =\u003e [\n           'key' =\u003e 'value',\n           'ms'  =\u003e microtime(true),\n        ]\n    ]);\n    echo 'messageID ' . $messageID . \"\\n\";\n}\n\n// Sending delayed messages\nfor ($i = 0; $i \u003c 10; $i++) {\n    $producer-\u003esend(sprintf('hello-delay %d',$i),[\n        \\Pulsar\\MessageOptions::DELAY_SECONDS =\u003e $i * 5, // Seconds\n    ]);\n}\n\n// Send Batch message \n$messages = [];\nfor ($i = 0;$i \u003c 10;$i++) {\n  $messages[] = json_encode([\n        'id'    =\u003e $i,\n        'now'   =\u003e date('Y-m-d H:i:s')\n  ]);\n}\n\n$messageID = $producer-\u003esend($messages);\necho \"batch message id ${messageID}\\n\";\n\n// close\n$producer-\u003eclose();\n\n```\n\n\u003e 保持连接\n\n* 依赖 `Swoole` 扩展，必须开启协程\n* 如果是常驻内存应用，建议开启\n* 会保持连接，无需反复建立连接\n* 可以通过 `$producer-\u003eclose()` 关闭连接，但不应该去调用\n* 请看[示例](./examples/producer-keepalive.php)\n\n```php\n$options-\u003esetKeepalive(true);\n```\n\n\u003e 消息去重\n\n* 消息消重是pulsar提供的一项功能，它基于生产者名称和序列号ID\n* 同一生产者的名称需要是固定而且是唯一的，一般根据业务纬度区分即可，每条消息的序列号ID是唯一而且是自增的。\n* [参考 Pulsar Docs](https://pulsar.apache.org/docs/next/concepts-messaging#message-deduplication)\n\n```php\n$options = new ProducerOptions();\n$options-\u003esetProducerName('name');\n\n$producer = new Producer('pulsar://localhost:6650', $options);\n$producer-\u003esend('body',[\n    \\Pulsar\\MessageOptions::SEQUENCE_ID =\u003e 123456,\n]);\n```\n\n## 消费者\n\n```php\n\u003c?php\n\nuse Pulsar\\Authentication\\Jwt;\nuse Pulsar\\Consumer;\nuse Pulsar\\ConsumerOptions;\nuse Pulsar\\SubscriptionType;\nuse Pulsar\\Proto\\CommandSubscribe\\InitialPosition;\n\nrequire_once __DIR__ . '/vendor/autoload.php';\n\n$options = new ConsumerOptions();\n\n// If permission authentication is available\n// Only JWT authentication is currently supported\n$options-\u003esetAuthentication(new Jwt('token'));\n\n$options-\u003esetConnectTimeout(3);\n$options-\u003esetTopic('persistent://public/default/demo');\n$options-\u003esetSubscription('logic');\n$options-\u003esetSubscriptionType(SubscriptionType::Shared);\n\n// Initial position at which to set cursor when subscribing to a topic at first time.\t\n// default use InitialPosition::Latest()\n// $options-\u003esetSubscriptionInitialPosition(InitialPosition::Earliest());\n\n// Configure how many seconds Nack's messages are redelivered, the default is 1 minute\n$options-\u003esetNackRedeliveryDelay(20);\n\n$consumer = new Consumer('pulsar://localhost:6650', $options);\n// or use pulsar proxy address\n//$consumer = new Consumer('http://localhost:8080', $options);\n\n$consumer-\u003econnect();\n\nwhile (true) {\n    $message = $consumer-\u003ereceive();\n    \n    // get properties\n    var_export($message-\u003egetProperties());\n    \n    echo sprintf('Got message 【%s】messageID[%s] topic[%s] publishTime[%s] redeliveryCount[%d]',\n        $message-\u003egetPayload(),\n        $message-\u003egetMessageId(),\n        $message-\u003egetTopic(),\n        $message-\u003egetPublishTime(),\n        $message-\u003egetRedeliveryCount()\n    ) . \"\\n\";\n    \n    // ... \n    \n    // Remember to confirm that the message is complete after processing\n    $consumer-\u003eack($message);\n    \n    // When processing fails, you can also execute the Nack\n    // The message will be re-delivered after the specified time\n    // $consumer-\u003enack($message);\n}\n\n$consumer-\u003eclose();\n```\n\n\u003e 批量接收消息\n\n- 只有当生产者批量发送消息时，才能接收到批量消息。\n\n```php\n$messages = $consumer-\u003ebatchReceive();\nforeach ($messages as $message) {\n    // ...\n    \n    // Ack\n    $consumer-\u003eack($message);\n}\n```\n\n\u003e 订阅多个主题\n\n```php\n$options-\u003esetTopics([\n    'persistent://public/default/demo-1',\n    'persistent://public/default/demo-2',\n    'persistent://public/default/demo-3',\n    //....\n]);\n```\n\n\u003e 死信队列\n\n```php\n// Assuming that the subject matter is： \u003ctopicname\u003e-\u003csubscriptionname\u003e-DLQ\n$options-\u003esetDeadLetterPolicy(6);\n\n// Custom topic name\n$options-\u003esetDeadLetterPolicy(6,'persistent://public/default/demo-dead');\n\n// Custom subscription name\n$options-\u003esetDeadLetterPolicy(6,'persistent://public/default/demo-dead','sub-name');\n```\n\n\u003e 自动重连（仅支持消费者）\n\n```php\n// start reconnect\n$options-\u003esetReconnectPolicy(true);\n\n// Reconnect interval(seconds)\n$options-\u003esetReconnectPolicy(true,3);\n\n// Maximum number of reconnections\n$options-\u003esetReconnectPolicy(true,3,100);\n```\n\n\u003e 不循环接收消息，且平滑退出\n\n```php\n\n$running = true;\n\n// kill -15 $PID  \npcntl_signal(SIGTERM,function() use (\u0026$running){\n    $running = false;\n});\n\nwhile ($running) {\n    try {\n        $message = $consumer-\u003ereceive(false);\n        \n        // ...\n    } catch (\\Pulsar\\Exception\\MessageNotFound $e) {\n            \n        if ($e -\u003egetCode() != \\Pulsar\\Exception\\MessageNotFound::Ignore) {\n            die($e-\u003egetMessage());\n        }\n        \n        echo \"Message Not Found\\n\";\n        continue;\n    } catch (Throwable $e) {\n        echo $e-\u003egetMessage() . \"\\n\";\n        throw $e;\n    } finally {\n        pcntl_signal_dispatch();\n    }\n}\n```\n\n## TLS\n\n- 证书配置请参考[官方文档](https://pulsar.apache.org/docs/next/security-tls-transport/)\n\n- 示例\n\n```php\n$tls = new \\Pulsar\\TLSOptions('./cert.pem','./cert.key.pem');\n\n// CA Cert\n$tls-\u003esetTrustCertsFilePath('./ca.cert.pem');\n\n// 无证书建立TLS连接\n//$tls = new \\Pulsar\\TLSOptions('','');\n\n// optional\n$tls-\u003esetAllowInsecureConnection(false);\n$tls-\u003esetValidateHostname(true);\n$options-\u003esetTLS($tls);\n\n$consumer = new \\Pulsar\\Consumer('pulsar+ssl://localhost:6651',$options);\n//$producer = new \\Pulsar\\Producer('pulsar+ssl://localhost:6651',$options);\n\n// or https\n$consumer = new \\Pulsar\\Consumer('https://localhost:8081',$options);\n//$producer = new \\Pulsar\\Producer('https://localhost:8081',$options);\n```\n\n## Schema\n\n- 目前只支持 `INT8`、`INT16`、`INT32`、`INT64`、`DOUBLE`、`STRING`、`JSON`，以下代码以 `JSON Schema` 为示例\n- https://pulsar.apache.org/docs/2.11.x/schema-overview/\n- https://avro.apache.org/docs/1.11.1/specification/\n\n- `model.php`\n\n```php\n\u003c?php\n\nclass Person\n{\n    public $id;\n    public $name;\n    public $age;\n    // ...\n}\n```\n\n- 生产者配置`Schema`\n\n```php\n\u003c?php\n$define = '{\"type\":\"record\",\"name\":\"Person\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"int\"}]}';\n$schema = new \\Pulsar\\Schema\\SchemaJson($define, [\n    'key' =\u003e 'value',\n]);\n\n// ... some code\n$producerOptions-\u003esetSchema($schema);\n$producer = new \\Pulsar\\Producer('xx',$options);\n$producer-\u003econnect();\n\n$person = new Person();\n$person-\u003eid = 1;\n$person-\u003ename = 'Tony';\n$person-\u003eage = 18;\n\n// 可以直接发送 $person 对象\n$id = $producer-\u003esend($person);\n```\n\n- 消费者配置`Schema`\n\n ```php\n\u003c?php\n$define = '{\"type\":\"record\",\"name\":\"Person\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"age\",\"type\":\"int\"}]}';\n\n$schema = new \\Pulsar\\Schema\\SchemaJson($define, [\n    'key' =\u003e 'value',\n]);\n\n// ... 省略一些初始化的代码\n$consumerOptions-\u003esetSchema($schema);\n$consumer = new \\Pulsar\\Consumer('pulsar://xxx',$consumerOptions);\n$consumer-\u003econnect();\n\nwhile (true) {\n    $message = $consumer-\u003ereceive();\n    $person = new Person();\n    $message-\u003egetSchemaValue($person);\n    echo sprintf(\n        'payload %s id %d name %s age %d',\n        $message-\u003egetPayload(),\n        $person-\u003eid,\n        $person-\u003ename,\n        $person-\u003eage\n    ) . \"\\n\";\n    \n    // .. some code\n}\n\n```\n\n## Reader\n\n```php\n\u003c?php\nuse Pulsar\\Message;\nuse Pulsar\\Reader;\nuse Pulsar\\ReaderOptions;\n\nrequire_once __DIR__ . '/../vendor/autoload.php';\n\n\n$options = new ReaderOptions();\n\n// If permission authentication is available\n// Only JWT authentication is currently supported\n// $options-\u003esetAuthentication(new Jwt('token'));\n\n$options-\u003esetConnectTimeout(3);\n$options-\u003esetTopic('persistent://public/default/demo'); // support partition topic\n\n// Read the latest message\n$options-\u003esetStartMessageID(Message::latestMessageIdData());\n\n// From the earliest message\n// $options-\u003esetStartMessageID(Message::earliestMessageIdData());\n\n// Start reading from a message\n// $options-\u003esetStartMessageID(Message::deserialize('621:103:0'));\n\n$reader = new Reader('pulsar://localhost:6650', $options);\n$reader-\u003econnect();\n\nwhile (true) {\n    $message = $reader-\u003enext();\n    echo sprintf('Got message 【%s】messageID[%s]  topic[%s] publishTime[%s]',\n            $message-\u003egetPayload(),\n            $message-\u003egetMessageId(),\n            $message-\u003egetTopic(),\n            $message-\u003egetPublishTime()\n        ) . \"\\n\";\n\n}\n\n$reader-\u003eclose();\n```\n\n## 可选项配置\n\n* ProducerOptions\n    * setTopic()\n    * setAuthentication()\n    * setConnectTimeout()\n    * setProducerName()\n    * setCompression()\n    * setSchema()\n* ConsumerOptions\n    * setTopic()\n    * setTopics()\n    * setAuthentication()\n    * setConnectTimeout()\n    * setConsumerName()\n    * setSubscription()\n    * setSubscriptionType()\n    * setNackRedeliveryDelay()\n    * setReceiveQueueSize()\n    * setDeadLetterPolicy()\n    * setSubscriptionInitialPosition()\n    * setReconnectPolicy()\n    * setSchema()\n* ReaderOptions\n    * setTopic()\n    * setAuthentication()\n    * setConnectTimeout()\n    * setReaderName()\n    * setStartMessageID()\n    * setReceiveQueueSize()\n* MessageOptions\n    * DELAY_SECONDS\n    * SEQUENCE_ID\n    * PROPERTIES\n* TLSOption (v1.3.0)\n    * __construct(string $certFilePath, string $keyFilePath)\n    * setTrustCertsFilePath()\n    * setValidateHostname()\n    * setAllowInsecureConnection()\n\n## MessageNotFound 错误码（v1.2.1）\n\n* `MessageNotFound::Ignore`\n* `MessageNotFound::CommandParseFail`\n\n## License\n\n[MIT](LICENSE) LICENSE","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikilobyte%2Fpulsar-client-php","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fikilobyte%2Fpulsar-client-php","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fikilobyte%2Fpulsar-client-php/lists"}