Installation
Add the bundle and its dependency to composer.json:
composer require bytes/docraptor-bundle bytes/docraptor "@dev"
Run composer update.
Register the Bundle
Add the bundle to config/bundles.php (Symfony 4+) or app/AppKernel.php (Symfony 2/3):
Bytes\Bundle\DocraptorBundle\BytesDocraptorBundle::class => ['all' => true],
Configuration Publish the default config:
php bin/console config:dump-reference BytesDocraptorBundle
Override in config/packages/bytes_docraptor.yaml:
bytes_docraptor:
api_key: '%env(DOCRAPTOR_API_KEY)%'
timeout: 30
First Use Case: PDF Generation Inject the client into a controller/service:
use Bytes\DocraptorBundle\Client\DocraptorClientInterface;
public function __construct(DocraptorClientInterface $docraptor) {
$this->docraptor = $docraptor;
}
public function generatePdf() {
$job = $this->docraptor->createJob(
'https://example.com/invoice.pdf',
'https://example.com/html-content'
);
return $job->getUrl();
}
Job Creation & Management
createJob() with HTML URL and target PDF URL.getJob() with getStatus() in a loop:
$job = $this->docraptor->getJob($jobId);
while ($job->getStatus() !== 'finished') {
sleep(2);
$job = $this->docraptor->getJob($jobId);
}
Dynamic Content
$htmlUrl = $this->generateTwigHtml($data);
$job = $this->docraptor->createJob($pdfUrl, $htmlUrl);
Error Handling
try {
$job = $this->docraptor->createJob($pdfUrl, $htmlUrl);
} catch (\Bytes\DocraptorBundle\Exception\DocraptorException $e) {
$this->handleDocraptorError($e);
}
Configuration Overrides
# config/packages/bytes_docraptor.yaml
bytes_docraptor:
api_key: '%env(resolve:DOCRAPTOR_API_KEY)%'
endpoint: 'https://api.docraptor.eu/v1'
Event-Driven Workflows
// In a service
event(new JobCompleted($job));
API Key Exposure
.env or parameter bags.DOCRAPTOR_API_KEY in config/packages/bytes_docraptor.yaml:
bytes_docraptor:
api_key: '%env(DOCRAPTOR_API_KEY)%'
Add to .env.example:
DOCRAPTOR_API_KEY=your_key_here
Rate Limiting
$attempts = 0;
$maxAttempts = 3;
while ($attempts < $maxAttempts) {
try {
$job = $this->docraptor->createJob($pdfUrl, $htmlUrl);
break;
} catch (\Bytes\DocraptorBundle\Exception\RateLimitException $e) {
$attempts++;
sleep(2 ** $attempts);
}
}
HTML URL Validity
http://localhost) may fail.Bundle Maturity
DocraptorClientInterface for custom needs.Debugging API Calls
bytes_docraptor.yaml:
bytes_docraptor:
debug: true
var/log/dev.log.Caching Job Results
$pdfUrl = Cache::remember("docraptor_job_{$jobId}", 3600, function () use ($jobId) {
return $this->docraptor->getJob($jobId)->getUrl();
});
Queue Delayed Jobs
Dispatch(new GeneratePdfJob($data))->delay(now()->addMinutes(5));
Custom Headers
$client = $this->docraptor->getClient();
$client->setDefaultOption('headers', [
'X-Custom-Header' => 'value',
]);
Testing
DocraptorClientInterface in PHPUnit:
$mock = $this->createMock(DocraptorClientInterface::class);
$mock->method('createJob')->willReturn(new Job(['url' => 'test.pdf']));
$this->app->instance(DocraptorClientInterface::class, $mock);
Webhook Integration
X-Signature header):
$signature = $_SERVER['HTTP_X_SIGNATURE'];
$isValid = hash_equals($signature, hash_hmac('sha256', $payload, $apiKey));
Fallback for Offline
try {
$job = $this->docraptor->createJob($pdfUrl, $htmlUrl);
} catch (\Exception $e) {
$pdf = $this->generateLocalPdf($htmlContent);
return $pdf->saveAs($pdfUrl);
}
How can I help you explore Laravel packages today?