bfg/text
bfg/text is a lightweight Laravel/PHP text utility package offering convenient helpers for cleaning, formatting, and manipulating strings. It provides a simple API for common text operations, making it easy to handle content consistently across your application.
composer require bfg/text
Before writing any code, spend ten minutes reading the repo itself — this is a 1-star, 0-dependent package, so the source is the documentation.
composer.json — confirm the PHP and illuminate/* version constraints actually match your app. This is the single most common reason a low-traffic package fails to install on Laravel 11/12.src/ — look for a ServiceProvider, a Facade, and the main text-handling class(es). If there is no provider, everything is likely static helpers or plain instantiable classes.First use case: pick the one string operation you repeat most across your app — almost always slug generation, excerpt/truncate, or whitespace/case normalization — and replace a hand-rolled helper with the package's equivalent in a single place. Verify output against your existing behavior before rolling it out further.
If the package ships a provider, Laravel auto-discovery will register it; if not, either new the classes directly or wrap them (see below).
Wrap it, don't sprinkle it. With a single maintainer and near-zero adoption, treat the package as a leaf dependency behind your own thin service:
final class Text
{
public static function slug(string $value): string
{
return \Bfg\Text\...::slug($value); // adjust to actual API
}
}
Then call Text::slug() throughout the app. If the package is abandoned or you need to swap it, you change one file.
Use it in accessors and form requests, where text normalization naturally lives:
protected function title(): Attribute
{
return Attribute::make(
set: fn (string $v) => Text::normalize($v),
);
}
Chain operations where the API allows it. Packages in this category often return an instance for fluent chaining (->trim()->lower()->slug()). If so, favor chaining over nesting static calls — it reads better and is easier to debug step by step.
Bind to an interface if you inject it. If the classes are instantiable and you're using constructor injection in services, register a binding in your own provider so tests can substitute a fake:
$this->app->bind(TextProcessor::class, BfgTextProcessor::class);
Test the boundary, not the package. Write a small test suite asserting the specific outputs you depend on (e.g. assertSame('my-post-title', Text::slug('My Post Title!'))). This pins behavior if the package changes under a loose constraint and gives you a spec for a future replacement.
"bfg/text": "^1.0" or an exact tag) and commit composer.lock.Illuminate\Support\Str overlap. Most of what this package likely offers already exists in Str (slug, limit, headline, studly, etc.). Before adopting, diff the feature set — if it's 90% overlap, the dependency isn't paying for itself. Where it does add value (multi-byte handling, locale-aware casing, text stats), note that in a code comment so the next developer knows why it's there.mb_*, confirm mbstring is enabled in every environment, including CI and production.config/text.php and a publishes() call, run php artisan vendor:publish --tag=text-config and commit the file — otherwise defaults can shift between versions. If there's no config at all, don't invent one; configure via constructor args.tests/ directory, that's your best usage reference and reveals edge-case behavior the README omits.php artisan tinker call against the specific class. If output looks "almost right," suspect input encoding first, then regex flags (/u), then trimming of non-breaking spaces.vcs repository, and open an upstream PR.Str, symfony/string, or patchwork/utf8 later is a contained change. Keep a tracking issue noting the replacement candidate.How can I help you explore Laravel packages today?