İçeriğe geç

NextPDF istisna hiyerarşisiyle hataları ele alın

NextPDF, istisnai durumlar için türlendirilmiş istisnalar fırlatır. Bir hatayı asla false veya null dönüş değerlerinin arkasına gizlemez. Her etki alanı istisnası, aynı soyut temel sınıf olan NextPdfException sınıfından türemiştir ve yapılandırılmış tanılama bağlamını ContextAwareExceptionInterface aracılığıyla sunar. Bu tarif, yakalamayı nerede yapacağınızı ve yapılandırılmış bağlamı bir uygulama performansı izleme (APM) işlem hattı için nasıl günlüğe kaydedeceğinizi gösterir. Ayrıca tek bir catch-all bloğunun hangi başarısızlıkları kapsamadığını da gösterir.

Terminal window
composer require nextpdf/core:^3

Başka bir uzantıya ihtiyacınız yoktur.

Hiyerarşi şöyledir:

RuntimeException
└── NextPdfException (abstract, implements ContextAwareExceptionInterface)
├── InvalidConfigException
├── FontNotFoundException
├── FontParsingException
├── ImageProcessingException
├── WriterException
├── SignatureException
├── EncryptionException
├── HtmlParsingException
├── … (every domain exception under NextPDF\Exception)
└── Strict\StrictModeViolation (abstract)
├── Strict\IncompatibleRenderingModeException
└── Strict\OracleConformanceFailure

Kaynak koduna karşı doğrulanmış bu hiyerarşinin iki pratik sonucu vardır:

  1. catch (NextPdfException $e) bloğu, katı mod ihlalleri dahil olmak üzere NextPDF\Exception altındaki her istisnayı yakalar. Hepsi soyut tabandan türemiştir.
  2. Kütüphanenin fırlatabileceği her şeyi yakalamaz. NextPDF\Support\DegradedException, RuntimeException sınıfından doğrudan türemiştir; NextPdfException sınıfından değil. Dolayısıyla bir catch (NextPdfException $e) bloğu, bir düşürme ilkesi reddini yakalamaz. Bunu ele almak için DegradedException (veya daha geniş kapsamlı RuntimeException) istisnasını açıkça yakalayın. Bu tarif, tek bir catch-all bloğunu eksiksiz kapsama olarak görmek yerine bu sınırı açık hale getirir.

NextPdfException::getContext(), snake_case anahtarlar ve yalnızca ilkel değerler ya da ilkel değer listeleri içeren bir array<string, mixed> döndürür. Bunu doğrudan bir PSR-3 günlükleyicisinin bağlam dizisine aktarabilirsiniz. PSR-3 §1.3, bir istisnanın 'exception' bağlam anahtarının altında yer almasını belirtir. NextPDF’in getContext() yöntemi, istisna nesnesinin kendisini değil, bu anahtarın yanına etki alanına özgü ayrıntılar ekler.

Bu API yüzeyi şu kaynaklardaki PHPDoc’tan alınır: NextPDF\Exception\NextPdfException, NextPDF\Contracts\ContextAwareExceptionInterface, somut etki alanı istisnaları (örneğin NextPDF\Exception\FontNotFoundException, getFontName() / getSearchPaths() / wasFallbackAttempted() ile) ve NextPDF\Support\DegradedException (Capability ve DegradationPolicy öğelerini taşır). Aşağıdaki örnekler NextPdfException::getContext() yöntemini ve istisnaya özel erişimcileri kullanır.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Exception\NextPdfException;
try {
$doc = Document::createStandalone();
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Hello');
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/out.pdf');
} catch (NextPdfException $e) {
// Every NextPDF\Exception\* (and strict-mode violation) lands here.
// $e->getContext() is APM-safe structured detail.
error_log($e->getMessage());
}

Tam örnek; ayrıntılı yakalamaları, yapılandırılmış bağlamı günlüğe kaydetmeyi ve DegradedException sınırını gösterir. Ayrıca test koşumunun çıktı kanalını da korur.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Contracts\ContextAwareExceptionInterface;
use NextPDF\Exception\FontNotFoundException;
use NextPDF\Exception\NextPdfException;
use NextPDF\Support\DegradedException;
/**
* A minimal PSR-3-shaped sink. In production this is your real logger;
* the exception goes under the 'exception' key (PSR-3 §1.3) and the
* NextPDF structured context is merged in as domain detail.
*
* @param array<string, mixed> $context
*/
function logError(string $message, array $context): void
{
fwrite(STDERR, $message . ' ' . json_encode($context, JSON_THROW_ON_ERROR) . "\n");
}
$doc = Document::createStandalone();
$doc->setTitle('Exception handling patterns');
try {
$doc->addPage();
$doc->setFont('helvetica', 'B', 16);
$doc->cell(0, 12, 'Exception-aware error handling', newLine: true);
// This call succeeds; the catch blocks below show the SHAPE of handling.
$doc->setFont('helvetica', '', 11);
$doc->cell(0, 8, 'Catch specifically, then fall back to the base.', newLine: true);
} catch (FontNotFoundException $e) {
// Most specific first: actionable, typed accessors.
logError('Font missing — using a fallback face', [
'exception' => $e::class,
'font_name' => $e->getFontName(),
'searched' => $e->getSearchPaths(),
'fallback' => $e->wasFallbackAttempted(),
]);
} catch (NextPdfException $e) {
// Catch-all for every NextPDF\Exception\* including strict violations.
$context = ['exception' => $e::class];
if ($e instanceof ContextAwareExceptionInterface) {
$context += $e->getContext();
}
logError($e->getMessage(), $context);
} catch (DegradedException $e) {
// BOUNDARY: DegradedException extends RuntimeException directly, NOT
// NextPdfException. The catch above would NOT have caught it. This
// explicit block (or a broader RuntimeException) is required.
logError('Capability degraded under the active policy', [
'exception' => $e::class,
'capability' => $e->capability->id,
'policy' => $e->policy->value,
]);
}
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/out.pdf');
fwrite(STDERR, "Document built; handlers wired.\n");

STDOUT, koşum donanımı için boş kalır; PDF yalnızca NEXTPDF_COOKBOOK_OUTPUT hedefine yazılır.

  • Yakalama bloklarını özelden → genele doğru sıralayın. PHP, uyumlu olan ilk catch bloğuyla eşleşir. Bir catch (NextPdfException $e) bloğunun catch (FontNotFoundException $e) bloğundan önce yerleştirilmesi, özel bloğu erişilemez kod haline getirir.
  • DegradedException bir NextPdfException değildir. Kaynak koduna karşı doğrulandığı üzere, RuntimeException sınıfından türemiştir. Tek bir catch (NextPdfException $e), katı düşürme reddinin yayılmasına izin verir. Düşürme ilkesi devredeyken bunu (veya RuntimeException sınıfını) açıkça yakalayın.
  • getContext() sözleşme gereği APM açısından güvenlidir. Anahtarlar snake_case biçimindedir. Değerler ilkel türler veya ilkel tür listeleridir; iç içe nesneler ya da kaynaklar içermez. Bunu doğrudan seri hale getirebilirsiniz. Asla belge baytları içermez.
  • İstisna iletilerini ayrıştırmayın. İletiler insanlar için okunabilirdir ve değişebilir. Kararlı makine yüzeyi olarak türlendirilmiş erişimcileri (getFontName(), capability->id vb.) ve getContext() yöntemini kullanın.
  • Güncel olmayan sayı notu. Daha eski materyaller sabit bir “N etki alanı istisnası” değerinden söz edebilir. Hiyerarşi sürümler boyunca büyür. Sabit kodlanmış bir sayıya değil, her zaman NextPdfException taban türüne ve instanceof kullanımına güvenin.
  • PSR-3 yer tutucuları dize olarak kalır. Günlüğe kaydederken iletiyi {placeholder} belirteçleri içeren bir dize olarak tutun ve değerleri bağlam dizisine yerleştirin (PSR-3 §1.2). İstisna nesnesini iletinin içine koymayın.

İstisna işleme, normal akışta ek maliyet getirmez. NextPDF yalnızca istisnai durumlarda istisna fırlatır ve getContext() çağrıldığında küçük bir dizi oluşturur. performance_budget (wall_ms: 2000, peak_mb: 96), rastgele belgeleri değil, bu tarife yönelik test koşumunu sınırlandırır.

  • getContext() günlük açısından güvenli olacak şekilde tasarlanmıştır: yalnızca ilkel türler içerir; belge yükü veya dosya baytı içermez. Bir günlük bağlamına eklediğiniz değerlerden yine de siz sorumlusunuz. Kullanıcı tarafından sağlanan her şeyi (örneğin bir dosya yolu) bir hedefe ulaşmadan önce günlük kaydı ilkenize göre temizleyin.
  • Ham istisna iletilerini, dosya sistemi düzenini sızdıracak biçimde son kullanıcılara göstermeyin. Genel bir ileti gösterin ve yapılandırılmış bağlamı sunucu tarafında günlüğe kaydedin.
İfadeBelirtimMaddereference_id
Bir istisna, PSR-3 günlük bağlamında exception anahtarının altında yer alır.PSR-3§1.3
Günlük iletileri dize olarak kalır; yer tutucu adları bağlam anahtarlarıyla eşlenir.PSR-3§1.2
Değişiklik tarihi her kaydetme işleminde yeniden oluşturulur, dolayısıyla çıktı bayt düzeyinde değil yapısal olarak kararlıdır.ISO 32000-2§14.3

Bu tarif yapısal yeniden üretilebilirlik profiliyle doğrulanır. Çıktı, her kaydetme işleminde yeniden oluşturulan bir fragman (trailer) /ID değeri ve bir değişiklik tarihi taşır, dolayısıyla bayt düzeyinde özdeşlik elde edilemez. qpdf ile normalleştirilmiş yapı kararlı kalır.