Aller au contenu

Dépannage du package Laravel NextPDF

Cette page associe chaque mode de défaillance observable du package à sa cause racine vérifiée dans le code source. Chaque entrée précise le symptôme, la cause et le correctif.

Fenêtre de terminal
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

La plupart des problèmes signalés relèvent de cinq catégories : découverte, résolution du conteneur, signature, jobs de file d’attente et noms de fichiers HTTP. Par conception, le package échoue de manière explicite. Les fonctionnalités optionnelles non configurées renvoient null, et une entrée non sûre lève des exceptions typées. Le symptôme indique donc généralement la cause directement.

SymptômeCause vérifiéeCorrectif
Le provider n’est pas enregistré après l’installationL’application a désactivé la découverte via extra.laravel.dont-discoverRetire le package de dont-discover ou enregistre NextPdfServiceProvider manuellement dans bootstrap/providers.php
config('nextpdf') est videLa configuration n’a pas été fusionnée, car aucune liaison annoncée n’a été résolue (provider différé)Résous n’importe quelle entrée provides() ou confirme la découverte avec php artisan package:discover --ansi
config/nextpdf.php n’a pas été créé par la publicationLe tag de publication ne correspond pasUtilise le tag exact : php artisan vendor:publish --tag=nextpdf-config
RuntimeException : « NextPDF requires the ext-mbstring/ext-zlib PHP extension »Une extension PHP requise manque à l’exécutionInstalle ou active mbstring et zlib dans php.ini
SymptômeCause vérifiéeCorrectif
app(SignerInterface::class) renvoie nullLa signature est désactivée, ou le certificat est vide dans nextpdf.signatureDéfinis signature.enabled = true et un signature.certificate valide ; installe nextpdf/premium pour le signataire concret
app(TsaClient::class) renvoie nullnextpdf.tsa.url est videConfigure tsa.url (et les credentials/pins si nécessaire)
Classe introuvable pour un type de version PDF/Anextpdf.pdfa est non-null mais nextpdf/premium n’est pas installéInstalle nextpdf/premium, ou redéfinis pdfa à null
Classe introuvable lors de la résolution d’un contrat de facture électroniqueLes liaisons sont enregistrées, mais les classes concrètes Premium sont absentesInstalle nextpdf/premium ; les contrats de facture électronique se résolvent paresseusement et n’échouent qu’à la première résolution sans Premium
Le même document est muté entre deux opérations logiquesLa liaison du document est une factory ; tu as réutilisé une seule instance résolueRésous une nouvelle instance de PdfDocumentInterface par document

Quand une entrée est absente, le conteneur lève une exception « not-found » sur get() (PSR-11 §1.1.2). Les contrats de facture électronique sont liés ; le has() du conteneur renvoie donc vrai. L’erreur vient de la classe concrète Premium manquante au moment de la construction, et non du conteneur lui-même.

SymptômeCause vérifiéeCorrectif
InvalidArgumentException: Path traversal sequences are not allowedLe chemin de sortie contient un segment de remontée ..Utilise un chemin absolu, sans traversée, sous ton répertoire de stockage
InvalidArgumentException: Stream wrappers are not allowedLe chemin correspond à un schéma comme php://Utilise un simple chemin du système de fichiers
InvalidArgumentException: Output path contains null bytesLe chemin contient un octet nul \0Nettoie le chemin avant la mise en file d’attente
InvalidArgumentException: Output path must end with .pdf extensionLe chemin ne se termine pas par .pdf (insensible à la casse)Utilise un suffixe .pdf (ou .PDF)
Le job s’exécute, mais le fichier est vide ou incorrectLa closure du builder n’a pas renvoyé le document configuréRenvoie le document depuis le builder ; la valeur renvoyée est celle qui est enregistrée
Le job utilise la mauvaise file d’attente ou le mauvais délai d’expirationnextpdf.queue.* n’est pas défini comme attenduDéfinis queue.queue, queue.connection, queue.timeout ; tries et backoff nécessitent de créer une sous-classe

Les vérifications de chemin s’exécutent dans handle() sur le worker : un chemin incorrect échoue donc à l’exécution, et non à la mise en file d’attente. C’est intentionnel : la charge utile sérialisée dans le transport de file d’attente est validée là où elle est consommée.

SymptômeCause vérifiéeCorrectif
Le nom de fichier de téléchargement est document.pdf de façon inattendueUn nom de fichier vide a été passé ; la factory lui applique sa valeur par défautPasse un nom de fichier non vide
Le nom de fichier a perdu son chemin ou ses caractères spéciauxL’assainisseur de nom de fichier supprime les séparateurs de chemin, les caractères de contrôle et les octets nulsPasse uniquement le nom de fichier de base ; c’est un durcissement attendu
Un nom de fichier non-ASCII affiche du mojibake sur certains clientsLe paramètre RFC 5987 filename*= est émis pour les noms non-ASCII ; les anciens clients lisent le repli ASCIIAttendu ; fournis un nom compatible ASCII si un client hérité doit afficher exactement le même nom
La réponse en flux n’a pas de Content-LengthLes réponses en flux omettent Content-Length par conception (sortie en chunks)Attendu ; utilise les méthodes non diffusées inline()/download() si un en-tête de longueur est requis
Fenêtre de terminal
# Confirm the provider is discovered
php artisan package:discover --ansi
# Inspect merged configuration
php artisan tinker --execute="dump(config('nextpdf.queue'));"
resource: src/Laravel/NextPdfServiceProvider.php (null-check pattern)
<?php
declare(strict_types=1);
use NextPDF\Contracts\SignerInterface;
$signer = app(SignerInterface::class);
if ($signer === null) {
// Signing not configured, or nextpdf/premium not installed.
// Continue without a signature, or fail with a clear message.
}
  • Le provider différé signifie qu’une nouvelle installation peut sembler « cassée » jusqu’à la première résolution pertinente. Le bon signal de réussite est que package:discover liste le package.
  • image_cache_mb = null revient à 50 Mo ; seul 0 désactive le cache. Un signalement « le cache ne se désactive pas » utilisait généralement null.
  • signature.level = null revient silencieusement à PAdES B-B. Un signalement « B-B inattendu » a généralement laissé le niveau non défini.

Si les premières requêtes sur un worker à longue durée de vie sont lentes, le registre de polices analyse les polices à la demande. Renseigne nextpdf.preload_fonts pour que le préchauffage s’exécute une seule fois au démarrage du worker. Voir /integrations/laravel/configuration/ et /integrations/laravel/boot-and-discovery/ pour les détails.

Les rejets liés aux chemins et aux noms de fichiers sont des contrôles de sécurité, pas des bugs. Ne les contourne pas en pré-décodant ni en assouplissant les vérifications. Achemine plutôt la sortie de fichier via un chemin de stockage contrôlé. Voir /integrations/laravel/security-and-operations/.

AffirmationSourceArticlereference_id
Une entrée de conteneur manquante lève une erreur « not-found » sur get()Conteneur PSR-11§1.1.2
  • /integrations/laravel/install/ — étapes de découverte et de publication
  • /integrations/laravel/configuration/ — chaque clé et sa valeur par défaut
  • /integrations/laravel/production-usage/ — modèles d’injection de dépendances et de file d’attente
  • /integrations/laravel/security-and-operations/ — pourquoi les vérifications de chemin existent