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

Trimmed Non Empty String Laravel Package

oskarstark/trimmed-non-empty-string

A tiny PHP value object that trims surrounding whitespace from strings and guarantees the result is non-empty, throwing an exception when validation fails. Use it to keep user input and domain values clean, predictable, and safe.

View on GitHub
Deep Wiki
Context7

Getting Started

oskarstark/trimmed-non-empty-string is a tiny, framework-agnostic value object that guarantees a string has been trimmed and is not empty. There is nothing to register, no config to publish, no service provider — it is a plain PHP class you composer require oskarstark/trimmed-non-empty-string and start type-hinting.

First steps

  1. composer require oskarstark/trimmed-non-empty-string (the 1.x line is stable; ^1.11 is a safe constraint — see the note on 1.11.2 below).
  2. Read src/ before the README — it is a handful of classes: the value object itself plus the exception thrown when the string is empty (or whitespace-only) after trimming. Confirm the exact factory method name (fromString() / from()) and the accessor (toString() / __toString() / value()) there; it takes two minutes and saves guessing.
  3. Skim tests/ for the edge-case matrix the maintainers care about (empty string, whitespace-only, leading/trailing whitespace, already-clean input). That is effectively the spec.

First use case: anything that arrives from a user or a config file and is then trusted to be non-blank — a form field, a webhook payload name, a .env-backed setting, a header value. Replace trim($request->input('name')) !== '' scattered across controllers with one constructor call and let the exception (or your own catch) handle the failure path.

On 1.11.2 specifically: this release is tooling-only — ergebnis/php-cs-fixer-config with PHP 8.2 rules, a Rector config, PHP_CS_FIXER_IGNORE_ENV cleanup, and assertNotSame test cosmetics. No runtime, API, or behaviour changes. Bump it without a second thought; it is a patch on an already-published API.

Implementation Patterns

Constructor-time validation in DTOs / form objects. Parse the request once, build typed objects, pass those around. The value object does the trimming and the emptiness check in the same place, so downstream code never needs to re-trim():

final class CreateProjectData
{
    public function __construct(
        public readonly TrimmedNonEmptyString $name,
    ) {}

    public static function fromRequest(ProjectRequest $request): self
    {
        return new self(
            TrimmedNonEmptyString::fromString((string) $request->input('name')),
        );
    }
}

Catch the package exception in the request/DTO factory and rethrow as ValidationException::withMessages([...]) so Laravel returns a 422 rather than a 500. This is the pattern you will write on day one and reuse everywhere.

Wrap it in a validation rule, not in every controller. A small TrimmedNonEmpty rule (Rule::class returning a closure that tries the factory and fails on exception) keeps validation in FormRequest::rules() where the rest of the team expects it, and keeps the value object for the parsing step afterwards. Do both: rule for the user-facing message, factory for the invariant.

Eloquent casts for "optional but not blank" columns. A custom cast (CastsAttributes) that maps null ↔ null and otherwise delegates to the factory gives you the trim on save and the guarantee on load. Beware: this silently rewrites stored values, so pair it with a backfill/migration check if the column already has untrimmed data.

Config objects over config() calls. Resolve config once in a service provider into typed constructor arguments. A TrimmedNonEmptyString-typed parameter means a stray trailing newline pasted into .env fails at boot with a clear exception instead of producing a 404 on a route prefix three weeks later. This is the highest-leverage use of the package in a Laravel app.

Collection boundaries. When mapping an array of inputs (tags, recipients, header lines), use the factory as the filter predicate and let the exception drop invalid entries, or try/catch per item to collect messages. Prefer explicit per-item reporting over array_filter silently swallowing the fact that someone submitted a whitespace-only row.

Equality and comparisons. Because values are normalised at construction, ===-style comparisons between two instances of the same class are finally meaningful. Compare the value objects in domain code, not the raw strings.

Gotchas and Tips

  • Trim is trim(). That means ASCII whitespace by default and nothing else — no zero-width spaces, no non-breaking spaces, no Unicode whitespace, no case-folding, no normalisation. If your input can contain \u{00A0} (pasted from a browser or Excel), it will survive and your "non-empty" object will look blank in the UI. Pre-sanitise, or wrap the factory in a helper that strips your own character set first.
  • Never apply this to passwords or secrets. Trimming a password silently changes it, and a whitespace-only password becoming "empty" turns an authentication attempt into an unexpected exception. Keep credentials as opaque strings.
  • Decide where the exception lives. The package exception is not a Laravel ValidationException. Letting it bubble from a controller yields a 500. Wrap it at the boundary (requests, jobs, console commands) — and don't do a broad catch (\Throwable) in a job that hides genuine bugs behind a retry loop.
  • Jobs and queues: a constructor-injected value object is serialised by Laravel. Confirm it survives serialize()/unserialize() (a single readonly string property will; anything holding a closure or resource won't). If in doubt, put the plain string on the job and build the value object in handle().
  • Immutability is the point. There are no setters and no in-place trim. Do not "modify" — construct a new instance. Code that expects $obj->value = 'x' will fail loudly, which is the desired behaviour but surprises people migrating from helper-function style.
  • Don't over-type. Using the value object for every string in the domain produces a wrapper tax (->toString() noise, mapping layers, factories in every fixture). Reserve it for boundaries and invariants — request input, config, external payloads — and let it fall back to string once inside a well-tested method.
  • Debugging surprises: when a DTO shows a trimmed value in the debugger, remember the original was discarded at construction. Log the raw input before constructing if you need it for audit; by the time the exception fires you only have the trim result, and "was it empty or whitespace?" is no longer distinguishable.
  • Extension points are deliberately thin. There is no interface, no service provider, no config file to publish. If you need custom trimming semantics (Unicode, a character blacklist, length limits), write a thin adapter class of your own that calls the package — do not fork it. That adapter is also the right place to swap in regex- or mb_-based normalisation later without touching call sites.
  • Upgrade cadence: the project ships frequent patch releases that are almost entirely CS-fixer/Rector/test housekeeping (1.11.2 is exactly that). Constrain to ^1.11 and let Renovate/Dependabot merge them; you only need to read the changelog when a 2.0 lands.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource