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

Gretel Laravel Package

glhd/gretel

Gretel is a Laravel package for managing redirects and avoiding broken links. Define redirects in code, automatically catch 404s, route old URLs to new ones, and track hits with a simple, flexible API for keeping your app’s links healthy.

View on GitHub
Deep Wiki
Context7

Getting Started

Gretel is a redirect manager: it catches 404s and turns them into 301/302s, backed by either a routes-file map or a database table. The 1.10.0 release only widens the framework constraint to Laravel 13 — no API changes — so the onboarding path below is identical for 1.9.x and 1.10.x.

composer require glhd/gretel
php artisan gretel:install   # publishes config/gretel.php + the redirects migration
php artisan migrate

Register the middleware so it can inspect responses. On Laravel 11+/13 (bootstrap/app.php):

->withMiddleware(function (Middleware $middleware) {
    $middleware->web(append: [
        \Glhd\Gretel\Http\Middleware\HandleRedirects::class,
    ]);
})

First use case — the one you'll reach for 90% of the time — is a static map of legacy URLs in routes/web.php:

Route::gretel([
    '/old-pricing' => '/pricing',
    '/blog/2020/hello' => '/blog/hello',
]);

Hit the old URL in a browser, confirm the 301, then check gretel_redirects in the DB to see the hit recorded. That's the whole loop.

Implementation Patterns

Static map vs. database rows. Route::gretel([...]) is best for a bounded, known set of legacy URLs that lives in version control and ships with deploys. Reach for DB-backed redirects (Gretel::redirect('/old', '/new'), or inserting rows) when editors or a CMS need to create them at runtime, or when you're importing thousands of rows from an old site.

Slug history on Eloquent models. The highest-leverage pattern: when a model's slug changes, register the old one so links don't rot.

// in an observer or model event
Gretel::slug($model->getOriginal('slug'), $model->slug);

This is what makes Gretel worth installing over hand-rolled Route::redirect() calls — content URLs stay stable while editorial slugs churn.

Bulk import from a legacy system. Seed straight from a CSV/JSON dump in a one-off artisan command or seeder, then php artisan gretel:refresh in the deploy script so the cached map is rebuilt. Don't loop Gretel::redirect() inside a request.

Chains and pruning. Point every old URL directly at the final destination — never old → interim → new. Then use the recorded hits / last_hit_at columns to find redirects that haven't fired in a year and retire them (soft-delete preserves the history).

Testing. Nothing special is required; the middleware runs in feature tests.

$this->get('/old-pricing')->assertRedirect('/pricing');
$this->get('/pricing')->assertOk();

Deploy integration. After any migration or content import that touches redirects, run gretel:refresh. Adding that to your deploy script is the single most useful habit with this package.

Gotchas and Tips

  • Redirects only fire on 404. The middleware inspects the finished response and only consults the redirect table when the app returned a 404. If a route still exists at the old path, that route wins and the redirect silently never fires — the usual cause of "my redirect isn't working." Remove/rename the stale route first.
  • Middleware placement matters. It must run on the request path you expect (typically the web group) and after session/start-session middleware. Putting it in a narrow group means only those routes get redirect handling.
  • Cache invalidation is manual. Rows inserted directly via SQL, a seeder, or a CMS bypass the package's cache. Local dev with a stale map is confusing: run gretel:refresh (or disable the cache in config/gretel.php) before debugging anything else.
  • Browsers cache 301s permanently. While building or testing a map, use 302s and test in a private window; otherwise Chrome will keep serving a redirect you deleted an hour ago. Flush the browser cache before concluding the package is broken.
  • Normalise before inserting. Trailing slashes, casing, and query strings are the three ways a map "fails" when it's really a mismatch. Decide whether query strings should be forwarded and be consistent about it; write paths exactly as they arrive.
  • Don't chain. A → B → C costs users two round trips and makes analytics useless. Flatten on import.
  • Extension points. The redirect model is configurable in config/gretel.php — subclass it if you need extra columns, scopes, or per-tenant redirects. Custom middleware wrapping HandleRedirects is the sane place to add logging or A/B logic.
  • Upgrading to 1.10.0 / Laravel 13. Nothing to change in your app code. The only real risk is doing the framework bump and the package bump in the same PR: Laravel 13 raises the minimum PHP version, so verify your runtime satisfies both constraints before merging, and run your redirect feature tests plus one manual browser check against 404s afterwards to confirm the middleware still fires under the new HTTP kernel.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource