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

Inflector Laravel Package

icanboogie/inflector

A fast, dependency-free PHP inflector for English words. Pluralize and singularize nouns, and convert between camelCase, snake_case, hyphenated, humanized and title-case forms. Works standalone or with ICanBoogie, with customizable rules and locale support.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a plain PHP package (ICanBoogie\Inflector) — there is no Laravel service provider, no config file, and no auto-discovery beyond Composer's PSR-4 autoloading. Treat it as a library you wrap yourself.

composer require icanboogie/inflector

Where to look first:

  1. ICanBoogie\Inflector — the static facade. It exposes pluralize, singularize, camelize, underscore, humanize, hyphenate, titleize, slugize, and format.
  2. Inflector::get($locale) — returns a per-locale instance. The multilingual support (the main reason to pick this over Laravel's Str) lives here, backed by locale data files shipped with the package.

First use case — poke it in Tinker:

use ICanBoogie\Inflector;

Inflector::pluralize('child');        // children
Inflector::singularize('people');     // person
Inflector::camelize('user_profile');  // userProfile
Inflector::underscore('UserProfile'); // user_profile
Inflector::humanize('line_items');    // Line items
Inflector::format('Hello {name}', ['name' => 'World']); // Hello World

Before writing any code, audit what you actually need. Laravel's Str::plural, Str::camel, Str::slug, and Str::headline already cover most English single-locale cases. Reach for this package when you need (a) non-English pluralization/singularization, or (b) the {placeholder}-style format() helper. If neither applies, you're adding a dependency for nothing.

Implementation Patterns

Wrap it in a container binding. Because there's no provider, register one yourself so the locale follows the app locale and the instance is reused:

// app/Providers/AppServiceProvider.php
$this->app->singleton('inflector', function ($app) {
    $locale = $app->getLocale();
    try {
        return \ICanBoogie\Inflector::get($locale);
    } catch (\Throwable $e) {
        return \ICanBoogie\Inflector::get('en'); // graceful fallback
    }
});

// helper
function inflector(): \ICanBoogie\Inflector {
    return app('inflector');
}

Multi-locale pattern. The inflector instance is immutable per locale, so don't share one across a locale switch mid-request. If you're generating localized UI strings in a loop, capture the instance once:

$inflector = \ICanBoogie\Inflector::get(app()->getLocale());

$labels = collect($columns)
    ->mapWithKeys(fn ($col) => [$col => $inflector->humanize($col)]);

Model / CRUD label generation. The most natural day-to-day use: turning table or column names into admin-panel labels without a translation key for every field.

$label = inflector()->humanize($model->getTable());   // "Line items"
$title = inflector()->titleize($model->getTable());

Naming conventions for generated code. Use camelize/underscore consistently when generating job, policy, or resource class names from a table name:

$base = inflector()->camelize(inflector()->singularize($table), true);
$jobClass = "Generate{$base}Report";

Templated strings from the database. format() shines for user-editable templates (email subjects, notification bodies) stored with {named} placeholders rather than positional sprintf args:

$subject = inflector()->format(
    $template->subject,               // "Your order {order_number} shipped"
    ['order_number' => $order->number]
);

Blade exposure. If templates need it, register a directive rather than calling a helper in 40 views:

Blade::directive('inflect', fn ($expr) => "<?php echo e(inflector()->humanize($expr)); ?>");

Testing pattern. Swap the binding in tests for a stub or a fixed-locale instance so assertions don't depend on app()->getLocale():

$this->app->instance('inflector', \ICanBoogie\Inflector::get('en'));

Gotchas and Tips

  • Overlap with Str. Pick one convention per codebase. Mixing Str::plural() and Inflector::pluralize() will eventually disagree on irregulars (person, datum, uncountables like news), producing route names or labels that don't match the tables Laravel migrations created.
  • Don't double-pluralize. If a table name came from $table->increments conventions or your own Str::plural, feeding it back into pluralize() can produce newses or people_s style artifacts. Decide singular-in, plural-out and stick to it.
  • Locale coverage is uneven. Only locales with shipped data files are real. Unsupported locales may silently fall back to English behavior, so add a test asserting the plural form for each locale you claim to support.
  • Facade caching vs. runtime locale. Inflector::get('fr') caches instances statically. If your middleware sets the locale after the binding resolves, you'll get the wrong language — resolve inside the request, not at boot, or pass the locale explicitly.
  • format() placeholder syntax collides. {name} is not :name (Laravel translations) and not {{ }} (Blade). Don't run format() output through Blade compilation, and don't mix placeholder styles in the same template store.
  • Acronym casing. camelize won't know that api should be API in ApiClient. For acronym-heavy class names, post-process or keep using Str::studly with your own mapping.
  • Performance. Static calls are cheap after the first locale load, but new Inflector() per iteration re-reads locale data. Bind once, resolve once per request.
  • Extension points are limited. Rules are data-driven per locale rather than a runtime addIrregular() API. If you need custom inflections, decorate the package: a small class AppInflector { public function __construct(private Inflector $inner) {} } with an override table is cleaner than subclassing internals.
  • License says NOASSERTION. The repo license metadata isn't machine-asserted (likely BSD/MIT-family). Confirm the LICENSE file manually before shipping in a commercial product.
  • Version pinning. It's actively released (latest tagged 2026-02-04), and it's independent of Laravel, so no framework constraint will protect you from a breaking API change — pin a minor range in composer.json.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource