Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ezodf Ls Laravel Package

ezsystems/ezodf-ls

PHP library for creating and manipulating OpenDocument Format files, including text documents and spreadsheets. Extracted from eZ Publish, it provides classes for generating ODF content programmatically, useful for exports and reports.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a legacy eZ Systems library pulled from the eZ Components ODF component. It is not a Laravel package — no service provider, no facade, no config file. You install it and drive the classes directly, so the first job is wrapping it yourself.

composer require ezsystems/ezodf

Check composer.json and the src/ tree before anything else. The entry points are the legacy ezc-prefixed document classes (ezcDocumentOdt, ezcDocumentOds, ezcDocumentOdp), and the primary input format is DocBook XML, not HTML or a fluent builder. That single fact drives most of the design decisions you'll make with this package.

Register a binding in a service provider so you can inject a single wrapper rather than newing classes up across controllers:

// app/Providers/AppServiceProvider.php
$this->app->singleton(OdfExporter::class, fn () => new OdfExporter(
    storage_path('app/templates')
));

First use case — the one that maps cleanly onto day-to-day Laravel work — is document export: take structured data (an order, an invoice, a content record), render it to an ODT/ODS, and return it as a download or push it to storage.

Minimal flow:

$doc = new \ezcDocumentOdt();
$doc->loadString($docbookXml);
$doc->save(storage_path('app/exports/order-'.$order->id.'.odt'));

The output is a zip container (ODF is zipped XML), so ext-zip, ext-dom, and likely ext-xsl must be available in your runtime image. Verify those in Dockerfile/php.ini before you start debugging formatting — missing extensions produce confusing failures rather than clean errors.

Implementation Patterns

Wrap, never scatter. Create App\Support\Odf\OdfExporter with methods like toOdt(string $docbook): string and toOds(array $rows): string. Every call into ezc* lives behind that boundary. When the library eventually needs patching (it will), you touch one file.

DocBook as the intermediate layer. Do not try to hand-build ODF XML. Instead, render a Blade view that produces DocBook:

public function toOdt(string $docbook): string
{
    $document = new \ezcDocumentOdt();
    $document->loadString($docbook);
    return $document->saveToString(); // or write to a temp path
}

// In a controller / job:
$docbook = view('exports.invoice-docbook', ['invoice' => $invoice])->render();
$path = $this->exporter->toOdt($docbook);

This keeps your templates in resources/views/exports/ where you can iterate on them and diff them in review, exactly like an HTML mail template.

Template-driven documents. For documents that must match a corporate layout, keep .odt templates on disk, load a template, then substitute. This is the pattern eZ Publish itself used for CMS content export — treat the shipped template as the style source of truth, and only inject content.

Queue the heavy work. ODF assembly is CPU- and memory-bound on large documents and is a poor fit for the request lifecycle. Dispatch an ExportOrderDocument job, write the .odt to the local or s3 disk, and notify the user:

Storage::disk('local')->put("exports/{$order->id}.odt", $bytes);

Because ODF is just a directory tree zipped, S3 storage works fine — no partial-write weirdness as long as you put() the full string rather than streaming the save() call.

Stream downloads explicitly. Write to a temp path, then return response()->download($path, 'invoice.odt', ['Content-Type' => 'application/vnd.oasis.opendocument.text']). The library's in-memory output is a string; a StreamedResponse that calls save('php://output') will fight with Laravel's buffering on some FPM setups.

Spreadsheets for reporting. ezcDocumentOds is the right tool for "export this table to LibreOffice". For anything complex, prefer a plain CSV export and reserve ODS for documents where formatting, multi-sheet structure, or formulas are the actual requirement.

Test against fixtures. Keep a known-good .odt in tests/Fixtures/, generate output, unzip both, and assert on content.xml. Snapshot the unzipped XML rather than the binary — zips contain timestamps and the binary diff is useless.

Extension point: the library's styler/rendering layer is where you reach when default mappings don't suit you. If you find yourself subclassing to adjust DocBook element mapping, do it inside your wrapper and keep the subclass in app/Support/Odf/.

Gotchas and Tips

  • This is archived (last release 2014) and has zero dependents. Treat it as vendored legacy code, not a dependency you can rely on for fixes. Pin the exact version, and vendor a patch if you need one — upstream is not coming.
  • PHP version risk is the top item. The code predates PHP 7 and certainly PHP 8. Expect dynamic property deprecations, each(), and curly-brace string offsets on modern runtimes. Test on your actual runtime early; do not assume it installs cleanly.
  • License reads NOASSERTION. eZ Components historically shipped under GPL-family terms. Before this goes near a commercial product, get a human to confirm the license file in the repo. Do not infer it from the package name.
  • ODF is a zip — debug by unzipping. When output is subtly wrong, unzip -o doc.odt -d /tmp/doc && xmllint --format /tmp/doc/content.xml. Almost every "why does it look wrong" question is answered in content.xml or styles.xml.
  • DocBook validation failures are cryptic. The converter expects a specific DocBook subset. Strip to the smallest DocBook that converts, then add elements back one at a time until it breaks.
  • No namespacing guarantees across versions. Confirm the class names actually shipped in the tag you installed (grep -r "class ezcDocumentOdt" vendor/) rather than trusting docs or older tutorials.
  • Memory scales with document size. A few hundred table rows is fine; a thousand-page export will hit memory_limit. Enforce a size cap in the job and chunk at the domain level instead of fighting the library.
  • Beware loadString on user-influenced input. If DocBook is assembled from user data, escape values on the Blade side — the library will happily emit malformed XML and fail with an unhelpful parse error.
  • Content type matters. application/vnd.oasis.opendocument.text for .odt, ...spreadsheet for .ods, ...presentation for .odp. Getting this wrong makes browsers download without the right preview behaviour in LibreOffice-adjacent tooling.
  • If you only need Word/PDF, stop here. This library solves "open in LibreOffice natively". For .docx or PDF outputs, PhpWord or a headless LibreOffice conversion step is a better use of time — the maintenance cost of this package is only worth paying when ODF is a hard requirement.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle