PHP 与以太坊交互,使用 Geth 进行节点通信与开发实践

投稿 2026-03-12 4:09 点击数: 3

随着区块链技术的飞速发展,以太坊作为全球领先的智能合约平台,吸引了无数开发者的目光,PHP 作为一种广泛使用的服务器端脚本语言,在企业级应用和 Web 开发中占据着重要地位,如何将 PHP 与以太坊结合,利用 PHP 的强大功能来构建与区块链交互的应用呢?Geth(Go Ethereum)作为以太坊的官方客户端之一,为我们提供了与以太坊网络通信的基础,本文将探讨如何通过 PHP 与 Geth 结合,实现与以太坊网络的交互。

以太坊与 Geth:基础概览

以太坊不仅仅是一个加密货币平台,更是一个去中心化的、可编程的区块链网络,它允许开发者通过智能合约在区块链上构建和部署去中心化应用(DApps),以太坊的虚拟机(EVM)负责执行这些智能合约。

Geth是用 Go 语言编写的以太坊节点客户端,它是目前最流行、功能最全的以太坊客户端之一,通过运行 Geth,用户可以:

  1. 连接到以太坊网络:作为全节点同步区块链数据,或作为轻节点/节点连接到其他节点。
  2. 管理账户:创建、导入、导出以太坊账户,管理私钥。
  3. 发送交易:向其他账户转移 ETH,或部署、调用智能合约。
  4. 挖矿(可选):为以太坊网络提供算力,获得区块奖励。
  5. 提供 JSON-RPC 接口:这是 PHP 与 Geth 交互的关键,Geth 通过 HTTP 或 WebSocket 暴露标准的 JSON-RPC API,允许外部程序(如 PHP 脚本)远程控制和管理节点。

PHP 与 Geth 的桥梁:JSON-RPC

PHP 本身不直接理解以太坊的底层协议,但它擅长通过 HTTP 请求与其他服务通信,Geth 的 JSON-RPC 接口恰好提供了这样一种标准化的通信方式,PHP 可以构建 HTTP 请求,向 Geth 节点的 RPC 端点发送特定的 JSON-RPC 方法调用,并接收返回的 JSON 格式响应。

要启用 Geth 的 JSON-RPC 接口,在启动 Geth 时需要添加相应的参数,

geth --http --http.addr "0.0.0.0" --http.port "8545" --http.api "eth,net,web3,personal,miner"
  • --http: 启用 HTTP JSON-RPC 服务器。
  • --http.addr: 监听地址,"0.0.0.0" 表示监听所有网络接口。
  • --http.port: RPC 服务端口,默认为 8545。
  • --http.api: 指定通过 HTTP API 暴露的 API 模块,如 eth(以太坊核心功能)、net(网络信息)、web3(Web3.js 兼容方法)、personal(账户管理)等。

PHP 与 Geth 交互实践

在 PHP 中,我们可以使用 cURL 扩展或者 file_get_contents() 等函数来发送 HTTP 请求,为了方便起见,这里我们使用 cURL

安装与启动 Geth 确保你已经安装了 Geth,并按照上述方式启动了一个带有 JSON-RPC 接口的节点。

PHP 环境准备 确保你的 PHP 环境已经安装并启用了 cURL 扩展(大多数 PHP 默认安装)。

编写 PHP 脚本调用 Geth API

以下是一些常见的 PHP 与 Geth 交互示例:

示例 1:连接 Geth 并获取节点信息

<?php
$rpcUrl = 'http://localhost:8545';
$requestId = 1;
// 构建 JSON-RPC 请求
$request = [
    'jsonrpc' => '2.0',
    'method' => 'web3_clientVersion', // 获取 Geth 客户端版本
    'params' => [],
    'id' => $requestId
];
// 发送 cURL 请求
$ch = curl_init($rpcUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
$response = curl_exec($ch);
curl_close($ch);
// 解析响应
$result = json_decode($response, true);
if (isset($result['result'])) {
    echo "Geth 客户端版本: " . $result['result'] . "\n";
} else {
    echo "获取版本失败: " . ($result['error']['message'] ?? '未知错误') . "\n";
}
?>

示例 2:获取最新区块号

<?php
$rpcUrl = 'http://localhost:8545';
$requestId = 2;
$request = [
    'jsonrpc' => '2.0',
    'method' => 'eth_blockNumber',
    'params' => [],
    'id' => $requestId
];
$ch = curl_init($rpcUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if (isset($result['result'])) {
    $latestBlockNumber = hexdec($result['result']); // 将十六进制转换为十进制
    echo "最新区块号: " . $latestBlockNumber . "\n";
} else {
    echo "获取最新区块号失败: " . ($result['error']['message'] ?? '未知错误') . "\n";
}
?>

示例 3:获取账户列表(需解锁账户)

<?php
$rpcUrl = 'http://localhost:8545';
$accountId = 'your_account_address_here'; // 替换为你的账户地址
$accountPassword = 'your_account_password'; // 账户密码(注意安全,不要硬编码在生产环境)
// 首先解锁账户
$unlockRequest = [
    'jsonrpc' => '2.0',
    'method' => 'personal_unlockAccount',
    'params' => [$accountId, $accountPassword, 30], // 解锁30秒
   
随机配图
'id' => 3 ]; $ch = curl_init($rpcUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($unlockRequest)); $unlockResponse = curl_exec($ch); curl_close($ch); $unlockResult = json_decode($unlockResponse, true); if (!$unlockResult || !$unlockResult['result']) { echo "解锁账户失败: " . ($unlockResult['error']['message'] ?? '未知错误') . "\n"; exit; } echo "账户解锁成功,\n"; // 然后获取账户余额 $balanceRequest = [ 'jsonrpc' => '2.0', 'method' => 'eth_getBalance', 'params' => [$accountId, 'latest'], // 'latest' 表示最新区块 'id' => 4 ]; $ch = curl_init($rpcUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($balanceRequest)); $balanceResponse = curl_exec($ch); curl_close($ch); $balanceResult = json_decode($balanceResponse, true); if (isset($balanceResult['result'])) { $balanceInWei = hexdec($balanceResult['result']); // Wei 是以太坊的最小单位 $balanceInEth = $balanceInWei / 1e18; // 转换为 ETH echo "账户 " . $accountId . " 的余额: " . $balanceInEth . " ETH\n"; } else { echo "获取账户余额失败: " . ($balanceResult['error']['message'] ?? '未知错误') . "\n"; } // 锁定账户(可选,但推荐) $lockRequest = [ 'jsonrpc' => '2.0', 'method' => 'personal_lockAccount', 'params' => [$accountId], 'id' => 5 ]; $ch = curl_init($rpcUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($lockRequest)); curl_exec($ch); curl_close($ch); echo "账户已锁定,\n"; ?>

**示例 4