本指南展示如何使用 Symfony Messenger 在 PHP 中构建可扩展的基于 NFT 的活动票务后端,以安全可靠地处理区块链延迟。本指南展示如何使用 Symfony Messenger 在 PHP 中构建可扩展的基于 NFT 的活动票务后端,以安全可靠地处理区块链延迟。

使用 Symfony 7.4 构建去中心化活动票务系统 Web3

Web3 dan rangka kerja web tradisional bersilang di mana utiliti dunia sebenar bermula. Walaupun kitaran gembar-gembur datang dan pergi, utiliti Token Tidak Boleh Fungible (NFT) untuk mengesahkan pemilikan — khususnya dalam tiket acara — kekal sebagai kes penggunaan yang kukuh.

Dalam artikel ini, kita akan membina tulang belakang Sistem Tiket Acara Terdesentralisasi menggunakan Symfony 7.4 dan PHP 8.3. Kita akan melangkaui tutorial asas dan melaksanakan seni bina gred pengeluaran yang mengendalikan sifat asinkronus transaksi blockchain menggunakan komponen Symfony Messenger.

Seni Bina

Pendekatan "Senior" mengakui bahawa PHP bukanlah proses berjalan lama seperti Node.js. Oleh itu, kita tidak mendengar peristiwa blockchain dalam masa nyata dalam pengawal. Sebaliknya, kita menggunakan pendekatan hibrid:

  1. Interaksi Langsung (Tulis): Kita menggunakan Symfony Messenger untuk memindahkan transaksi "Minting" kepada pekerja, mencegah tamat masa HTTP.
  2. Pengundian RPC (Baca): Kita menggunakan arahan berjadual untuk mengesahkan status on-chain.
  3. Kontrak Pintar: Kita menganggap kontrak ERC-721 standard yang digunakan pada rantai serasi EVM (Ethereum, Polygon, Base).

Prasyarat & Stack

  • PHP: 8.3+
  • Symfony: 7.4 (LTS)
  • Nod Blockchain: Infura, Alchemy, atau nod Hardhat tempatan.

Banyak perpustakaan PHP Web3 ditinggalkan atau ditaip dengan buruk. Walaupun web3p/web3.php adalah yang paling terkenal, bergantung sepenuhnya padanya boleh berisiko kerana jurang penyelenggaraan.

Untuk panduan ini, kita akan menggunakan web3p/web3.php (versi ^0.3) untuk pengekodan ABI tetapi akan memanfaatkan HttpClient asli Symfony untuk pengangkutan JSON-RPC sebenar. Ini memberi kita kawalan penuh ke atas tamat masa, percubaan semula dan pembalakan — kritikal untuk aplikasi pengeluaran.

Persediaan Projek

Pertama, mari kita pasang kebergantungan. Kita memerlukan runtime Symfony, klien HTTP dan perpustakaan 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 kestabilan:

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

Perkhidmatan Blockchain

Kita memerlukan perkhidmatan yang kukuh untuk bercakap dengan blockchain. Kita akan mencipta 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 ujian tempatan mengakses getTicketOwner dengan ID yang diketahui telah dicetak. Jika anda mendapat alamat 0x, sambungan RPC anda berfungsi.

Pencetakan Asinkronus dengan Messenger

Transaksi blockchain adalah perlahan (15 saat hingga minit). Jangan sekali-kali membuat pengguna menunggu pengesahan blok dalam permintaan pelayar. Kita akan menggunakan Symfony Messenger untuk mengendalikan ini di latar belakang.

Mesej

//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 ) {} }

Pengendali

Di sinilah keajaiban berlaku. Kita akan menggunakan pembantu perpustakaan web3p/web3.php untuk menandatangani transaksi secara tempatan.

Nota: Dalam persekitaran keselamatan tinggi, anda akan menggunakan Perkhidmatan Pengurusan Kunci (KMS) atau enklaf tandatangan berasingan. Untuk artikel ini, kita menandatangani secara tempatan.

//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; } } }

Pengawal

Pengawal kekal nipis. Ia menerima permintaan, mengesahkan input, mencipta entiti tiket "Pending" dalam pangkalan data anda (ditinggalkan untuk ringkas) dan menghantar mesej.

//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 taip ketat dan atribut. Pastikan messenger.yaml anda dikonfigurasikan untuk pengangkutan 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

Pengesahan

Untuk mengesahkan pelaksanaan ini berfungsi tanpa menggunakan ke Mainnet:

Nod Tempatan: Jalankan blockchain tempatan menggunakan Hardhat atau Anvil (Foundry).

npx hardhat node

Persekitaran: Tetapkan .env.local anda untuk menunjuk 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"

Gunakan: Mulakan pekerja.

php bin/console messenger:consume async -vv

Permintaan:

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

Anda sepatutnya melihat pekerja memproses mesej dan, jika anda melaksanakan logik tandatangan transaksi mentah sepenuhnya, hash transaksi muncul dalam konsol Hardhat anda.

Kesimpulan

Membina aplikasi Web3 dalam PHP memerlukan perubahan pemikiran. Anda bukan hanya membina aplikasi CRUD; anda membina orkestrator untuk keadaan terdesentralisasi.

Dengan menggunakan Symfony 7.4, kita memanfaatkan:

  • HttpClient untuk komunikasi RPC yang boleh dipercayai dan boleh dikawal.
  • Messenger untuk mengendalikan realiti asinkronus blockchain.
  • Atribut PHP 8.3 untuk kod yang bersih dan mudah dibaca.

Seni bina ini berskala. Sama ada anda menjual 10 tiket atau 10,000, baris gilir mesej bertindak sebagai penampan, memastikan nonce transaksi anda tidak berlanggar dan pelayan anda tidak tergantung.

Bersedia untuk meningkatkan infrastruktur Web3 anda?

Mengintegrasikan blockchain memerlukan ketepatan. Jika anda memerlukan bantuan mengaudit interaksi kontrak pintar anda atau meningkatkan penggunaan mesej Symfony anda, mari kita berhubung.

\

市场机遇
4 图标
4实时价格 (4)
$0.02011
$0.02011$0.02011
+2.23%
USD
4 (4) 实时价格图表
免责声明: 本网站转载的文章均来源于公开平台,仅供参考。这些文章不代表 MEXC 的观点或意见。所有版权归原作者所有。如果您认为任何转载文章侵犯了第三方权利,请联系 [email protected] 以便将其删除。MEXC 不对转载文章的及时性、准确性或完整性作出任何陈述或保证,并且不对基于此类内容所采取的任何行动或决定承担责任。转载材料仅供参考,不构成任何商业、金融、法律和/或税务决策的建议、认可或依据。