Zum Inhalt springen

E-Rechnungen mit PHP erstellen, ganz ohne Laravel

Quittio ist als E-Rechnungs-Bibliothek für Laravel bekannt. Der Kern ist aber reines PHP und läuft in jedem Projekt mit PHP 8.3, auch ohne Framework.

Anleitung15.10.2026 · ca. 6 Minuten

Kurz gesagt

Für E-Rechnungen ohne Laravel installierst du quittio/core und das Länderpaket quittio/country-de. Statt der Facade erzeugst du einmal eine Instanz mit Quittio::create() und baust Rechnungen mit InvoiceBuilder::make(). ZUGFeRD, XRechnung, Peppol, Validierung und das Lesen von Eingangsrechnungen funktionieren genauso wie in Laravel.

Welche Pakete du brauchst

PaketOhne LaravelInhalt
quittio/corenötigDatenmodell, Berechnung, CII und UBL, ZUGFeRD/Factur-X, Validierung, Lesen
quittio/country-deempfohlenPflichtangaben nach UStG, Steuersätze, XRechnung-Regeln, DIN 5008
quittio/laravelnicht nötigFacade, Konfiguration, Blade, Artisan
quittio/quittionicht nötigKomplettpaket für Laravel-Projekte

Voraussetzung ist PHP 8.3 oder neuer mit den Erweiterungen ctype, dom, gd, libxml, mbstring, xmlwriter und zlib. Laravel oder ein anderes Framework wird nicht gebraucht.

Installation

Ein Befehl, keine Konfigurationsdatei:

composer require quittio/core quittio/country-de

Ein vollständiges Skript

Das Skript erzeugt eine ZUGFeRD-Rechnung (PDF/A-3 mit eingebettetem XML), speichert sie und liest sie zur Kontrolle wieder ein. Es läuft so mit php rechnung.php.

rechnung.php
<?php
require __DIR__.'/vendor/autoload.php';

use Quittio\Core\Builder\InvoiceBuilder;
use Quittio\Core\Builder\Party;
use Quittio\Core\Enums\PaymentMeansCode;
use Quittio\Core\Enums\UnitCode;
use Quittio\Core\Quittio;
use Quittio\Core\Tax\CountryDefaultVat;
use Quittio\Country\DE\CountryDE;

$quittio = Quittio::create([], [new CountryDE]);
InvoiceBuilder::useDefaultVat(new CountryDefaultVat($quittio->countries()));   // Positionen ohne vat(): 19 %

$invoice = InvoiceBuilder::make()
    ->number('RE-2026-0120')
    ->issueDate('2026-10-14')
    ->deliveryDate('2026-10-14')
    ->seller(Party::make('Muster GmbH')->vatId('DE123456789')->address('Hauptstraße 1', '12345', 'Musterstadt', 'DE'))
    ->buyer(Party::make('Kunde AG')->vatId('DE987654321')->address('Bahnhofstraße 5', '54321', 'Beispielstadt', 'DE'))
    ->line('Consulting', netPrice: '120.00', quantity: 4, unit: UnitCode::Hour)
    ->payment(PaymentMeansCode::SepaCreditTransfer, iban: 'DE02120300000000202051')
    ->dueInDays(14)
    ->build();

$result = $quittio->make($invoice)->render();                        // ZUGFeRD: PDF/A-3 mit XML
$path = $result->save(__DIR__.'/invoices/'.$result->filename());   // invoices/Rechnung_RE-2026-0120.pdf

// Zur Kontrolle wieder einlesen, so wie der Empfänger es tut
$read = $quittio->readFile($path);
echo $read->data->totals->amountDue;                               // EUR 571.20
  • Ohne Laravel gibt es keine Konfigurationsdatei. Verkäufer und Bankverbindung stehen deshalb im Code.
  • useDefaultVat() gibt Positionen ohne eigenen Steuersatz den Standardsatz des Länderpakets, in Deutschland 19 %. Ohne diesen Aufruf schlägt build() bei solchen Positionen fehl.
  • render() validiert die Rechnung. Ist sie ungültig, wird eine Exception mit allen Befunden geworfen, bevor eine Datei entsteht.

Was anders ist als in Laravel

ThemaLaravelReines PHP
EinstiegFacade Quittio::invoice()Instanz aus Quittio::create(), Rechnung mit InvoiceBuilder::make()
Konfigurationconfig/quittio.phpArray oder Config-Objekt an Quittio::create()
Verkäufer und Bankaus der Konfigurationim Code: ->seller(…) und ->payment(…)
Standard-Umsatzsteuerautomatischeinmal InvoiceBuilder::useDefaultVat(…) beim Start
Länderpaketwird automatisch erkanntnew CountryDE an Quittio::create() übergeben
VorlagenBladePHP-Vorlagen; Twig o. Ä. über eine eigene TemplateEngine
SpeichernStorage-Disk$result->save($pfad) oder file_put_contents()

Einstellungen übergibst du als Array, zum Beispiel für die Prüfstufen:

bootstrap.php
$quittio = Quittio::create([
    'validation' => ['mode' => 'error', 'levels' => ['L1', 'L2', 'L3', 'L4', 'L7']],
    'pdf' => ['b2c_embed_xml' => false],
], [new CountryDE]);

XRechnung und Prüfen

Der Formatwechsel ist eine Zeile. Mit check() prüfst du eine Rechnung, ohne ein PDF zu erzeugen:

rechnung.php
// XRechnung statt ZUGFeRD
$result = $quittio->make($invoice)->format('xrechnung-cii')->render();

// Nur prüfen, ohne PDF; wirft nie, sondern liefert einen Bericht
$report = $quittio->make($invoice)->format('xrechnung-cii')->check();
$report->isValid();
$report->errors();

Auch der Storno-Beleg funktioniert ohne Laravel:

rechnung.php
$cancellation = $quittio->cancellation($result->data(), 'ST-2026-0001', reason: 'Doppelt berechnet');

Eingangsrechnungen lesen

Seit 2025 muss jedes Unternehmen E-Rechnungen empfangen können. Die Instanz liest CII, UBL und ZUGFeRD und prüft sie auf Wunsch mit allen Stufen:

eingang.php
$read = $quittio->read($uploadedContent);   // Inhalt einer XML- oder PDF-Datei
$read = $quittio->readFile('/path/to/invoice.pdf');

$read->data->number;                        // "RE-2026-0101"
$read->data->seller->name;                  // der Lieferant
$read->profile;                             // z. B. "en16931" oder "xrechnung"

$report = $quittio->validateFile($uploadedContent);   // alle Prüfstufen auf eine Eingangsrechnung

In dein Projekt einbinden

Erzeuge die Instanz einmal beim Start und verwende sie überall. In Symfony, Slim oder einem anderen Framework registrierst du sie als Dienst; ohne Framework genügt eine kleine Fabrik:

InvoiceFactory.php
final class InvoiceFactory
{
    private static ?Quittio $quittio = null;

    public static function quittio(): Quittio
    {
        if (self::$quittio === null) {
            self::$quittio = Quittio::create([], [new CountryDE]);
            InvoiceBuilder::useDefaultVat(new CountryDefaultVat(self::$quittio->countries()));
        }

        return self::$quittio;
    }
}

Was nur mit Laravel geht

  • Facade, Konfigurationsdatei und Artisan-Befehle
  • Blade-Vorlagen, Queue, Events, Mail und Storage-Integration
  • Quittio::fake() und die Test-Assertions (Factories und Szenarien gibt es auch ohne Laravel)
  • Quittio Managed (quittio/managed) mit Datenbank, Nummernkreisen und Archiv braucht Laravel 13

Alles, was eine gültige E-Rechnung ausmacht, steckt im Core. Die vollständige Referenz für den Einsatz ohne Laravel steht in der Dokumentation.

Häufige Fragen

Brauche ich Laravel für Quittio?

Nein. quittio/core hat keine Abhängigkeit zu Laravel und läuft in jeder Anwendung mit PHP 8.3 oder neuer. Laravel brauchst du nur für die Integration quittio/laravel und für Quittio Managed.

Funktioniert Quittio mit Symfony, Slim, WordPress oder Shopware?

Ja, mit allem, was Composer-Pakete laden kann. Erzeuge die Quittio-Instanz einmal beim Start und registriere sie so, wie dein Framework Dienste verwaltet.

Welches Paket installiere ich?

quittio/core und für Deutschland quittio/country-de. Das Paket quittio/quittio ist für Laravel-Projekte gedacht, weil es die Laravel-Integration mitbringt.

Welche PHP-Erweiterungen brauche ich?

ctype, dom, gd, libxml, mbstring, xmlwriter und zlib; intl wird empfohlen. Für den offiziellen KoSIT-Validator (Prüfstufe L5) zusätzlich Java 17 oder Docker, für veraPDF (L6) veraPDF oder Docker.

Sind die Rechnungen ohne Laravel genauso gültig?

Ja. Datenmodell, Berechnung, Formate und Validierung stecken alle im Core. Die Laravel-Integration ist nur eine bequeme Hülle darum.

Probier es in fünf Minuten aus.

Ein Composer-Befehl, ein Skript, eine gültige E-Rechnung.