Repository navigation
Laravel: implicit framework mount prefix (/api) not composed onto routes from routes/api.php #1146
Description
Version
main @ e678b2b (v0.9.0-221, includes the #952 fix from PR #1059)
Platform
macOS (Apple Silicon)
Install channel
GitHub release archive / install.sh / install.ps1
Binary variant
standard
What happened, and what did you expect?
PR #1059 fixed facade-style Route::get(...) extraction and prefix()->group() composition — thank you, this works well (132/132 registrations captured on our production Laravel 11 gateway). However, the minted Route node paths are still missing the framework-level mount prefix that Laravel applies to every route registered in routes/api.php. The graph mints GET /users/me while the runtime route is GET /api/users/me.
Why it matters
Route identity is the join key for cross-repo-intelligence (CROSS_HTTP_CALLS matches canonicalized paths literally). Real HTTP callers (frontends, other services, artisan snapshots) reference /api/users/me, so the minted identities never match and cross-repo HTTP edges stay at zero even though both sides are now extracted.
Where the prefix comes from
Laravel 11+: Application::configure()->withRouting(api: ...) mounts the api file under the apiPrefix argument, default 'api'. (Laravel ≤ 10 used RouteServiceProvider::boot() instead — feel free to ignore that variant: most projects are on 11+ by now, so covering withRouting() alone is enough.)
Suggested fix
At extraction time, when processing a routes file:
- If
bootstrap/app.phpis parseable, readwithRouting(...): routes registered in the file passed asapi:get theapiPrefix:value (defaultapi) prepended; theweb:file gets no prefix. - Fallback heuristic when
bootstrap/app.phpcan't be resolved: prepend/apito routes minted from a file namedroutes/api.phpby convention. A property on the Route node (e.g.mount_prefix_inferred: true) would make the heuristic transparent.
Same class of problem as the group-prefix composition solved in #1059 — this is just one more enclosing prefix, declared in a different file.
Environment
Fleet of Laravel 11 + PHP 8.4 services (roadrunner), routes registered exclusively facade-style in routes/api.php with nested prefix()->group() blocks. Built from source on Linux x86_64, gcc, make -f Makefile.cbm cbm.
Reproduction
- Code: minimal Laravel 11+ app shape.
bootstrap/app.php:
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
api: __DIR__.'/../routes/api.php', // <- everything in this file is mounted under /api
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
...routes/api.php:
Route::prefix('/users')->middleware(DomainCheckMiddleware::class)->group(function (): void {
Route::get('/me', GetCurrentUserController::class);
});php artisan route:list shows GET api/users/me.
-
Command:
codebase-memory-mcp cli index_repository --repo-path .then
codebase-memory-mcp cli query_graphwithMATCH (r:Route) WHERE r.name CONTAINS 'users/me' RETURN r.name, r.method -
Result:
/users/me, GET/ Expected:/api/users/me, GET
Logs
Diagnostics trajectory (memory / performance / leak issues)
Project scale (if relevant)
4,077 nodes / 11,248 edges / ~430 files (Laravel gateway repo)
Confirmations
- I searched existing issues and this is not a duplicate.
- My reproduction uses shareable code (a dummy snippet or a public OSS repository), not proprietary code.
Activity
DeusData commentedon Jul 18, 2026
Thanks for the detailed follow-up to the Laravel route work. This is a high-priority 0.9.1-rc extraction-correctness bug under #592. The RED coverage should separate an explicit
withRouting(apiPrefix: ...)case from the default-prefix convention and prove the final composed identity used by cross-repository matching. Any filename-only fallback must remain distinguishable from a prefix proven frombootstrap/app.phpso the graph does not present inference as source fact.fix(routes): compose the Laravel 11+ withRouting api prefix into Rout…
fix(routes): compose the Laravel 11+ withRouting api prefix into Rout…
DeusData commentedon Oct 1, 2026
Hi @paolo-blocklabs, thank you so much for this report and for the careful follow-up to #952. The minimal repro, the pointer to
withRouting(), and your note on why route identity matters for cross-repo matching made this easy to pin down.It turned out to be three separate gaps, fixed in #2447 (the api mount), #2465 (class-based actions) and #2471 (slash-less URIs):
bootstrap/app.php. When->withRouting(api: ...)names a route file, it prependsapiPrefix(defaultapi, custom values like'v1/api'too) to every route from that file, so your example now mintsGET /api/users/me, asroute:listshows. Theweb:file stays unprefixed, and nothing is inferred from file names: a non-literalapiPrefixor ausing:callback leaves paths untouched rather than guessed.[Controller::class, 'method']and invokableController::classnow get a handler edge. The class is resolved through youruseimports and the composer PSR-4 root, never by short name alone.Route::get('users', ...)is now recorded as/users, including insideRoute::group(['prefix' => ...]).The cross-repo matcher needs both the full
/api/...path and a handler on the route, which is why your frontend calls were never linked. With the three fixes together, a reproduction of your setup linksfetch('/api/users/me')toGetCurrentUserController::__invoke. Thanks again for helping make the Laravel support solid!Merge pull request #2447 from DeusData/fix/issue-1146-laravel-withrou…
fix(routes): mint Laravel routes written without a leading slash
fix(routes): HANDLES for Laravel array and invokable controller actions
fix(routes): resolve PSR-4 handler classes through the class-file res…
fix(routes): leave a PSR-4-covered handler without a class file unres…
Merge main into fix/issue-686-fiber-group-v2 for the release batch
DeusData commentedon Oct 7, 2026
All three fixes are now on main and will ship in the next release: #2447 (the api mount) in 6644fc4, #2471 (slash-less URIs) in bf93f0b, and #2465 (class-based actions) in 1aabc40. Thanks again, @paolo-blocklabs!