Ethereum
PHP
web3.php is the established way to reach Ethereum from PHP, and it covers the JSON-RPC surface you need to read balances, send transactions, and call contracts on chain 1. Install it with composer require web3p/web3.php. One thing to know up front: the library predates PHP's async story, so every eth method takes a callback of the form function ($err, $result) rather than returning a value. That style spreads quickly if you sprinkle it across controllers, so wrap it in a service class — like the EthereumService below — that resolves each callback into a plain return value and keeps your application code linear.
web3.php delivers every Ethereum result through a callback rather than a return value. In a Laravel app, push that detail into a service class so controllers ask for an ETH balance and get a string back, with the callback plumbing hidden one layer down.
Web3.php
Construction nests three objects: new Web3(new HttpProvider(new HttpRequestManager('https://ethereum.therpc.io/YOUR_API_KEY'))). The request manager handles the HTTP transport, the provider wraps it as JSON-RPC, and Web3 exposes the namespaces. From there $web3->eth->getBalance(...) hands its result to your callback as ($err, $result). Always check $err first — on a bad address or a transport failure web3.php passes the error there and leaves $result empty, so reading $result without the guard gives you a silent null instead of a thrown exception.
- GitHub: https://github.com/web3p/web3.php
- Packagist: https://packagist.org/packages/web3p/web3.php
- Full Ethereum JSON-RPC support over HTTP
- Contract interaction through the
Contractclass - Transaction handling — build, send, and read receipts
- ETH unit conversion via
utils->fromWei/toWei - ABI encoding and decoding for contract calldata
Laravel Integration
In Laravel, keep the endpoint out of your code: put it in .env and read it through config('services.ethereum.node_url'), so the URL with your key never lands in a commit or a stack trace. The second win is caching. An ETH balance doesn't change between blocks, and Ethereum produces one roughly every 12 seconds, so wrapping the read in Cache::remember($key, 300, ...) serves the same address from cache for a few minutes and spares your CU budget the duplicate calls a busy dashboard would otherwise fire.
Smart Contract Integration
For contracts, construct web3.php's Contract from the provider and ABI, then bind it to a deployed address with ->at($contractAddress). Reads run through ->call($method, $params, $callback), which performs an eth_call against Ethereum and delivers the decoded return value to the callback — no gas, no signing. The same callback discipline applies: check $err before trusting $response, so a reverted balanceOf on an ERC-20 surfaces as an error rather than a misleading zero.
Error Handling
Define an EthereumException that carries the original error alongside your own message. Because web3.php reports failures through the $err callback argument, a thin wrapper that rethrows them as a single typed exception lets the rest of the app use ordinary try/catch and pattern-match one class. The example keeps the raw error reachable through getEthError(), so you can log the exact RPC failure from Ethereum while still showing the user a clean message.