anomaly/slug-field_type
Slug field type for the Anomaly Streams Platform. Adds an editable slug input that auto-generates URL-friendly, unique slugs from a source field, helping create clean, SEO-friendly URLs in Laravel-based Streams applications.
The package is a Streams Platform field type addon — it does not work standalone. You need an existing Streams/PyroCMS install before it means anything.
Install via Composer into a Streams-enabled project:
composer require anomaly/slug-field_type
The addon registers through its service provider and the composer.json extra.streams hints, so no manual providers array edit is normally required.
Recompile the addon manifest so the platform sees it:
php artisan addon:recompile
# or, if you use the compiled cache:
php artisan streams:compile
In the admin, go to Fields → Create and pick Slug from the field type dropdown (its slug is anomaly.field_type.slug). The config form will ask for the source field (the field to slugify, e.g. title) and a separator.
Assign the field to a stream (e.g. posts), then render it in a view:
<a href="{{ url('blog/' ~ entry.slug) }}">{{ entry.title }}</a>
The first real use case is a posts/pages stream where you want a title → slug pair for pretty URLs. That is essentially the whole point of the package.
Standard title/slug pair on a stream. Create a title text field and a slug field whose config points at title. In the admin form, typing in the title auto-fills the slug client-side. Pair this with a route that resolves by slug:
Route::get('blog/{slug}', function ($slug) {
return app(\Anomaly\PostsModule\Post\Contract\PostRepositoryInterface::class)
->findBySlug($slug);
});
Enforcing uniqueness on save. The field type itself will not guarantee unique slugs, so either add a unique index on the column or hook the stream's save:
$post->slug = str_slug($post->title) . '-' . Str::random(4);
A more durable pattern is a small custom field type extending the slug one and overriding preSave()/fill() to de-duplicate before persistence.
Custom field type extension. Because it is a normal FieldType, you can extend it:
class ProjectSlugFieldType extends \Anomaly\SlugFieldType\SlugFieldType
{
protected $slug = 'project_slug';
}
Register the new type in your own addon and you inherit the JS watcher and config UI.
Views and overrides. Publish the addon's views into your project to customise the input markup:
php artisan addon:publish anomaly/slug_field_type
Then edit resources/views/input.twig (or form.twig) in resources/{namespace}/slug-field_type/. Overriding the input view is the usual way to change the JS binding attribute if you use a nonstandard source field name.
API/import workflows. For seeded or API-created entries, set the slug explicitly in your payload — the client-side generator is not involved. A common pattern is to compute the slug in a form request or observer before passing data to the repository.
QueryException, or de-duplicate in a preSave hook.field_type options and uses keys like source and separator. A typo silently falls back to defaults rather than throwing, so verify with $field->getConfig('source') in a tinker session.php artisan cache:clear and php artisan streams:compile. A freshly installed field type that "doesn't show in the dropdown" is almost always a stale compile.{% if entry.slug %} in Twig; a missing slug renders as an empty string, producing broken links like /blog/ that are easy to miss in development.input view, getConfig() for defaults, and preSave()/fill() for programmatic slug generation — these cover almost every real customisation need without forking.composer.json and be prepared to vendor/patch it if the platform's field type API moves.How can I help you explore Laravel packages today?