Panduan ini menunjukkan cara membangun backend tiket acara berbasis NFT yang dapat diskalakan dalam PHP menggunakan Symfony Messenger untuk menangani latensi blockchain dengan aman dan andal.Panduan ini menunjukkan cara membangun backend tiket acara berbasis NFT yang dapat diskalakan dalam PHP menggunakan Symfony Messenger untuk menangani latensi blockchain dengan aman dan andal.

Membangun Sistem Tiket Acara Terdesentralisasi Web3 dengan Symfony 7.4

Persimpangan antara Web3 dan framework web tradisional adalah tempat dimulainya utilitas dunia nyata. Sementara siklus hype datang dan pergi, utilitas Non-Fungible Tokens (NFTs) untuk memverifikasi kepemilikan — khususnya dalam tiket acara — tetap menjadi kasus penggunaan yang solid.

Dalam artikel ini, kita akan membangun tulang punggung Sistem Tiket Acara Terdesentralisasi menggunakan Symfony 7.4 dan PHP 8.3. Kita akan melampaui tutorial dasar dan mengimplementasikan arsitektur tingkat produksi yang menangani sifat asinkron transaksi blockchain menggunakan komponen Symfony Messenger.

Arsitektur

Pendekatan "Senior" mengakui bahwa PHP bukanlah proses yang berjalan lama seperti Node.js. Oleh karena itu, kita tidak mendengarkan event blockchain secara real-time dalam controller. Sebaliknya, kita menggunakan pendekatan hybrid:

  1. Interaksi Langsung (Write): Kita menggunakan Symfony Messenger untuk memindahkan transaksi "Minting" ke worker, mencegah timeout HTTP.
  2. RPC Polling (Read): Kita menggunakan perintah terjadwal untuk memverifikasi status on-chain.
  3. Smart Contract: Kita mengasumsikan kontrak ERC-721 standar yang di-deploy pada chain yang kompatibel dengan EVM (Ethereum, Polygon, Base).

Prasyarat & Stack

  • PHP: 8.3+
  • Symfony: 7.4 (LTS)
  • Blockchain Node: Infura, Alchemy, atau node Hardhat lokal.

Banyak library PHP Web3 yang ditinggalkan atau kurang baik dalam typing. Meskipun web3p/web3.php adalah yang paling terkenal, mengandalkannya sepenuhnya bisa berisiko karena kesenjangan pemeliharaan.

Untuk panduan ini, kita akan menggunakan web3p/web3.php (versi ^0.3) untuk encoding ABI tetapi akan memanfaatkan HttpClient native Symfony untuk transport JSON-RPC yang sebenarnya. Ini memberi kita kontrol penuh atas timeout, retry, dan logging — kritis untuk aplikasi produksi.

Setup Proyek

Pertama, mari install dependensi. Kita membutuhkan runtime Symfony, HTTP client, dan library Web3.

composer create-project symfony/skeleton:"7.4.*" decentralized-ticketing cd decentralized-ticketing composer require symfony/http-client symfony/messenger symfony/uid web3p/web3.php

Pastikan composer.json Anda mencerminkan stabilitas:

{ "require": { "php": ">=8.3", "symfony/http-client": "7.4.*", "symfony/messenger": "7.4.*", "symfony/uid": "7.4.*", "web3p/web3.php": "^0.3.0" } }

Service Blockchain

Kita membutuhkan service yang kuat untuk berkomunikasi dengan blockchain. Kita akan membuat EthereumService yang membungkus panggilan JSON-RPC.

//src/Service/Web3/EthereumService.php namespace App\Service\Web3; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Web3\Utils; class EthereumService { private const JSON_RPC_VERSION = '2.0'; public function __construct( private HttpClientInterface $client, #[Autowire(env: 'BLOCKCHAIN_RPC_URL')] private string $rpcUrl, #[Autowire(env: 'SMART_CONTRACT_ADDRESS')] private string $contractAddress, #[Autowire(env: 'WALLET_PRIVATE_KEY')] private string $privateKey ) {} /** * Reads the owner of a specific Ticket ID (ERC-721 ownerOf). */ public function getTicketOwner(int $tokenId): ?string { // Function signature for ownerOf(uint256) is 0x6352211e // We pad the tokenId to 64 chars (32 bytes) $data = '0x6352211e' . str_pad(Utils::toHex($tokenId, true), 64, '0', STR_PAD_LEFT); $response = $this->callRpc('eth_call', [ [ 'to' => $this->contractAddress, 'data' => $data ], 'latest' ]); if (empty($response['result']) || $response['result'] === '0x') { return null; } // Decode the address (last 40 chars of the 64-char result) return '0x' . substr($response['result'], -40); } /** * Sends a raw JSON-RPC request using Symfony HttpClient. * This offers better observability than standard libraries. */ private function callRpc(string $method, array $params): array { $response = $this->client->request('POST', $this->rpcUrl, [ 'json' => [ 'jsonrpc' => self::JSON_RPC_VERSION, 'method' => $method, 'params' => $params, 'id' => random_int(1, 9999) ] ]); $data = $response->toArray(); if (isset($data['error'])) { throw new \RuntimeException('RPC Error: ' . $data['error']['message']); } return $data; } }

Jalankan tes lokal dengan mengakses getTicketOwner dengan ID yang telah di-mint. Jika Anda mendapat alamat 0x, koneksi RPC Anda berfungsi.

Minting Asinkron dengan Messenger

Transaksi blockchain lambat (15 detik hingga menit). Jangan pernah membuat pengguna menunggu konfirmasi blok dalam request browser. Kita akan menggunakan Symfony Messenger untuk menangani ini di background.

Message

//src/Message/MintTicketMessage.php: namespace App\Message; use Symfony\Component\Uid\Uuid; readonly class MintTicketMessage { public function __construct( public Uuid $ticketId, public string $userWalletAddress, public string $metadataUri ) {} }

Handler

Di sinilah keajaiban terjadi. Kita akan menggunakan helper library web3p/web3.php untuk menandatangani transaksi secara lokal.

Catatan: Dalam lingkungan keamanan tinggi, Anda akan menggunakan Key Management Service (KMS) atau enklave penandatanganan terpisah. Untuk artikel ini, kita menandatangani secara lokal.

//src/MessageHandler/MintTicketHandler.php namespace App\MessageHandler; use App\Message\MintTicketMessage; use App\Service\Web3\EthereumService; use Psr\Log\LoggerInterface; use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Web3\Contract; use Web3\Providers\HttpProvider; use Web3\RequestManagers\HttpRequestManager; use Web3p\EthereumTx\Transaction; #[AsMessageHandler] class MintTicketHandler { public function __construct( private EthereumService $ethereumService, // Our custom service private LoggerInterface $logger, #[Autowire(env: 'BLOCKCHAIN_RPC_URL')] private string $rpcUrl, #[Autowire(env: 'WALLET_PRIVATE_KEY')] private string $privateKey, #[Autowire(env: 'SMART_CONTRACT_ADDRESS')] private string $contractAddress ) {} public function __invoke(MintTicketMessage $message): void { $this->logger->info("Starting mint process for Ticket {$message->ticketId}"); // 1. Prepare Transaction Data (mintTo function) // detailed implementation of raw transaction signing usually goes here. // For brevity, we simulate the logic flow: try { // Logic to get current nonce and gas price via EthereumService // $nonce = ... // $gasPrice = ... // Sign transaction offline to prevent key exposure over network // $tx = new Transaction([...]); // $signedTx = '0x' . $tx->sign($this->privateKey); // Broadcast // $txHash = $this->ethereumService->sendRawTransaction($signedTx); // In a real app, you would save $txHash to the database entity here $this->logger->info("Mint transaction broadcast successfully."); } catch (\Throwable $e) { $this->logger->error("Minting failed: " . $e->getMessage()); // Symfony Messenger will automatically retry based on config throw $e; } } }

Controller

Controller tetap tipis. Ia menerima request, memvalidasi input, membuat entitas tiket "Pending" di database Anda (dihilangkan untuk singkatnya) dan mengirim message.

//src/Controller/TicketController.php: namespace App\Controller; use App\Message\MintTicketMessage; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Uid\Uuid; #[Route('/api/v1/tickets')] class TicketController extends AbstractController { #[Route('/mint', methods: ['POST'])] public function mint(Request $request, MessageBusInterface $bus): JsonResponse { $payload = $request->getPayload(); $walletAddress = $payload->get('wallet_address'); // 1. Basic Validation if (!$walletAddress || !str_starts_with($walletAddress, '0x')) { return $this->json(['error' => 'Invalid wallet address'], 400); } // 2. Generate Internal ID $ticketId = Uuid::v7(); // 3. Dispatch Message (Fire and Forget) $bus->dispatch(new MintTicketMessage( $ticketId, $walletAddress, 'https://api.myapp.com/metadata/' . $ticketId->toRfc4122() )); // 4. Respond immediately return $this->json([ 'status' => 'processing', 'ticket_id' => $ticketId->toRfc4122(), 'message' => 'Minting request queued. Check status later.' ], 202); } }

Konfigurasi & Panduan Gaya

Mengikuti gaya Symfony 7.4, kita menggunakan strict typing dan attributes. Pastikan messenger.yaml Anda dikonfigurasi untuk transport async.

#config/packages/messenger.yaml: framework: messenger: transports: async: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' retry_strategy: max_retries: 3 delay: 1000 multiplier: 2 routing: 'App\Message\MintTicketMessage': async

Verifikasi

Untuk memverifikasi implementasi ini bekerja tanpa deploy ke Mainnet:

Node Lokal: Jalankan blockchain lokal menggunakan Hardhat atau Anvil (Foundry).

npx hardhat node

Environment: Atur .env.local Anda untuk mengarah ke localhost.

BLOCKCHAIN_RPC_URL="http://127.0.0.1:8545" WALLET_PRIVATE_KEY="<one of the test keys provided by hardhat>" SMART_CONTRACT_ADDRESS="<deployed contract address>" MESSENGER_TRANSPORT_DSN="doctrine://default"

Consume: Jalankan worker.

php bin/console messenger:consume async -vv

Request:

curl -X POST https://localhost:8000/api/v1/tickets/mint \ -H "Content-Type: application/json" \ -d '{"wallet_address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"}'

Anda seharusnya melihat worker memproses message dan, jika Anda mengimplementasikan logika penandatanganan transaksi raw secara penuh, hash transaksi akan muncul di konsol Hardhat Anda.

Kesimpulan

Membangun aplikasi Web3 di PHP memerlukan pergeseran pola pikir. Anda tidak hanya membangun aplikasi CRUD; Anda membangun orkestrator untuk state terdesentralisasi.

Dengan menggunakan Symfony 7.4, kita memanfaatkan:

  • HttpClient untuk komunikasi RPC yang andal dan terkontrol.
  • Messenger untuk menangani realitas asinkron blockchain.
  • PHP 8.3 Attributes untuk kode yang bersih dan mudah dibaca.

Arsitektur ini dapat diskalakan. Baik Anda menjual 10 tiket atau 10.000, antrian message bertindak sebagai buffer, memastikan nonce transaksi Anda tidak bertabrakan dan server Anda tidak hang.

Siap menskalakan infrastruktur Web3 Anda?

Mengintegrasikan blockchain memerlukan presisi. Jika Anda memerlukan bantuan mengaudit interaksi smart contract Anda atau menskalakan consumer message Symfony Anda, mari terhubung.

\

Peluang Pasar
Logo 4
Harga 4(4)
$0.02016
$0.02016$0.02016
+2.49%
USD
Grafik Harga Live 4 (4)
Penafian: Artikel yang diterbitkan ulang di situs web ini bersumber dari platform publik dan disediakan hanya sebagai informasi. Artikel tersebut belum tentu mencerminkan pandangan MEXC. Seluruh hak cipta tetap dimiliki oleh penulis aslinya. Jika Anda meyakini bahwa ada konten yang melanggar hak pihak ketiga, silakan hubungi [email protected] agar konten tersebut dihapus. MEXC tidak menjamin keakuratan, kelengkapan, atau keaktualan konten dan tidak bertanggung jawab atas tindakan apa pun yang dilakukan berdasarkan informasi yang diberikan. Konten tersebut bukan merupakan saran keuangan, hukum, atau profesional lainnya, juga tidak boleh dianggap sebagai rekomendasi atau dukungan oleh MEXC.