jorgehernan/odmrelationshipview-bundle
jorgehernan/odmrelationshipview-bundle is a Symfony bundle for working with Doctrine ODM relationships, offering view integration to inspect and display document associations in ODM-backed applications.
First, confirm the mismatch. This is a Symfony bundle (*Bundle suffix, Resources/config/, kernel registration). Laravel has no ServiceProvider, no config/bundles.php, no AppKernel. If your composer.json is a Laravel app, composer require jorgehernan/odmrelationshipview-bundle will either fail on install (Symfony framework-bundle constraints) or install dead code you can never boot. Before writing any code, run:
composer require jorgehernan/odmrelationshipview-bundle --dry-run
If it refuses to resolve against laravel/framework, stop. That is the fast answer.
Where to look first (as reference material, not a dependency): read the repo's Resources/config/services.yml to see the relationship-graph service IDs and how they query Doctrine ODM, then Resources/views/ for the Twig templates. For a 2-star utility the templates and the query builder calls are the whole product — the PHP is thin glue. Pull the source with git clone into a throwaway directory and read it there; do not add it to composer.json.
First use case in a Laravel app: reproduce the core idea natively with mongodb/laravel-mongodb. If the goal is "show me what a document references and what references it," that is one or two Eloquent-style queries and a Blade partial. Minimum viable version:
// app/Http/Controllers/RelationshipsController.php
public function show(string $collection, string $id)
{
$doc = DB::connection('mongodb')->collection($collection)->find($id);
$inbound = DB::connection('mongodb')->collection('__your_ref_collection')
->where('parent.$id', new ObjectId($id))
->limit(50)->get();
return view('admin.relationships.show', compact('doc', 'inbound'));
}
Confirm your MongoDB connection in config/database.php under 'mongodb' works before building anything around it. Then gate the route: ->middleware(['auth', 'can:view-admin']).
Treat the bundle as a design reference, and implement the equivalent pattern in Laravel. The realistic day-to-day patterns:
Read the bundle's config tree, mirror it in config/. Symfony bundles expose a Configuration.php (or DependencyInjection/Configuration.php) describing document paths and display options. Copy the shape of that into config/relationships.php as plain Laravel config — that is cheaper than porting the DI wiring.
Port the query pattern, not the classes. Look at how the bundle resolves ReferenceOne vs ReferenceMany. In mongodb/laravel-mongodb you get that out of the box via belongsTo / hasMany with $foreignKey overrides. A "relationship view" is: for each document type, list its outbound edges (query the document and inspect which fields are DBRefs) and inbound edges (query each known ref field with ->where('field.$id', $oid)).
Cache the graph. If the bundle renders a graph per request, your ported version will too. Cache the node/edge list per collection with Cache::remember("relgraph:{$collection}", 300, fn() => ...) — ODM relationship traversal is N+1 prone, which is a large part of why this bundle exists in the first place.
Hydrate in one query. When fanning out from a document to its referenced docs, collect the _ids first, then issue a single whereIn('_id', $ids). Do not iterate and find() per reference.
Blade partial over a full layout. Adopt the view concept (a graph of nodes and edges) into your admin layout. A tiny D3/Cytoscape component fed by a JSON endpoint is the modern equivalent:
Route::get('/admin/relationships/{collection}/graph', [GraphController::class, 'json'])
->middleware(['auth', 'can:view-admin']);
Test it like a first-party feature. Because there are 0 dependents, you're the QA. Seed two collections with a reference, assert the graph JSON contains both nodes and the edge.
If you must run the Symfony bundle for a spike: stand it up in a throwaway Symfony skeleton app, not in your Laravel app. Symfony 3.4/4.x with a matching doctrine/mongodb-odm-bundle is the realistic target. Modern PHP 8.2 will fight old Symfony — expect to pin PHP 7.4 in a container just to boot it. That cost is why the recommendation is "read, don't require."
The -bundle suffix is not cosmetic. Laravel PackageManifest auto-discovery looks for extra.laravel.providers, not a Symfony Bundle class. There is no path for php artisan vendor:publish here. You cannot "Laravel-ify" this without porting the class tree.
No doctrine/mongodb-odm in a stock Laravel app. Laravel is Eloquent-first. Adding Doctrine ODM just to run this bundle means two persistence layers, two lifecycles, and two sets of migrations. Not worth it for a read-only graph view.
N+1 is the real trap in ported code. Doctrine ODM lazily hydrates reference collections. If you lift query code from this bundle, watch for foreach ($doc->getRelated() as $r) patterns — each iteration hits Mongo. Port with whereIn batching, then profile with DB::listen().
ObjectId vs string comparison. ->where('ref.$id', $id) needs an ObjectId instance, not a string, or the match silently returns empty. Cast defensively:
use MongoDB\BSON\ObjectId;
$oid = $id instanceof ObjectId ? $id : new ObjectId($id);
DBRef format varies across Doctrine ODM versions ($ref/$id vs $db/$ref/$id). The bundle may assume a particular ODM version; your Laravel Mongo connection may write a different shape. Inspect a real document with mongosh before hard-coding a path like parent.$id. If it's actually parent._id, your query silently returns nothing.
security.yaml has no Laravel equivalent. The Symfony bundle typically expects a firewall entry guarding its dev route. The Laravel analogue is access_control replaced by middleware + gates — make sure you actually add them, because a public graph endpoint leaks your entire data model.
Autoload / config quirks. Symfony bundles from the 2/3 era use Resources/config/services.xml and services.yml files Symfony 4+ no longer reads (paths moved to config/). If you ever boot it, rename and adjust. That is a hint at age — budget for it.
Debugging strategy. bin/console debug:container | grep -i relationship in a Symfony spike shows service IDs. In Laravel, the equivalent is php artisan route:list | grep relationship and php artisan tinker against the ported query. With no issue tracker to search, your only debugging surface is your own ported code — document it, because you're the maintainer now.
Forking rules, if you must. MIT permits a hard fork. Fork to a private repo only if you need the actual Symfony code in a Symfony service and are prepared to pin all Symfony + Doctrine versions. Do not fork for a Laravel app — you'd be maintaining an integration layer nobody asked for. Build the ~100 lines in-house, name an owner, and put a // ported from jorgehernan/odmrelationshipview-bundle (MIT) header in the file so future-you knows where the pattern came from.
How can I help you explore Laravel packages today?