Documents
Description
Documents is a Laravel Enso backend package for generic document management. It provides document categories, document types, type-owned field definitions, editable HTML templates, reusable partials, generated files, PDF generation, signature requests, and placeholder resolution.
The package intentionally does not define polymorphic ownership links. Consuming applications add their own local foreign keys or link tables over documents when they need to connect generated or uploaded files to project, profile, request, contract, or other application-owned records.
It is the backend companion for @enso-ui/documents.
Installation
Install the package:
composer require laravel-enso/documents
Run the package migrations:
php artisan migrate
Register frontend routes from @enso-ui/documents in the consuming application when the administrative UI is needed.
Features
- Administration CRUD for document type categories, document types, type-owned fields, partials, and templates.
- Document archive tables for persisted generated or uploaded files.
- Type-level static PDF model upload through
document_types.file_id. - Active template selection through
document_types.template_id. - Type-owned field definitions stored in
document_type_fields, ordered per type. - Typed document field values stored in
document_field_values. - Reusable partials for headers, footers, and body snippets.
- Placeholder contexts and placeholder classes registered by applications.
- Template rendering with partial expansion and placeholder replacement.
- PDF generation with configurable fonts, line height, and PDF options.
- Signature request lifecycle with token refresh, expiry, preview, signing, and persisted signed document output.
- Requirements service for checking placeholder completeness before local workflows generate or sign documents.
- Events for external integration after documents are generated or signature requests are signed.
Usage
Core Models
LaravelEnso\Documents\Models\Document: persisted document record with a required file.LaravelEnso\Documents\Models\Type: document type, optional category, optional static PDF file, and optional active template.LaravelEnso\Documents\Models\Category: document type grouping.LaravelEnso\Documents\Models\Field: type-owned field definition stored indocument_type_fields.LaravelEnso\Documents\Models\Value: typed value for a concrete document field stored indocument_field_values.LaravelEnso\Documents\Models\Template: editable HTML template tied to one document type.LaravelEnso\Documents\Models\Partial: reusable HTML fragment for header, footer, or body include.LaravelEnso\Documents\Models\SignatureRequest: generic signing workflow record.
Field Definitions And Values
Field definitions belong to one document type:
$type->fields; // hasMany(Field::class), ordered by order_index
The field definition table is document_type_fields and includes:
document_type_idnameslugdescriptionvalidationscustom_validationstypeoption_sourceorder_index
Field slugs are unique per document type. option_source is required for select fields and may reference either:
- an enum implementing
LaravelEnso\Enums\Contracts\Select; - an Eloquent model implementing
LaravelEnso\Documents\Contracts\OptionSource.
Document values are stored separately in document_field_values and belong to a concrete document:
$document->values; // hasMany(Value::class)
The value table stores exactly one typed value column for each row:
string_valueforField::String;integer_valueforField::Numeric;date_valueforField::Date;boolean_valueforField::Checkbox;json_valueforField::Select, with at leastidandname.
Value validates that document_id, document_type_id, and field_id are consistent, and that the populated value column matches the field type.
Templates, Partials, And Placeholders
Applications register contexts and placeholders in their service providers:
use LaravelEnso\Documents\Resolvers\Contexts;
Contexts::register(App\Documents\Contexts\Project::class);
Context classes implement LaravelEnso\Documents\Contracts\Context; placeholder classes implement LaravelEnso\Documents\Contracts\Placeholder. Template syntax uses simple tokens such as {projectCode} and {clientName}.
Partials are stored in document_partials. Header and footer selectors use is_header and is_footer; body partials use both flags as false and may be included in template content with tokens such as {terms}.
Partials may contain placeholders. Partials cannot include other partials.
Generation
Generate a document from a template-backed type:
use LaravelEnso\Documents\Services\Generator;
$document = (new Generator($type))
->withPayload($payload)
->withFilename('contract.pdf')
->generate();
If no filename is provided, the generator uses the template filename. Generated files are PDFs.
Requirements
Check whether a payload satisfies the placeholders used by a template:
use LaravelEnso\Documents\Services\Requirements;
$requirements = (new Requirements())->check($template, $payload);
(new Requirements())->assertValid($template, $payload);
The default rule follows Laravel filled semantics: null, empty strings, and empty arrays are missing; 0 and false are valid values. Placeholder classes may customize validity and message output.
Applications may override LaravelEnso\Documents\Contracts\Requirements\Validator to add application-specific requirements.
Signature Requests
SignatureRequest uses its document type's active template and dynamic payload to render the public preview. The package does not create a Document when the public signature link is opened.
When the request is signed, the package regenerates the PDF with the submitted SVG signature, creates a File, creates a Document, links it to the signature request, and marks the request as signed.
Token validity is configured through enso.documents.signatureRequests.validityDays.
Configuration
The package publishes/merges config/enso/documents.php under the enso.documents config key:
return [
'fonts' => [
'family' => 'Inter',
'lineHeight' => 1.45,
],
'pdfOptions' => [
'margin-top' => 30,
'margin-left' => 20,
'margin-right' => 20,
'margin-bottom' => 20,
'footer-font-size' => 9,
'enable-local-file-access' => true,
'header-font-name' => 'Inter',
'footer-font-name' => 'Inter',
],
'signatureRequests' => [
'validityDays' => 7,
],
];
API
Administration Routes
Protected routes use api, auth, and core middleware.
administration.documents.categories.*administration.documents.types.*administration.documents.fields.*administration.documents.partials.*administration.documents.templates.*
The administration surface exposes table initialization, table data, Excel export, create/edit forms, store/update/destroy actions, and select options where applicable.
Document Routes
documents.initTabledocuments.tableDatadocuments.exportExceldocuments.optionsdocuments.signatureRequests.initTabledocuments.signatureRequests.tableDatadocuments.signatureRequests.exportExceldocuments.signatureRequests.refreshTokendocuments.publicSignatureRequests.showdocuments.publicSignatureRequests.sign
Public signature show/sign routes are token-based and do not create menu or permission entries.
Contracts
LaravelEnso\Documents\Contracts\ContextLaravelEnso\Documents\Contracts\PlaceholderLaravelEnso\Documents\Contracts\OptionSourceLaravelEnso\Documents\Contracts\Requirements\Validator
Services
LaravelEnso\Documents\Services\GeneratorLaravelEnso\Documents\Services\RequirementsLaravelEnso\Documents\Resolvers\ContextsLaravelEnso\Documents\Resolvers\Placeholder
Depends On
laravel-enso/corelaravel-enso/fileslaravel-enso/formslaravel-enso/helperslaravel-enso/pdflaravel-enso/selectlaravel-enso/tableslaravel-enso/track-wholaravel-enso/users
Contributions
are welcome. Pull requests are great, but issues are good too.
Thank you to all the people who already contributed to Enso!