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

Classname Mapper Laravel Package

mouf/classname-mapper

mouf/classname-mapper is a lightweight PHP utility for mapping class names to custom identifiers, making it easier to resolve aliases and decouple configuration from concrete class strings. Useful for DI containers, plugin registries, and flexible component lookup.

View on GitHub
Deep Wiki
Context7

Getting Started

Pull the package in and pin it, because this is effectively abandoned (last release Jan 2019, PHP 7 era):

composer require mouf/classname-mapper

Before writing any code, read three things in the repo, in this order:

  1. composer.json — see what transitive Mouf packages it drags in (several mouf/* packages assume a Mouf DI container you will not be running).
  2. The ClassnameMapperInterface (or equivalent) — this is the entire contract: given a class name, return the file it would be loaded from (and usually a way to enumerate everything it knows about).
  3. The concrete implementations — typically one that wraps Composer's PSR-4/classmap data and one that composes several mappers together.

Treat the package as a small, readable utility, not infrastructure. The value is the interface and the "aggregate several resolution strategies" pattern; you can vendor a fork in app/Support/ in an afternoon if it fights PHP 8.

First use case that actually fits Laravel: you have a class name as a string from somewhere non-static — a DB column, a config value, a queue payload, a route parameter — and you need the file path so you can reflect on it (attributes, docblocks, method signatures) without instantiating it. Typical shape: a "modules" or "plugins" table where each row names a class, and you want to enumerate/validate those classes at boot or in an Artisan command.

// app/Providers/ClassnameMapperServiceProvider.php
public function register(): void
{
    $this->app->singleton(ClassnameMapperInterface::class, function () {
        // Build from your PSR-4 roots + Composer's classmap.
        // Check the concrete constructor signature in the repo; most
        // implementations take prefix => directory pairs or are composed.
        return new /* ... */ ClassnameMapper(/* ... */);
    });
}

Implementation Patterns

Bind the interface, never the concrete class. The package's whole design is "compose mappers," so having the container resolve an interface lets you swap in a cached or test-double mapper without touching call sites.

Compose, don't configure. If the package ships an aggregate mapper, register your PSR-4 roots as one child mapper and Composer's vendor/composer/autoload_classmap.php as another. Order matters: put the authoritative classmap first if you want composer dump-autoload -o semantics.

Pair it with ReflectionClass, not with class_exists. The mapper answers "where," reflection answers "what." A clean discovery pattern:

foreach ($mapper->getClassPaths() as $className => $path) {
    if (! str_starts_with($className, 'App\\Modules\\')) {
        continue;
    }

    $reflection = new \ReflectionClass($className);

    foreach ($reflection->getAttributes(Module::class) as $attribute) {
        $modules->register($className, $attribute->newInstance());
    }
}

Because you get paths, you can pre-filter by file mtime or directory before triggering autoload — useful when the map is large.

Cache the built map on deploy, not per request. Building a mapper that walks directories is filesystem I/O. Serialize the resolved className => path array into Laravel's cache (or a generated PHP file like bootstrap/cache/classmap.php) inside a php artisan app:cache-classes command, and rebuild it in your deploy script after composer install. This mirrors what Composer does and is the only way this package stays cheap in production.

Use it in Artisan commands and validation rules, not in hot paths. The natural home is php artisan modules:list, a ClassExistsInMapper validation rule for admin-supplied class strings, or a config sanity check at boot. Do not put a mapper call inside a loop that renders views.

Wrap it behind your own small service. App\Support\ClassLocator with path(string $class): ?string and all(): array means the 2019 package is an implementation detail you can replace with a 20-line Composer ClassLoader wrapper the day it breaks.

Gotchas and Tips

  • Unmaintained and PHP-7-shaped. Expect deprecation noise on PHP 8.1+ (dynamic properties, implicit nullable params, ${var} interpolation). Run the suite under your target PHP before committing to it; if it breaks, fork it — the surface area is tiny.
  • Zero dependents, 11 stars. There is no community, no issue triage, no security process. Budget for owning the code. Do not build a load-bearing feature on top of it.
  • It does not load classes. This is a resolution utility: it tells you which file a class would be found in. Actual autoloading is still Composer's job. If the class isn't in Composer's autoload config, the mapper won't invent it — and calling new ReflectionClass($name) will still trigger the real autoloader and throw if Composer can't find it. Use the path result to avoid autoloading, not to replace it.
  • classmap-authoritative will lie to you. If your production composer.json sets "classmap-authoritative": true or "optimize-autoloader": true, the map the package derives from Composer data will differ from dev. Verify behaviour in a production-shaped build, not just php artisan serve.
  • PSR-4 case sensitivity. Class names and directory names must match exactly on Linux. A mapper that worked on macOS will silently return null in CI. Add a test that asserts a known class resolves to a known path.
  • null vs false vs exception. Check what the interface returns for "not found" and normalise it in your wrapper. This is the single most common source of TypeError when swapping implementations.
  • Mouf container assumptions. Some mouf/* siblings expect Mouf\Container or a MOUF_URL/ROOT_PATH constant. If you see a ContainerException or a missing-constant fatal on boot, you're hitting that — bypass the factory classes and instantiate the plain mapper directly.
  • Extension point is the interface. Custom resolution (e.g., classes registered in a database, or a legacy non-PSR-4 tree) is a one-method implementation of the mapper contract composed into the aggregate. That's the intended way to add behaviour, and it's cheap.
  • Debugging: dump the full map with dd($mapper->getClassPaths()) (or whatever enumeration method the version exposes) and diff it against require 'vendor/composer/autoload_classmap.php'. If your class is missing from both, the problem is composer.json, not the mapper.
  • Testing: point the mapper at a tests/Fixtures/ tree rather than app/, so refactors of your real namespaces don't break mapper tests.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin