Examples
Exemplos PHP
Exemplos completos de integração com PHP, Laravel, Symfony e mais
Exemplos PHP
Exemplos práticos e completos de como integrar o RenderHub em aplicações PHP.
Instalação
composer require guzzlehttp/guzzle vlucas/phpdotenv
Configuração Básica
Variáveis de Ambiente
Crie um arquivo .env:
RENDERHUB_API_KEY=rh_live_sua_chave_aqui
RENDERHUB_BASE_URL=https://renderhub.com/api/v1
Cliente RenderHub
<?php
// lib/RenderHubClient.php
require_once __DIR__ . '/../vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Dotenv\Dotenv;
class RenderHubClient
{
private $client;
private $apiKey;
private $baseUrl;
public function __construct($apiKey = null)
{
// Carregar .env
$dotenv = Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();
$this->apiKey = $apiKey ?? $_ENV['RENDERHUB_API_KEY'];
$this->baseUrl = $_ENV['RENDERHUB_BASE_URL'] ?? 'https://renderhub.com/api/v1';
if (!$this->apiKey) {
throw new Exception('RENDERHUB_API_KEY não configurada');
}
$this->client = new Client([
'base_uri' => $this->baseUrl,
'headers' => [
'Authorization' => 'Bearer ' . $this->apiKey,
'Content-Type' => 'application/json'
],
'timeout' => 30
]);
}
public function render($options)
{
try {
$response = $this->client->post('/render', [
'json' => $options
]);
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
$this->handleError($e);
}
}
public function createTemplate($template)
{
try {
$response = $this->client->post('/templates', [
'json' => $template
]);
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
$this->handleError($e);
}
}
public function getTemplate($templateId)
{
try {
$response = $this->client->get("/templates/{$templateId}");
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
$this->handleError($e);
}
}
public function savePdf($pdfBase64, $filename)
{
$pdfBytes = base64_decode($pdfBase64);
file_put_contents($filename, $pdfBytes);
}
private function handleError($exception)
{
if ($exception->hasResponse()) {
$response = $exception->getResponse();
$status = $response->getStatusCode();
$body = json_decode($response->getBody(), true);
switch ($status) {
case 401:
throw new Exception("Erro de autenticação: " . ($body['message'] ?? 'Chave inválida'));
case 403:
throw new Exception("Quota excedida: " . ($body['message'] ?? ''));
case 429:
$retryAfter = $body['retry_after'] ?? 60;
throw new Exception("Rate limit excedido. Tente novamente em {$retryAfter}s");
default:
throw new Exception("Erro {$status}: " . ($body['message'] ?? 'Erro desconhecido'));
}
}
throw $exception;
}
}
Exemplo 1: Converter HTML para PDF
<?php
// examples/convert_html.php
require_once __DIR__ . '/../lib/RenderHubClient.php';
function convertHtmlToPdf()
{
$client = new RenderHubClient();
$html = <<<HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body {
font-family: Arial, sans-serif;
padding: 40px;
max-width: 800px;
margin: 0 auto;
}
h1 {
color: #2563eb;
border-bottom: 3px solid #2563eb;
padding-bottom: 10px;
}
.highlight {
background: #fef3c7;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
}
</style>
</head>
<body>
<h1>Relatório de Vendas - Janeiro 2024</h1>
<div class="highlight">
<h2>Resumo</h2>
<p>Total de vendas: R$ 150.000,00</p>
<p>Novos clientes: 42</p>
<p>Taxa de conversão: 15.8%</p>
</div>
<h2>Detalhes</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
</body>
</html>
HTML;
$result = $client->render([
'mode' => 'CONVERT',
'input_type' => 'html',
'data' => $html,
'page_size' => 'A4',
'orientation' => 'portrait'
]);
// Salvar PDF
$client->savePdf($result['pdf_base64'], 'relatorio.pdf');
echo "✅ PDF gerado com sucesso!\n";
echo "Páginas: {$result['pages']}\n";
echo "Tamanho: {$result['file_size_kb']} KB\n";
echo "Duração: {$result['duration_ms']}ms\n";
}
convertHtmlToPdf();
Exemplo 2: Fatura com Template
<?php
// examples/generate_invoice.php
require_once __DIR__ . '/../lib/RenderHubClient.php';
function createInvoiceTemplate()
{
$client = new RenderHubClient();
$templateHtml = file_get_contents(__DIR__ . '/../templates/invoice.html');
$template = $client->createTemplate([
'name' => 'invoice-template-v1',
'description' => 'Template de fatura padrão',
'category' => 'invoice',
'content' => $templateHtml,
'variables' => [
['name' => 'company_name', 'type' => 'string', 'required' => true],
['name' => 'invoice_number', 'type' => 'string', 'required' => true],
['name' => 'customer_name', 'type' => 'string', 'required' => true],
['name' => 'items', 'type' => 'array', 'required' => true],
['name' => 'total', 'type' => 'string', 'required' => true]
]
]);
echo "Template criado: {$template['id']}\n";
return $template['id'];
}
function generateInvoice($customerId, $templateId)
{
$client = new RenderHubClient();
// Buscar dados do cliente (simulado)
$customer = [
'id' => $customerId,
'name' => 'João Silva Comércio LTDA',
'email' => 'joao@example.com',
'address' => 'Rua das Flores, 123',
'city' => 'São Paulo',
'state' => 'SP'
];
$orders = [
['product' => 'Notebook Dell', 'quantity' => 2, 'price' => 3500.00],
['product' => 'Mouse Logitech', 'quantity' => 5, 'price' => 150.00],
['product' => 'Teclado Mecânico', 'quantity' => 3, 'price' => 450.00]
];
// Mapear dados para o template
$items = array_map(function($order) {
return [
'description' => $order['product'],
'quantity' => $order['quantity'],
'unit_price' => number_format($order['price'], 2, '.', ''),
'total' => number_format($order['quantity'] * $order['price'], 2, '.', '')
];
}, $orders);
$subtotal = array_sum(array_map(fn($o) => $o['quantity'] * $o['price'], $orders));
$invoiceData = [
'company_name' => 'Minha Empresa LTDA',
'company_cnpj' => '12.345.678/0001-99',
'invoice_number' => '2024-' . str_pad($customerId, 5, '0', STR_PAD_LEFT),
'invoice_date' => date('d/m/Y'),
'customer_name' => $customer['name'],
'customer_email' => $customer['email'],
'customer_address' => "{$customer['address']}, {$customer['city']} - {$customer['state']}",
'items' => $items,
'subtotal' => number_format($subtotal, 2, '.', ''),
'tax' => number_format($subtotal * 0.15, 2, '.', ''),
'total' => number_format($subtotal * 1.15, 2, '.', '')
];
// Renderizar PDF
$result = $client->render([
'mode' => 'RENDER',
'template_id' => $templateId,
'data' => $invoiceData
]);
// Salvar PDF
$filename = "invoice-{$invoiceData['invoice_number']}.pdf";
$client->savePdf($result['pdf_base64'], $filename);
echo "✅ Fatura {$invoiceData['invoice_number']} gerada!\n";
return $filename;
}
// Executar
$templateId = 'tpl_abc123'; // Ou criar com createInvoiceTemplate()
generateInvoice(1001, $templateId);
Exemplo 3: Integração com Laravel
<?php
// app/Services/RenderHubService.php
namespace App\Services;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
class RenderHubService
{
private $client;
private $apiKey;
public function __construct()
{
$this->apiKey = config('services.renderhub.api_key');
$this->client = new Client([
'base_uri' => 'https://renderhub.com/api/v1',
'headers' => [
'Authorization' => 'Bearer ' . $this->apiKey,
'Content-Type' => 'application/json'
],
'timeout' => 30
]);
}
public function render($options)
{
try {
$response = $this->client->post('/render', [
'json' => $options
]);
return json_decode($response->getBody(), true);
} catch (RequestException $e) {
throw new \Exception('Erro ao gerar PDF: ' . $e->getMessage());
}
}
public function savePdf($pdfBase64, $path)
{
$pdfBytes = base64_decode($pdfBase64);
\Storage::put($path, $pdfBytes);
return \Storage::url($path);
}
}
<?php
// app/Http/Controllers/PdfController.php
namespace App\Http\Controllers;
use App\Services\RenderHubService;
use Illuminate\Http\Request;
class PdfController extends Controller
{
protected $renderHub;
public function __construct(RenderHubService $renderHub)
{
$this->renderHub = $renderHub;
}
public function generatePdf(Request $request)
{
$validated = $request->validate([
'template_id' => 'required|string',
'data' => 'required|array'
]);
try {
$result = $this->renderHub->render([
'mode' => 'RENDER',
'template_id' => $validated['template_id'],
'data' => $validated['data']
]);
return response()->json([
'success' => true,
'pdf_base64' => $result['pdf_base64'],
'pages' => $result['pages'],
'file_size_kb' => $result['file_size_kb']
]);
} catch (\Exception $e) {
return response()->json([
'error' => 'Erro ao gerar PDF',
'message' => $e->getMessage()
], 500);
}
}
public function downloadPdf(Request $request)
{
$validated = $request->validate([
'template_id' => 'required|string',
'data' => 'required|array'
]);
try {
$result = $this->renderHub->render([
'mode' => 'RENDER',
'template_id' => $validated['template_id'],
'data' => $validated['data']
]);
$pdfBytes = base64_decode($result['pdf_base64']);
return response($pdfBytes, 200)
->header('Content-Type', 'application/pdf')
->header('Content-Disposition', 'attachment; filename="document.pdf"');
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 500);
}
}
}
<?php
// routes/api.php
use App\Http\Controllers\PdfController;
Route::post('/generate-pdf', [PdfController::class, 'generatePdf']);
Route::post('/download-pdf', [PdfController::class, 'downloadPdf']);
<?php
// config/services.php
return [
// ...
'renderhub' => [
'api_key' => env('RENDERHUB_API_KEY'),
],
];
Exemplo 4: Webhooks
<?php
// webhook.php
require_once __DIR__ . '/vendor/autoload.php';
use GuzzleHttp\Client;
$WEBHOOK_SECRET = getenv('WEBHOOK_SECRET');
// Receber POST do webhook
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
// Validar assinatura HMAC
$signature = $_SERVER['HTTP_X_RENDERHUB_SIGNATURE'] ?? '';
$expectedSignature = hash_hmac('sha256', $payload, $WEBHOOK_SECRET);
if ($signature !== $expectedSignature) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
exit;
}
// Processar webhook
$jobId = $data['job_id'];
$status = $data['status'];
if ($status === 'DONE') {
error_log("✅ PDF {$data['id']} pronto!");
// Baixar PDF da URL temporária
$client = new Client();
$response = $client->get($data['pdf_url']);
$pdfContent = $response->getBody();
// Salvar em storage
file_put_contents("pdfs/{$data['id']}.pdf", $pdfContent);
// Atualizar banco de dados
// $db->query("UPDATE jobs SET status='COMPLETED', pdf_path=? WHERE job_id=?",
// ["pdfs/{$data['id']}.pdf", $jobId]);
// Notificar usuário
// notifyUser($jobId);
} elseif ($status === 'FAILED') {
error_log("❌ Erro ao gerar PDF: {$data['error']}");
// Atualizar banco de dados
// $db->query("UPDATE jobs SET status='FAILED', error=? WHERE job_id=?",
// [$data['error'], $jobId]);
}
// IMPORTANTE: Retornar 200 OK rapidamente
http_response_code(200);
echo json_encode(['received' => true]);
Exemplo 5: Processamento em Lote
<?php
// examples/batch_processing.php
require_once __DIR__ . '/../lib/RenderHubClient.php';
function generateInvoicesForAllCustomers($customerIds, $templateId)
{
$client = new RenderHubClient();
foreach ($customerIds as $customerId) {
try {
echo "Processando fatura para cliente {$customerId}...\n";
// Buscar dados do cliente
$customerData = fetchCustomerData($customerId);
// Gerar PDF
$result = $client->render([
'mode' => 'RENDER',
'template_id' => $templateId,
'data' => $customerData
]);
// Salvar
$filename = "invoices/invoice-{$customerId}.pdf";
$client->savePdf($result['pdf_base64'], $filename);
echo "✅ Fatura gerada: {$filename}\n";
} catch (Exception $e) {
echo "❌ Erro para cliente {$customerId}: {$e->getMessage()}\n";
}
// Aguardar para não exceder rate limit
usleep(200000); // 200ms = 5 req/s (bem abaixo do limite)
}
echo "\nProcessamento concluído!\n";
}
function fetchCustomerData($customerId)
{
// Simular busca no banco
return [
'customer_name' => "Cliente {$customerId}",
'invoice_number' => "2024-{$customerId}",
'total' => '1500.00'
];
}
// Executar
$customerIds = [1001, 1002, 1003, 1004, 1005];
generateInvoicesForAllCustomers($customerIds, 'tpl_invoice_v1');
Exemplo 6: Retry com Backoff Exponencial
<?php
// lib/retry.php
function generatePdfWithRetry($renderFn, $maxRetries = 3)
{
for ($attempt = 0; $attempt < $maxRetries; $attempt++) {
try {
return $renderFn();
} catch (Exception $e) {
$isLastAttempt = $attempt === $maxRetries - 1;
// Se rate limited, aguardar
if (strpos($e->getMessage(), 'Rate limit') !== false) {
if ($isLastAttempt) {
throw $e;
}
$delay = min(pow(2, $attempt), 30); // Max 30s
echo "Rate limited. Aguardando {$delay}s...\n";
sleep($delay);
continue;
}
// Outros erros, não fazer retry
throw $e;
}
}
}
// Uso
require_once __DIR__ . '/RenderHubClient.php';
$client = new RenderHubClient();
$result = generatePdfWithRetry(function() use ($client) {
return $client->render([
'mode' => 'CONVERT',
'input_type' => 'html',
'data' => '<h1>Test</h1>'
]);
});
Exemplo 7: Job Queue com Laravel
<?php
// app/Jobs/GenerateInvoiceJob.php
namespace App\Jobs;
use App\Services\RenderHubService;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class GenerateInvoiceJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 3;
public $backoff = [2, 10, 30];
protected $customerId;
protected $templateId;
public function __construct($customerId, $templateId)
{
$this->customerId = $customerId;
$this->templateId = $templateId;
}
public function handle(RenderHubService $renderHub)
{
\Log::info("Processando fatura para cliente {$this->customerId}");
// Buscar dados do cliente
$customerData = $this->fetchCustomerData($this->customerId);
// Gerar PDF
$result = $renderHub->render([
'mode' => 'RENDER',
'template_id' => $this->templateId,
'data' => $customerData
]);
// Salvar em storage
$filename = "invoices/invoice-{$this->customerId}.pdf";
$renderHub->savePdf($result['pdf_base64'], $filename);
\Log::info("Fatura gerada: {$filename}");
}
private function fetchCustomerData($customerId)
{
// Buscar do banco de dados
return [
'customer_name' => "Cliente {$customerId}",
'invoice_number' => "2024-{$customerId}",
'total' => '1500.00'
];
}
}
<?php
// Disparar jobs
use App\Jobs\GenerateInvoiceJob;
$customerIds = [1001, 1002, 1003, 1004, 1005];
$templateId = 'tpl_invoice_v1';
foreach ($customerIds as $customerId) {
GenerateInvoiceJob::dispatch($customerId, $templateId);
}
\Log::info(count($customerIds) . ' jobs adicionados à fila');
Exemplo 8: Wrapper PDO para Múltiplos Clientes
<?php
// examples/multi_customer_invoices.php
require_once __DIR__ . '/../lib/RenderHubClient.php';
// Conexão com banco de dados
$db = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'password');
// Buscar clientes ativos
$stmt = $db->query("SELECT id, name, email FROM customers WHERE active = 1");
$customers = $stmt->fetchAll(PDO::FETCH_ASSOC);
$client = new RenderHubClient();
$templateId = 'tpl_invoice_v1';
foreach ($customers as $customer) {
// Buscar pedidos do cliente
$stmt = $db->prepare("
SELECT p.name, oi.quantity, oi.price
FROM order_items oi
JOIN products p ON oi.product_id = p.id
WHERE oi.customer_id = ?
");
$stmt->execute([$customer['id']]);
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($orders)) {
continue;
}
// Mapear dados
$invoiceData = [
'customer_name' => $customer['name'],
'customer_email' => $customer['email'],
'invoice_number' => date('Y') . '-' . $customer['id'],
'items' => array_map(function($order) {
return [
'description' => $order['name'],
'quantity' => $order['quantity'],
'unit_price' => number_format($order['price'], 2),
'total' => number_format($order['quantity'] * $order['price'], 2)
];
}, $orders),
'total' => number_format(
array_sum(array_map(fn($o) => $o['quantity'] * $o['price'], $orders)),
2
)
];
// Gerar PDF
try {
$result = $client->render([
'mode' => 'RENDER',
'template_id' => $templateId,
'data' => $invoiceData
]);
$filename = "invoices/{$customer['id']}-{$invoiceData['invoice_number']}.pdf";
$client->savePdf($result['pdf_base64'], $filename);
echo "✅ Fatura gerada para {$customer['name']}: {$filename}\n";
} catch (Exception $e) {
echo "❌ Erro para {$customer['name']}: {$e->getMessage()}\n";
}
}
Próximos Passos
- Exemplos Node.js - Integração com Node.js/Express
- Exemplos Python - Integração com Python/Flask/Django
- API Reference - Documentação completa da API
- Guia de Templates - Templates e variáveis