承接 blendbyte/filament-title-with-slug 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

blendbyte/filament-title-with-slug

Composer 安装命令:

composer require blendbyte/filament-title-with-slug

包简介

Title + slug field for Filament v5 with auto-slug generation, live permalink preview, and inline editing.

README 文档

README

filament-title-with-slug-banner

Title With Slug — Permalink Field for Filament v5

Latest Version on Packagist Total Downloads Tests Static Analysis PHP Version Software License

Title + slug field for Filament v5 with auto-slug generation, live permalink preview, and inline editing.

use Blendbyte\FilamentTitleWithSlug\TitleWithSlugInput;

TitleWithSlugInput::make()

Requirements

Package (blendbyte) Filament Laravel Namespace
^3.x ^5.0 ^11 / ^12 / ^13* Blendbyte\FilamentTitleWithSlug
^2.x ⚠️ (deprecated) ^4.0 ^11 / ^12 Camya\Filament\Forms\Components
^1.x ⚠️ (deprecated) ^3.0 ^10 / ^11 / ^12 Camya\Filament\Forms\Components

*PHP 8.2 is not tested against Laravel 13.

v1.x and v2.x are not actively maintained. They receive security and severe bug fixes only — no new features. Please upgrade to v3.x. See the Upgrading section for migration steps.

Looking for Filament v2 support? The original package is at camya/filament-title-with-slug.

Features

  • Auto-generates a URL-safe slug from the title
  • Live permalink preview (https://example.com/blog/my-post)
  • Inline slug editing with OK / Cancel / Reset
  • "Visit" link to the published URL
  • Readonly mode for title and/or slug independently
  • Custom title field — pass any Filament field (e.g. a translatable input) as the title
  • Fully configurable: labels, placeholder, URL host & path, validation rules, slugifier
  • Translatable UI strings (7 languages included)
  • Dark mode supported
  • No Tailwind build step required

Table of Contents

Upgrading

All upgrades to v3.x share one breaking change: the namespace changed from Camya\Filament\Forms\Components (used in v1 and v2) to Blendbyte\FilamentTitleWithSlug.

Find every import of the component in your app and update it:

// Before (v1.x and v2.x)
use Camya\Filament\Forms\Components\TitleWithSlugInput;

// After (v3.x)
use Blendbyte\FilamentTitleWithSlug\TitleWithSlugInput;

The TitleWithSlugInput::make() call signature and all parameter names are unchanged.

From v2.x (Filament v4 → v5)

composer require blendbyte/filament-title-with-slug:^3.0
  1. Update the namespace as shown above.
  2. Remove any manual CSS import for this package from your Tailwind config or Vite pipeline — v3 registers its stylesheet automatically via Filament's asset system. No build step required.

New in v3: the titleField parameter for passing a custom field (e.g. translatable) as the title input.

From v1.x (Filament v3 → v5)

composer require blendbyte/filament-title-with-slug:^3.0
  1. Update the namespace as shown above.
  2. Remove any manual CSS imports (see above).
  3. See the Filament upgrade guide for app-level Filament changes.

From camya/filament-title-with-slug (Filament v2)

1. Swap the package:

composer remove camya/filament-title-with-slug
composer require blendbyte/filament-title-with-slug:^3.0

2. Update the namespace as shown above.

3. Re-publish config and translations if you had published them previously:

php artisan vendor:publish --tag="filament-title-with-slug-config" --force
php artisan vendor:publish --tag="filament-title-with-slug-translations" --force

4. Remove any manual CSS imports — v3 registers its stylesheet automatically.

5. See the Filament upgrade guide for app-level Filament changes.

Installation

composer require blendbyte/filament-title-with-slug

Optionally publish the config file:

php artisan vendor:publish --tag="filament-title-with-slug-config"

Translation

Publish the translation files:

php artisan vendor:publish --tag="filament-title-with-slug-translations"

Published translations land at lang/vendor/filament-title-with-slug.

Included languages: English, French, Brazilian Portuguese, German, Dutch, Indonesian, Arabic.

Added a translation? Share it on our GitHub Discussions page.

Usage & Examples

Basic usage

Add TitleWithSlugInput to any Filament form schema. It binds to title and slug by default:

use Blendbyte\FilamentTitleWithSlug\TitleWithSlugInput;

class PostResource extends Resource
{
    public static function form(Form $form): Form
    {
        return $form->schema([

            TitleWithSlugInput::make(),

        ]);
    }
}

Tip: Use ->columnSpan('full') to make the component span the full form width.

Custom title field

Pass any Filament field as the title input via titleField. This is useful when you need a translatable input or another custom field type from a third-party package:

TitleWithSlugInput::make(
    titleField: \Spatie\FilamentTranslatable\Forms\Components\TranslatableInput::make('title'),
)

The package automatically wires slug auto-generation onto the provided field. The field name is derived from getName(), so you don't need to pass fieldTitle separately unless you want to override it.

All title-specific parameters (titleLabel, titleRules, titlePlaceholder, etc.) are ignored when titleField is provided — configure those directly on your field before passing it in.

The titleAfterStateUpdated and titleFieldWrapper parameters still work regardless:

TitleWithSlugInput::make(
    titleField: MyTranslatableField::make('title')
        ->label('Post Title')
        ->required(),
    titleAfterStateUpdated: function (Set $set, string $state) {
        // runs after every title update
    },
)

Change model field names

Default field names are title and slug. Override them:

TitleWithSlugInput::make(
    fieldTitle: 'name',
    fieldSlug: 'identifier',
)

Change labels and placeholder

TitleWithSlugInput::make(
    urlPath: '/book/',
    urlVisitLinkLabel: 'Visit Book',
    titleLabel: 'Title',
    titlePlaceholder: 'Insert the title...',
    slugLabel: 'Link:',
)

Permalink preview: hide host

TitleWithSlugInput::make(
    urlHostVisible: false,
)

Permalink preview: change host and path

TitleWithSlugInput::make(
    urlPath: '/category/',
    urlHost: 'https://project.local',
)

Visit link via named route

Use a named route to generate the Visit link URL:

TitleWithSlugInput::make(
    urlPath: '/product/',
    urlHost: 'camya.com',
    urlVisitLinkRoute: fn(?Model $record) => $record?->slug
        ? route('product.show', ['slug' => $record->slug])
        : null,
)

Because the Visit URL is now route-generated, you can use a short urlHost just for the permalink preview display.

Hide the Visit link

TitleWithSlugInput::make(
    urlVisitLinkVisible: false,
)

Style the title input

Pass extra HTML attributes directly to the title <input> element:

TitleWithSlugInput::make(
    titleExtraInputAttributes: ['class' => 'italic'],
)

Readonly title or slug

Lock either field, optionally based on context:

TitleWithSlugInput::make(
    titleIsReadonly: fn($context) => $context === 'edit',
    slugIsReadonly: fn($context) => $context === 'edit',
)

When slugIsReadonly is true the slug row renders as a static permalink display (no edit link, no action buttons).

Validation rules

TitleWithSlugInput::make(
    titleRules: [
        'required',
        'string',
        'min:3',
        'max:120',
    ],
)

A unique rule is automatically applied to the slug. To customize it, see Custom unique validation.

Custom unique validation

Pass an array of named arguments that map to Filament's ->unique() method:

TitleWithSlugInput::make(
    slugRuleUniqueParameters: [
        'modifyRuleUsing' => fn(Unique $rule) => $rule->where('is_published', 1),
        'ignorable' => fn(?Model $record) => $record,
    ],
)

Available keys: ignorable, modifyRuleUsing, ignoreRecord, table, column.

Custom error messages

Override validation messages in your resource class:

protected $messages = [
    'data.slug.regex' => 'Invalid slug. Use only a–z, 0–9, and hyphens.',
];

Custom slugifier

Replace the default Str::slug() with your own closure:

TitleWithSlugInput::make(
    slugSlugifier: fn($string) => preg_replace('/[^a-z]/', '', $string),
    slugRuleRegex: '/^[a-z]*$/',
)

Dark mode

Empty homepage slug

Remove the slug's required rule, then use / as the slug value to represent the homepage. The / bypasses the auto-regeneration that would trigger on an empty value:

TitleWithSlugInput::make(
    slugRules: [],
)

Within a repeater

Repeater::make('FAQEntries')
    ->relationship()
    ->collapsible()
    ->schema([

        TitleWithSlugInput::make(
            fieldTitle: 'title',
            fieldSlug: 'slug',
            urlPath: '/faq/',
            urlHostVisible: false,
            titleLabel: 'Title',
            titlePlaceholder: 'Insert FAQ title...',
        ),

    ]),

URL slug sandwich

Place the slug in the middle of a path, e.g. /books/my-slug/detail/:

TitleWithSlugInput::make(
    urlPath: '/books/',
    urlVisitLinkRoute: fn(?Model $record) => $record?->slug
        ? '/books/' . $record->slug . '/detail'
        : null,
    slugLabelPostfix: '/detail/',
    urlVisitLinkLabel: 'Visit Book Details',
),

Slug as subdomain

TitleWithSlugInput::make(
    fieldSlug: 'subdomain',
    urlPath: '',
    urlHostVisible: false,
    urlVisitLinkLabel: 'Visit Domain',
    urlVisitLinkRoute: fn(?Model $record) => $record?->slug
        ? 'https://' . $record->slug . '.camya.com'
        : null,
    slugLabel: 'Domain:',
    slugLabelPostfix: '.camya.com',
),

Config file defaults

Publish the config to set global defaults:

php artisan vendor:publish --tag="filament-title-with-slug-config"

Published at config/filament-title-with-slug.php:

[
    'field_title' => 'title',          // Override per-field with fieldTitle:
    'field_slug'  => 'slug',           // Override per-field with fieldSlug:
    'url_host'    => env('APP_URL'),   // Override per-field with urlHost:
]

All available parameters

All parameters are optional and use named argument syntax. Parameters marked (ignored when titleField is set) only apply to the default TextInput.

TitleWithSlugInput::make(

    // Model fields
    fieldTitle: 'title',
    fieldSlug: 'slug',

    // Custom title field — replaces the default TextInput
    titleField: SomeField::make('title'),

    // URL
    urlPath: '/blog/',
    urlHost: 'https://www.example.com',
    urlHostVisible: true,
    urlVisitLinkLabel: 'View',
    urlVisitLinkRoute: fn(?Model $record) => $record?->slug
        ? route('post.show', ['slug' => $record->slug])
        : null,
    urlVisitLinkVisible: true,

    // Title — ignored when titleField is provided
    titleLabel: 'The Title',
    titlePlaceholder: 'Post Title',
    titleExtraInputAttributes: ['class' => 'italic'],
    titleRules: ['required', 'string'],
    titleRuleUniqueParameters: [
        'modifyRuleUsing' => fn(Unique $rule) => $rule->where('is_published', 1),
        'ignorable' => fn(?Model $record) => $record,
    ],
    titleIsReadonly: fn($context) => $context !== 'create',
    titleAutofocus: true,

    // Title callbacks — work with both default TextInput and custom titleField
    titleAfterStateUpdated: function ($state) {},
    titleFieldWrapper: fn($field) => $field,

    // Slug
    slugLabel: 'The Slug:',
    slugRules: ['required', 'string'],
    slugRuleUniqueParameters: [
        'modifyRuleUsing' => fn(Unique $rule) => $rule->where('is_published', 1),
        'ignorable' => fn(?Model $record) => $record,
    ],
    slugIsReadonly: fn($context) => $context !== 'create',
    slugSlugifier: fn($string) => Str::slug($string),
    slugRuleRegex: '/^[a-z0-9\-\_]*$/',
    slugAfterStateUpdated: function ($state) {},
    slugLabelPostfix: '/suffix',

)->columnSpan('full'),

Credits

Originally created by Andreas Scheibel (camya). Inspired by packages from awcodes and the work of spatie. Tests built with Pest.

Please see the release changelog for version history, and contributing for how to get involved. Security vulnerabilities can be reported via our security policy.

Maintained by Blendbyte


Blendbyte

Blendbyte builds cloud infrastructure, web apps, and developer tools.
We've been shipping software to production for 20+ years.

This package runs in our own stack, which is why we keep it maintained.
Issues and PRs get read. Good ones get merged.


blendbyte.com · hello@blendbyte.com

blendbyte/filament-title-with-slug 适用场景与选型建议

blendbyte/filament-title-with-slug 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 26.43k 次下载、GitHub Stars 达 17, 最近一次更新时间为 2023 年 09 月 18 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「framework」 「slug」 「laravel」 「permalink」 「livewire」 「filament」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 blendbyte/filament-title-with-slug 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 blendbyte/filament-title-with-slug 我们能提供哪些服务?
定制开发 / 二次开发

基于 blendbyte/filament-title-with-slug 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 26.43k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 17
  • 点击次数: 34
  • 依赖项目数: 4
  • 推荐数: 0

GitHub 信息

  • Stars: 17
  • Watchers: 1
  • Forks: 44
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2023-09-18