在区块链技术快速发展的今天,以太坊作为最成熟的智能合约平台之一,吸引了大量开发者的关注,PHP作为广泛应用于Web开发的服务器端语言,如何与以太坊进行高效对接?本文将从环境搭建、核心库选择、源码实现到实战案例,全面讲解PHP对接以太坊的全流程,帮助开发者快速掌握这一技术。

环境准备:搭建PHP与以太坊的交互基础

在开始对接之前,需要确保开发环境满足以下条件:

PHP环境

推荐使用PHP 7.4 版本(支持最新的JSON-RPC处理和异步特性),通过以下命令检查PHP版本:

php -v

确保已安装必要的扩展:

  • curl:用于发送HTTP请求
  • json:用于数据序列化与反序列化
  • openssl:用于加密签名(可选,涉及交易签名时需要)

以太坊节点

PHP对接以太坊通常通过JSON-RPC协议与以太坊节点通信,因此需要运行一个以太坊节点,可选方案包括:

  • 本地私有节点:使用Geth(以太坊官方客户端)搭建本地节点,适合开发测试
  • 远程公共节点:使用Infura、Alchemy等第三方服务,无需同步全节点,适合快速开发
  • 测试网节点:在Ropsten、Goerli等测试网环境部署,避免消耗主网ETH

以Geth搭建本地私有节点为例,执行以下命令启动节点(开启RPC服务):

geth --datadir "./ethdata" --dev --http --http.addr "0.0.0.0" --http.port "8545" --http.api "eth,net,web3,personal"

参数说明:

  • --dev:开发模式,使用预分配的测试账户
  • --http:开启HTTP-RPC服务
  • --http.api:暴露的API接口,包括eth(交易相关)、net(网络状态)、web3(基础方法)等

核心库选择:PHP以太坊交互工具推荐

PHP本身没有内置以太坊交互功能,但可以通过以下库简化开发:

Web3.php(官方推荐)

Web3.php是以太坊官方PHP库,支持JSON-RPC调用、合约交互、交易签名等功能,是目前最成熟的PHP以太坊解决方案。

Ethabi.php(合约编码辅助)

Ethabi.php用于处理以太坊ABI(Application Binary Interface),实现参数编码与解码,是智能合约交互的重要工具。

第三方服务SDK

如Infura PHP SDK、Alchemy PHP SDK,封装了与远程节点的通信,适合快速接入。

本文以Web3.php为核心,结合Ethabi.php,从源码层面讲解对接实现。

PHP对接以太坊源码实现

安装Web3.php

通过Composer安装Web3.php:

composer require sc0vu79/web3.php

连接以太坊节点

创建EthConnection.php文件,实现节点连接逻辑:

<?php
require_once 'vendor/autoload.php';
use Web3\Web3;
use Web3\Providers\HttpProvider;
use Web3\RequestManagers\HttpRequestManager;
class EthConnection {
    private $web3;
    public function __construct($nodeUrl) {
        // 创建HTTP Provider
        $provider = new HttpProvider(new HttpRequestManager($nodeUrl, 2)); // 2为超时时间(秒)
        $this->web3 = new Web3($provider);
    }
    /**
     * 检查节点连接状态
     */
    public function checkConnection() {
        $this->web3->getVersion(function ($err, $version) {
            if ($err) {
                echo "连接失败: " . $err->getMessage() . "\n";
            } else {
                echo "节点版本: " . $version . "\n";
            }
        });
    }
}
// 使用示例
$nodeUrl = 'http://127.0.0.1:8545'; // 本地节点地址
$eth = new EthConnection($nodeUrl);
$eth->checkConnection();

源码解析

  • HttpProvider:封装了HTTP请求逻辑,负责向节点发送JSON-RPC请求
  • HttpRequestManager:管理HTTP请求的配置(如URL、超时时间)
  • web3->getVersion():调用节点的web3_version接口,验证连接是否正常

获取账户信息

以太坊节点中的账户是交易和合约交互的基础,以下代码获取账户列表及账户余额:

<?php
require_once 'EthConnection.php';
class AccountManager {
    private $web3;
    private $eth;
    public function __construct($web3) {
        $this->web3 = $web3;
        $this->eth = $web3->eth;
    }
    /**
     * 获取账户列表
     */
    public function getAccounts() {
        $this->eth->accounts(function ($err, $accounts) {
            if ($err) {
                echo "获取账户失败: " . $err->getMessage() . "\n";
            } else {
                echo "账户列表: " . implode(', ', $accounts) . "\n";
            }
        });
    }
    /**
     * 获取账户余额(单位:ETH)
     */
    public function getBalance($account) {
        $this->eth->getBalance($account, function ($err, $balance) {
            if ($err) {
                echo "获取余额失败: " . $err->getMessage() . "\n";
            } else {
                // 将余额从Wei转换为ETH(1 ETH = 1e18 Wei)
                $ethBalance = bcdiv($balance->toString(), '1000000000000000000', 18);
                echo "账户余额: " . $ethBalance . " ETH\n";
            }
        });
    }
}
// 使用示例
$ethConn = new EthConnection('http://127.0.0.1:8545');
$accountManager = new AccountManager($ethConn->getWeb3());
$accountManager->getAccounts();
$accountManager->getBalance('0xYourAccountAddress'); // 替换为实际账户地址

源码解析

  • $this->eth->accounts:调用eth_accounts接口,获取节点管理的账户列表
  • $this->eth->getBalance:调用eth_getBalance接口,返回账户余额(默认单位为Wei,需手动转换为ETH)
  • bcdiv:使用BC Math库处理高精度除法,避免浮点数精度问题

发送交易

交易是以太坊网络中价值转移的核心操作,以下代码实现从指定账户发送ETH到目标地址:

<?php
require_once 'EthConnection.php';
class TransactionSender {
    private $web3;
    private $eth;
    public function __construct($web3) {
        $this->web3 = $web3;
        $this->eth = $web3->eth;
    }
    /**
     * 发送ETH交易
     * @param string $fromAddress 发送方地址
     * @param string $toAddress 接收方地址
     * @param string $value 发送金额(单位:ETH)
     * @param string $privateKey 发送方私钥(用于签名)
     */
    public function sendTransaction($fromAddress, $toAddress, $value, $privateKey) {
        // 将ETH转换为Wei
        $weiValue = bcmul($value, '1000000000000000000', 0);
        // 构建交易参数
        $transaction = [
            'from' => $fromAddress,
            'to' => $toAddress,
            'value' => '0x' . dechex($weiValue), // 十六进制Wei值
            'gas' => '0x5208', // 普通交易Gas限制(21000)
            'gasPrice' => '0x9184e72a000', // Gas价格(默认20 Gwei)
        ];
        // 发送交易(需解锁账户或使用私钥签名)
        $this->eth->sendTransaction($transaction, $privateKey, function ($err, $txHash) {
            if ($err) {
                echo "交易发送失败: " . $err->getMessage() . "\n";
            } else {
                echo "交易哈希: " . $txHash . "\n";
            }
        });
    }
}
// 使用示例
$ethConn = new EthConnection('http://127.0.0.1:8545');
$txSender = new TransactionSender($ethConn->getWeb3());
$txSender->sendTransaction(
    '0xFromAddress', //