Not every piece of reusable logic belongs in a model, a controller, or a full service class registered in the container — sometimes a plain PHP class with static (or instance) methods is genuinely the simplest fit, especially for small, stateless utility logic specific to your application.
1. Create the class
// app/Support/TextHelper.php
namespace App\Support;
class TextHelper
{
public static function excerpt(string $text, int $length = 150): string
{
return Str::limit(strip_tags($text), $length);
}
}
2. Use it via its namespace
use App\Support\TextHelper;
$summary = TextHelper::excerpt($post->body);
3. Optional: a shorter alias
If typing the full namespace repeatedly is annoying, register a class alias in bootstrap/app.php (or the legacy config/app.php aliases array on pre-Laravel-11 projects):
class_alias(\App\Support\TextHelper::class, 'TextHelper');
This lets you call TextHelper::excerpt() anywhere without the use import — convenient, but used sparingly, since aliasing every class you write makes it harder to trace where a class actually comes from.
Class vs. plain function helper — which to use
A static-method class (like this one) groups related utility methods under one namespace and is easy to autoload via Composer's PSR-4 rules automatically. A plain global function (registered via composer.json's autoload.files, covered in our helper functions guide) is simpler for a single one-off function but doesn't group related logic the way a class does. For more than one or two related utilities, a class is usually the more maintainable choice.
When to upgrade to a real service class instead
If the "helper" starts needing constructor dependencies (another service, a config value, a repository), it's outgrown a simple static-method class — that's the point to make it a proper injectable service registered in the container instead, rather than reaching for static properties to hold state that doesn't belong there.
Import the classes the helper itself depends on
The example's Str::limit() call needs its own import inside TextHelper.php:
namespace App\Support;
use Illuminate\Support\Str;
class TextHelper
{
public static function excerpt(string $text, int $length = 150): string
{
return Str::limit(strip_tags($text), $length);
}
}
A use statement in the controller that calls TextHelper does not carry into the helper class; imports are file-scoped in PHP.
Static is a good fit only while the operation is genuinely stateless
A formatter that receives all of its input as method arguments has no hidden dependencies, so a static call is straightforward. The warning sign is the first time the class reaches into global state — configuration, the authenticated user, the database, the filesystem, or an external API. At that point the apparent convenience of a static helper starts hiding dependencies from callers and tests.
You usually do not need a global alias
Modern PHP IDEs and editors handle imports cheaply, and use App\Support\TextHelper; makes origin and refactoring behavior explicit. A global alias can be useful in a legacy codebase with many existing calls, but it is not required for a helper class to be "Laravel-compatible"; normal Composer PSR-4 autoloading already makes any class under the application's namespace available.
Test helper behavior at its boundary
Small utilities are easiest to keep trustworthy with focused unit tests: HTML is stripped, short strings are not unnecessarily changed, multibyte text is handled by the underlying string helper, and the configured limit behaves as expected. That is more valuable than making the helper globally callable — the point of extracting it is to give repeated behavior one stable implementation.