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

Doctrine Relations Analyser Laravel Package

huluti/doctrine-relations-analyser

Doctrine Relations Analyser inspects Doctrine ORM entity associations to flag missing or misconfigured relations—such as absent inversedBy/mappedBy, cascade, orphanRemoval, and nullable settings—helping you catch mapping issues early and keep your model consistent.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, niche Symfony bundle (15 stars, no dependents), so treat it as a development and CI aid rather than production infrastructure. Its value is in surfacing Doctrine entity relationship problems—missing inverses, circular mappings, cascade/orphan-removal mistakes, and general graph shape—before they cause runtime or persistence bugs. As of 0.8.0 it also ships Symfony 8 support, so it can live alongside a current Symfony 7/8 stack; if you are still on Symfony 5.4/6.x, check the constraint in composer.json before upgrading.

Minimal setup:

composer require --dev huluti/doctrine-relations-analyser

Register the bundle unless a Flex recipe does it for you. In modern Symfony, add it to config/bundles.php:

return [
    // ...
    Huluti\DoctrineRelationsAnalyser\DoctrineRelationsAnalyserBundle::class => ['dev' => true, 'test' => true],
];

If the namespace differs, confirm it from the package’s composer.json (autoload.psr-4) or the bundle class under src/.

Where to look first:

  1. README — command names, options, and any required config.
  2. src/Command/ — the console entry points are the primary day-to-day interface.
  3. src/DependencyInjection/ and config/ — configuration tree, service IDs, and extension points.
  4. tests/ — expected output formats and edge cases the author actually covers.
  5. bin/console list — after registration, filter for relation/doctrine commands:
bin/console list | grep -i -E 'relation|doctrine'

First use case: run the bundle’s analysis command against a local database before a refactor. Use it to answer: “Which entities have unidirectional relationships that should be bidirectional?”, “Where do I have cascade cycles?”, and “Which mappings look suspicious?” Treat the output as a review checklist, not an automatic fix.

A sensible first command might look like:

bin/console doctrine:relations:analyse
# or whatever exact command name appears in `bin/console list`

If the bundle only exposes services rather than commands, inspect the container:

bin/console debug:container --tag=doctrine.relations_analyser
bin/console debug:container RelationsAnalyser

Implementation Patterns

Pre-refactor relationship audit

The highest-value workflow is using the analyser as a mapping review tool before changing entity relationships. Run it on a branch that is already migrated locally, then compare its findings with the actual mapping annotations/attributes:

bin/console doctrine:schema:validate
bin/console <relations-analyser-command> --env=dev

Use the analyser output to drive a checklist:

  • bidirectional relations missing an inversedBy/mappedBy;
  • cascade: ["remove"] combined with shared parent relationships;
  • orphanRemoval: true on relations where children are reassigned;
  • circular entity graphs that will break serialization or fixture loading.

CI guardrail for new mappings

If the bundle returns a meaningful exit code, wire it into CI as a non-blocking report first, then promote to blocking once you understand its false positives:

# .github/workflows/relations.yml
- name: Doctrine relationship analysis
  run: bin/console <relations-analyser-command> --env=test

If it does not return failure exit codes, capture the output and grep it in CI:

bin/console <relations-analyser-command> --env=test | tee relations.txt
! grep -qi 'critical\|error' relations.txt

Only make it blocking after validating the command against your actual entity set. Small packages often flag legitimate “unidirectional by design” relations.

Use it alongside Doctrine’s own tooling

This package complements, rather than replaces, Doctrine’s built-in checks:

bin/console doctrine:schema:validate
bin/console doctrine:mapping:info
bin/console doctrine:query:sql "SELECT 1"

Recommended sequence:

  1. doctrine:mapping:info — confirm all entities are discovered.
  2. doctrine:schema:validate — mapping/schema sync.
  3. relations-analyser — relationship-shape review.
  4. targeted integration tests / fixtures load — actual persistence behaviour.

Custom analysis in application code

If the bundle exposes an analyser service, inject it into a dev-only command or test rather than calling it from production code. First locate the service:

bin/console debug:container --show-private | grep -i analyser

Then, if available:

final class RelationAuditCommand extends Command
{
    protected static $defaultName = 'app:relations:audit';

    public function __construct(
        private readonly RelationsAnalyserInterface $analyser,
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $result = $this->analyser->analyse(/* entity names or metadata */);

        // Format for humans and CI logs.
        $output->writeln(json_encode($result, JSON_PRETTY_PRINT));

        return Command::SUCCESS;
    }
}

The exact interface name will differ; confirm from src/. If the package has no stable public API, wrap it behind your own app:relations:audit command so the rest of your tooling depends on your wrapper, not the package.

Test fixtures and graph checks

For applications with deeply nested entities, use the analyser before loading fixtures. A common failure mode is fixture order or cascade configuration that works in one test but fails in another. Add a lightweight test:

public function testEntityRelationshipsAreAnalysable(): void
{
    $analyser = static::getContainer()->get('test.service_container')
        ->get(RelationsAnalyserInterface::class);

    $result = $analyser->analyse();

    self::assertEmpty($result->getErrors(), print_r($result->getErrors(), true));
}

Guard with if (class_exists(...)) or keep it in a separate test suite if the bundle is dev-only.

Day-to-day usage summary

  • Before adding an entity relation: run the analyser to see whether the graph already has a related pattern.
  • After adding mapping attributes: run mapping validation plus the analyser.
  • Before deleting an entity or changing ownership: inspect impacted relationships and cascade rules.
  • In code review: paste analyser output when changing OneToMany, ManyToMany, cascade, or orphanRemoval.

Gotchas and Tips

  • Low adoption means API instability. With 15 stars and zero known dependents, command names, output formats, and service IDs can change between minor releases. Pin a version in composer.json if you depend on its output in CI, and review changelogs before upgrading. The 0.7 → 0.8 bump is a good example: the only change is Symfony 8 support, but because there is no SemVer contract on the console interface, treat every release as potentially output-format-breaking.
  • Symfony 8 support landed in 0.8.0. If you are already on Symfony 8 (PHP 8.4+, Doctrine ORM 3.x), you need at least 0.8.0 — earlier releases will not install. Conversely, if you are on older Symfony, verify the constraint before pinning; the major-version bump of the framework can pull in a new Doctrine version whose metadata APIs the analyser may not yet exercise.
  • It is a development tool. Register it only in dev and test environments. Do not make production runtime depend on it.
  • Command names are the first friction point. After installation, confirm the actual command with bin/console list. Do not assume the README command matches the installed version.
  • Output may be informational, not actionable. Relationship analysis often produces false positives for intentionally unidirectional mappings, legacy entities, or polymorphic/inheritance setups. Build an allowlist or baseline before blocking CI.
  • Inheritance and embeddables are common blind spots. Single-table inheritance, mapped superclasses, embeddables, and ResolveTargetEntityListener setups can confuse metadata-based analysers. Cross-check results against doctrine:mapping:info.
  • Proxies and runtime state are not the same as metadata. The analyser likely works from Doctrine metadata, not live object graphs. It can tell you a relation is mapped, not whether your service layer actually populates it correctly.
  • Doctrine metadata must be bootable. If doctrine:mapping:info fails, the analyser will too. Fix mapping errors first.
  • Circular reference handling matters. If you serialize analyser output to JSON, use json_encode with depth limits or a normalizer; entity graphs can be cyclic.
  • Memory on large graphs. For applications with hundreds of entities, run the analyser in a dedicated CI job rather than on every request or test. If it walks the full metadata graph, expect startup and memory overhead.
  • Check the bundle registration order. If the analyser depends on Doctrine services, register it after DoctrineBundle in config/bundles.php (normally automatic, but relevant in manual setups).
  • Configuration quirks. Inspect src/DependencyInjection/Configuration.php for supported options—entity filters, output format, ignored relations. If there is no config tree, expect convention-based behaviour and hard-coded assumptions.
  • Extension point: wrap it. The safest long-term pattern is to create your own app:relations:audit command and formatter. If the package is abandoned or breaks on a Doctrine upgrade, only your wrapper changes.
  • Debugging failed analysis: run with -vvv, check var/log/dev.log, and verify the Doctrine entity manager is available:
bin/console debug:container doctrine.orm.default_entity_manager
bin/console doctrine:mapping:info -vvv
  • Upgrade risk is real. Doctrine ORM and Symfony major upgrades change metadata and bundle APIs. 0.8.0 proves the maintainer is still tracking Symfony releases, but there is a single maintainer and no test matrix visible against Doctrine 3 + Symfony 8 combinations — test this bundle after any framework or ORM upgrade and be prepared to remove it if it lags.
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