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

Laravel Gedcom Laravel Package

liberu-genealogy/laravel-gedcom

Laravel GEDCOM provides a Laravel-friendly toolkit for working with GEDCOM genealogy files, including parsing, importing, exporting, and managing family tree records such as individuals, families, events, and sources through an Eloquent-based workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm the wiring

composer require liberu-genealogy/laravel-gedcom

The package ships with Laravel package auto-discovery, so the service provider and any facade should register without touching config/app.php. Run php artisan vendor:publish --provider="Liberu\Genealogy\Gedcom\GedcomServiceProvider" (check the README for the exact provider class in your installed version) to pull out any config or migration stubs before you write code against it.

Where to look first

  1. README.md — the canonical surface area; the class names below come from there, not from guessing.
  2. src/GedcomGenerator.php — the export path. This is the class touched in v8.6.0, so it is the most actively maintained entry point.
  3. The parser/reader class (typically alongside the generator) — the import path.
  4. tests/ — the fixtures are usually real .ged snippets and are the fastest way to learn the expected shape of parsed records.
  5. Any Source class or interface — this is the abstraction resolved through the container as of v8.6.0.

First use case: round-trip a file

The lowest-risk first task is a read-then-write round trip: parse a small GEDCOM file you already have, dump the resulting structure, then feed it back through the generator and diff the output. That single exercise tells you the record model, the ordering guarantees, and where the package normalises versus preserves raw lines — all before you build anything on top of it.

Resolve everything from the container rather than new-ing classes directly. Given the v8.6.0 change, the generator now pulls Source from the container, which means constructor injection and app() resolution give you the same object graph — but manual instantiation may not.

Implementation Patterns

Constructor injection, not new

public function __construct(private GedcomGenerator $generator) {}

This is the pattern the package is steering you toward. Since Source is now container-resolved inside the generator, any binding you register for Source will be honoured during export. Direct instantiation bypasses that and will silently ignore your bindings.

Swap Source via a service provider

The practical payoff of the v8.6.0 change is testability and extendability. Bind your own implementation in a provider:

$this->app->bind(Source::class, DatabaseSource::class);

Day-to-day this lets you back exports with Eloquent models, an API client, or a fixture stub without forking the generator. Keep test bindings inside TestCase::setUp() and reset them in tearDown() — container bindings are global to the application instance and leak between tests otherwise.

Import as a queued job

GEDCOM files are line-oriented and can be tens of megabytes. Wrap parsing in a job, not a controller action:

  • Accept the upload, store it on a private disk, dispatch the job with the path.
  • Parse into your own Eloquent schema inside the job — do not persist the package's intermediate structures directly; you will regret coupling to them at the next major.
  • Emit progress per record batch so the UI has something to show.
  • Fail loudly on individual malformed records but keep going, collecting errors into a report.

Export as a streamed download

Generate the file, write it to a temp path or Storage, then response()->download(...)->deleteFileAfterSend(true). For large trees, generate into a stream and skip holding the full string in memory.

Facade where injection is awkward

In Blade, artisan commands, and quick scripts, the facade (if provided) or app(GedcomGenerator::class) keeps you on the container-resolved path. Inside domain services, prefer constructor injection.

Model the domain, not the file format

Map parsed individuals, families, and events onto your own models with explicit foreign keys. Treat the package as a translation layer at the boundary of your app: GEDCOM in → your models → GEDCOM out. This makes swapping or upgrading the package a contained change and lets you test your genealogy logic without touching real files.

Test with fixtures

Keep a handful of .ged files in tests/fixtures: minimal, one with non-ASCII names, one with a malformed line, one large enough to exercise batching. Assert on your models, not on the package's internal arrays.

Gotchas and Tips

Container resolution is now behavioural, not incidental

Before v8.6.0, Source was presumably constructed directly inside GedcomGenerator. Now it comes from the container. Consequences:

  • A Source whose constructor needs arguments must be bound, or it will fail to resolve. Register a closure binding or use singleton with a factory rather than relying on autowiring.
  • A singleton binding means one Source instance is shared across an entire request and across multiple generator calls. If your source accumulates state during export, you will see duplicated or leaked records on the second export in the same process — which is exactly the kind of thing that only shows up in a queue worker. Prefer bind unless you have a reason.
  • If you were previously instantiating Source yourself and passing it in, re-check the constructor signature: it may have changed or gained a default.

Laravel 13 support landed with a host pin

The CI change accepts Laravel 13 but pins the runner host, which usually signals that the matrix resolves differently on other hosts. If you run the package's own suite in your CI, mirror their approach — a composer update on a different image may produce a matrix you have not tested. For your application, verify on your actual PHP/Laravel combination rather than assuming the green badge covers it.

Encoding is the number one source of corruption

GEDCOM historically permits ANSEL as well as UTF-8, and older files routinely arrive in it. Non-ASCII names will silently mangle into mojibake if you assume UTF-8. Detect, convert at the boundary, and store UTF-8 internally. Round-trip a file with accented characters and a non-Latin name before trusting anything.

Line endings and continuations

The format is CRLF-oriented and long values are split across CONC (concatenate) and CONT (newline) lines. A parser that handles one but not the other will truncate notes and addresses in ways that are invisible until a user complains. Write a fixture with a deliberately long NOTE and assert the reassembled value.

Trailing whitespace in level numbers

GEDCOM level numbers are significant, and some exporters emit 0 @I1@ INDI with trailing spaces or tabs. If records vanish on import, dump the raw line with visible whitespace before assuming a logic bug.

Debugging: keep the raw text

When output looks wrong, the fastest path is to dd() the raw generated string or write it to storage/app/debug.ged and diff against a known-good file. Diffing two GEDCOM files line by line identifies ordering and tag problems far faster than stepping through the object model.

Ordering is not guaranteed

Do not rely on records coming back in file order, or on HEAD/TRLR neighbours being preserved. Sort explicitly in your own code if order matters downstream. Similarly, records without @X@ cross-references are not linkable — validate that individuals and families carry IDs before building relationships.

Extension points worth knowing

  • Container binding for Source — the main supported customisation.
  • Any config published from the provider — check for encoding, default paths, or strictness flags before hardcoding behaviour in your app.
  • Because generation is now container-driven, a decorator around Source (logging, caching, filtering) is a clean way to add cross-cutting behaviour without touching the generator.

Upgrade hygiene

The package is at v8.x with an active changelog, so minor bumps have introduced behavioural changes (v8.6.0 is a live example). Pin to ^8.6 rather than ^8.0, read the changelog on every bump, and keep your round-trip fixture test in CI — it will catch a container-resolution shift or an encoding change in one run.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
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