Skip to main content
PHP FacturaE allows you to attach files directly to your invoices, embedding them in Base64 format within the XML. This is useful for including supporting documents like contracts, delivery notes, or technical specifications.

Quick Start

The simplest way to attach a file is using the attachFile() convenience method:
use PhpFacturae\Invoice;

$invoice = Invoice::create('FAC-001')
    ->seller($seller)
    ->buyer($buyer)
    ->line('Consulting services', price: 2000.00, vat: 21)
    ->attachFile('/path/to/contract.pdf', 'Signed service contract')
    ->toXml();
Attached files are encoded in Base64 and embedded directly in the FacturaE XML, making the invoice self-contained.

Using the Attachment Entity

For more control, use the Attachment entity with the attach() method:
use PhpFacturae\Entities\Attachment;

$attachment = Attachment::fromFile(
    '/path/to/document.pdf',
    'Contract signed on 2024-01-15'
);

$invoice = Invoice::create('FAC-002')
    ->seller($seller)
    ->buyer($buyer)
    ->line('Development services', price: 5000.00, vat: 21)
    ->attach($attachment)
    ->toXml();

Creating Attachments

The Attachment class provides two static factory methods:

From File Path

use PhpFacturae\Entities\Attachment;

// Auto-detect MIME type
$attachment = Attachment::fromFile(
    '/path/to/contract.pdf',
    'Service agreement'
);

// Specify MIME type explicitly
$attachment = Attachment::fromFile(
    '/path/to/document.pdf',
    'Technical specifications',
    'application/pdf'
);

From Raw Data

// Attach data from memory or API
$pdfData = file_get_contents('https://api.example.com/contract.pdf');

$attachment = Attachment::fromData(
    $pdfData,
    'application/pdf',
    'Contract retrieved from API'
);

$invoice->attach($attachment);
Both methods automatically encode the data to Base64. You should provide the raw binary data, not pre-encoded data.

MIME Type Detection

When using fromFile() without specifying a MIME type, PHP FacturaE automatically detects it:
// MIME type auto-detected as 'application/pdf'
Attachment::fromFile('/path/to/contract.pdf', 'Contract');

// MIME type auto-detected as 'image/png'
Attachment::fromFile('/path/to/logo.png', 'Company logo');

// Fallback to 'application/octet-stream' if detection fails
Attachment::fromFile('/path/to/unknown.dat', 'Data file');

Supported File Types

While FacturaE supports any file type, these are commonly used:
1
Documents
2
  • PDF: application/pdf - Contracts, reports, specifications
  • Word: application/vnd.openxmlformats-officedocument.wordprocessingml.document
  • Excel: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • 3
    Images
    4
  • PNG: image/png
  • JPEG: image/jpeg
  • GIF: image/gif
  • 5
    Archives
    6
  • ZIP: application/zip
  • TAR: application/x-tar
  • Large attachments significantly increase XML file size. Keep attachments under 5MB when possible. For larger files, consider using external references or document management systems.

    Multiple Attachments

    You can attach multiple files to a single invoice:
    $invoice = Invoice::create('FAC-003')
        ->seller($seller)
        ->buyer($buyer)
        ->line('Project delivery', price: 10000.00, vat: 21)
        // Attach contract
        ->attachFile(
            '/path/to/contract.pdf',
            'Master service agreement'
        )
        // Attach delivery note
        ->attachFile(
            '/path/to/delivery-note.pdf',
            'Delivery note DN-2024-001'
        )
        // Attach technical documentation
        ->attach(
            Attachment::fromFile(
                '/path/to/technical-specs.pdf',
                'Technical implementation guide'
            )
        )
        ->toXml();
    

    Complete Example

    use PhpFacturae\Invoice;
    use PhpFacturae\Party;
    use PhpFacturae\Entities\Attachment;
    
    $seller = Party::company('B12345678', 'Consulting SL')
        ->address('Calle Mayor 1', '28001', 'Madrid', 'Madrid');
    
    $buyer = Party::company('A87654321', 'Tech Corp SA')
        ->address('Gran Via 50', '28013', 'Madrid', 'Madrid');
    
    $invoice = Invoice::create('FAC-2024-042')
        ->series('A')
        ->date('2024-03-15')
        ->seller($seller)
        ->buyer($buyer)
        // Invoice lines
        ->line('Software development', price: 8000.00, vat: 21)
        ->line('Project management', price: 2000.00, vat: 21)
        // Attach supporting documents
        ->attachFile(
            '/var/invoices/contracts/contract-2024-042.pdf',
            'Project contract signed 2024-01-10',
            'application/pdf'
        )
        ->attachFile(
            '/var/invoices/delivery/delivery-note-042.pdf',
            'Delivery note with client acceptance'
        )
        // Payment terms
        ->transferPayment(
            iban: 'ES91 2100 0418 4502 0005 1332',
            dueDate: '2024-04-15'
        )
        ->export('/var/facturae/FAC-2024-042.xsig');
    

    Attachment Class Reference

    The Attachment entity is defined in Entities/Attachment.php:9:
    final class Attachment
    {
        public readonly string $data;        // Base64-encoded data
        public readonly string $mimeType;    // MIME type
        public readonly string $description; // Description
    }
    

    Methods

    fromFile()

    public static function fromFile(
        string $path,
        string $description,
        ?string $mimeType = null
    ): self
    
    Creates an attachment from a file path. Throws RuntimeException if the file doesn’t exist. Defined at Entities/Attachment.php:25

    fromData()

    public static function fromData(
        string $data,
        string $mimeType,
        string $description
    ): self
    
    Creates an attachment from raw binary data. Defined at Entities/Attachment.php:41

    Invoice Methods

    attach()

    public function attach(Attachment $attachment): self
    
    Attaches an Attachment entity to the invoice. Defined at Invoice.php:392

    attachFile()

    public function attachFile(
        string $path,
        string $description,
        ?string $mimeType = null
    ): self
    
    Convenience method that creates and attaches a file in one step. Defined at Invoice.php:403
    Use attachFile() for simple cases where you just need to attach a file. Use attach() with Attachment::fromData() when you need to attach dynamically generated content or data from external sources.

    Common Use Cases

    Attach Signed Contract

    ->attachFile(
        '/contracts/signed/contract-2024-042.pdf',
        'Signed master service agreement dated 2024-01-15'
    )
    

    Attach Delivery Proof

    ->attachFile(
        '/delivery-notes/DN-2024-042.pdf',
        'Delivery note with client signature'
    )
    

    Attach Technical Documentation

    ->attachFile(
        '/docs/technical-spec-v2.pdf',
        'Technical implementation specifications v2.0'
    )
    

    Attach Generated Report

    $reportPdf = generateMonthlyReport();
    
    ->attach(
        Attachment::fromData(
            $reportPdf,
            'application/pdf',
            'Monthly activity report for January 2024'
        )
    )
    

    Attach Image Evidence

    ->attachFile(
        '/photos/installation-complete.jpg',
        'Photo evidence of completed installation',
        'image/jpeg'
    )
    

    Best Practices

    1
    Use Descriptive Names
    2
    Provide clear descriptions that explain what the document is and why it’s attached.
    3
    Keep Files Small
    4
    Compress PDFs and optimize images before attaching to keep XML file sizes manageable.
    5
    Specify MIME Types
    6
    For non-standard file types, always explicitly specify the MIME type.
    7
    Validate Files Exist
    8
    Check that files exist before attempting to attach them to avoid runtime errors.
    9
    Consider Alternatives for Large Files
    10
    For files over 5-10MB, consider hosting them externally and including a reference link instead.

    Error Handling

    use PhpFacturae\Entities\Attachment;
    use RuntimeException;
    
    try {
        $attachment = Attachment::fromFile(
            '/path/to/contract.pdf',
            'Service contract'
        );
    } catch (RuntimeException $e) {
        // Handle missing file
        echo "Attachment file not found: " . $e->getMessage();
    }
    
    The fromFile() method throws a RuntimeException with message “Attachment file not found: ” if the file doesn’t exist.

    Build docs developers (and LLMs) love