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 Morphmap Js Generator Laravel Package

gigerit/laravel-morphmap-js-generator

Generates a JavaScript file from your Laravel morph map so front-end code can resolve model aliases without hardcoding class names. Keeps polymorphic types in sync across PHP and JS, avoiding mismatches when morph aliases change.

View on GitHub
Deep Wiki
Context7

Getting Started

This package bridges Laravel's polymorphic type aliases (morphMap) to your JavaScript/TypeScript front end so that a commentable_type string coming from the API can be resolved to a real class name, route, or component without duplicating the map by hand.

Minimal setup

  1. Install as a dev dependency — the generated artifact is a build input, not runtime PHP:
    composer require --dev gigerit/laravel-morphmap-js-generator
    
  2. Publish the config so you can point it at your front-end source tree:
    php artisan vendor:publish --tag="morph-map-config"
    
  3. Make sure a morph map actually exists. The generator reads whatever Relation::morphMap() / Relation::enforceMorphMap() registered — typically in AppServiceProvider::boot():
    Relation::enforceMorphMap([
        'post'    => \App\Models\Post::class,
        'video'   => \App\Models\Video::class,
        'comment' => \App\Models\Comment::class,
    ]);
    
  4. Generate. Confirm the exact signature first, since command names vary between majors:
    php artisan list morph
    php artisan morph-map:generate
    
  5. Open the generated file (default path is set in config/morph-map.php) and import it in your front end.

First use case: a polymorphic activity feed. The API returns { subject_type: "post", subject_id: 42 }. Import the generated map and resolve:

import morphMap from '@/generated/morph-map.js';

const model = morphMap[activity.subject_type]; // "App\\Models\\Post"

If you don't need the FQCN, the higher-value pattern is mapping aliases to front-end concerns (route names, icons, component keys) — see below.

Implementation Patterns

Regenerate as part of the build, never by hand. Add it to composer.json scripts so it can't drift:

"scripts": {
  "post-autoload-dump": ["@php artisan morph-map:generate"]
}

Or hook it into Vite so npm run dev/build always sees fresh data:

// vite.config.js
import { defineConfig } from 'vite';
import { execSync } from 'node:child_process';

export default defineConfig({
  plugins: [{
    name: 'morph-map',
    buildStart() { execSync('php artisan morph-map:generate', { stdio: 'inherit' }); },
  }],
});

Note that buildStart alone won't watch PHP files — for a live dev loop, add a watcher on app/Models and app/Providers that re-runs the command.

Decorate the raw map rather than replacing it. Keep the generated file dumb and wrap it:

// resources/js/morph.ts
import morphMap from '@/generated/morph-map.js';

export const resources = {
  'App\\Models\\Post':    { route: 'posts.show',    icon: 'file-text' },
  'App\\Models\\Video':   { route: 'videos.show',   icon: 'play' },
  'App\\Models\\Comment': { route: 'comments.show', icon: 'message' },
};

export const resolve = (alias) => resources[morphMap[alias]] ?? null;

This keeps the generated artifact out of your diffs' logic and survives regeneration.

Drift detection in CI. Because the file is derived, a stale commit silently breaks the front end:

- run: php artisan morph-map:generate
- run: git diff --exit-code resources/js/generated/morph-map.js

Pair it with a PHP test that asserts every model using HasRelationships/morph relations is present in the map — enforceMorphMap already throws on unmapped models in non-production, which you can lean on.

Gitignore vs commit. Two defensible choices: commit the artifact (front-end-only contributors and CI builds don't need PHP), or gitignore it and require composer install && artisan morph-map:generate before npm run build. Committing is usually the pragmatic default for a Laravel monorepo; if you gitignore, make the generation step an explicit prerequisite in your deploy pipeline, not an afterthought.

Deployment. Run the command in the release step after config:cache is rebuilt, so the morph map reflects the deployed provider code.

Gotchas and Tips

v1.2.2 changed the output to plain JavaScript — regenerate everything. Prior to this fix the default command emitted JSON-shaped output into a .js file, which would either fail to parse as an ES module or silently export an object only via an implicit expression. If you worked around it with JSON.parse(fs.readFileSync(...)), a .json output path, or a fetch() against the generated file, drop that workaround and re-run the command. Also restart Vite and clear node_modules/.vite — the stale transform is cached and you'll otherwise conclude the fix didn't land.

An empty map almost always means the morph map wasn't bootstrapped. The command only sees what's registered during that console run. If you generate in an environment where AppServiceProvider is skipped, or where morphMap is guarded by if (app()->runningInConsole())/environment checks, you get {}. Keep registration unconditional and verify with php artisan tinker --execute="dump(array_keys(Relation::morphMap()));".

enforceMorphMap bites in production. It throws ClassMorphViolationException for any model not in the map. That's a feature, but it means a model added to the app without a morph alias will break at runtime, not at generation time — your CI parity test is what catches it early.

Alias keys need care in generated JS. Aliases like blog.post, foo-bar, or numeric strings must be quoted object keys. If you hand-edit generated output (don't), or post-process it, use Object.keys() rather than dot access.

Don't import the generated file into PHP-side tests. It's a front-end artifact. If you need parity assertions, read the alias list from Relation::morphMap() directly.

Caching layers. config:cache freezes the output path and any formatter settings from config/morph-map.php; changing config without re-caching produces confusing "still writing to the old path" behaviour. In dev, php artisan config:clear first when debugging output location.

Extension points. Before reaching for a custom solution, check whether the config exposes output path, filename, and format (JS vs TS/.d.ts) — most teams' "we need it typed" requirement is a config flag. If you need a totally different shape (e.g. alias → {class, table}), the cleanest layer is a post-processing step in your own build script or a wrapper module rather than a fork; the package's contract is intentionally narrow.

Watch for ordering. morphMap() merges in registration order and later calls overwrite earlier aliases. If two providers register the same alias, the generated file reflects whichever booted last — hard to spot, so keep morph map registration in exactly one place.

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.
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
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