framework icon indicating copy to clipboard operation
framework copied to clipboard

[13.x] Change `InteractsWithData::string()` to return native string

Open alies-dev opened this issue 3 months ago • 5 comments

⚠️ This is a breaking change for Laravel 13

This PR modifies the InteractsWithData::string() (and thus, a popular FormRequest::string()) method to return a native PHP string instead of a Stringable instance, making it consistent with Config\Repository::string() and avoiding unnecessary object instantiation when developers only need a string value.

Good news: InteractsWithData::str will return Stringable what is sort of inline with the \Illuminate\Support\Str class name.

Motivation

Currently, both string() and str() methods in InteractsWithData return Stringable instances, which creates:

  1. Inconsistency with Config\Repository::string() which returns native strings
  2. Performance overhead when developers just need a string and don't require Stringable methods
  3. Redundancy between string() and str() methods

With these changes, \Illuminate\Config\Repository::string and \Illuminate\Support\Traits\InteractsWithData::string have the same behaviour and similar code:

// Repository.php

     /**
     * Get the specified string configuration value.
     *
     * @param  string  $key
     * @param  (\Closure():(string|null))|string|null  $default
     * @return string
     */
    public function string(string $key, $default = null): string
    {
        $value = $this->get($key, $default);

        if (! is_string($value)) {
            throw new InvalidArgumentException(
                sprintf('Configuration value for key [%s] must be a string, %s given.', $key, gettype($value))
            );
        }

        return $value;
    }
// InteractsWithData.php

    /**
     * Retrieve data from the instance as a string.
     *
     * @param  string  $key
     * @param  mixed  $default
     * @return string
     */
    public function string($key, $default = null): string
    {
        $value = $this->data($key, $default);

        if (! is_scalar($value) && ! is_null($value)) {
            throw new InvalidArgumentException(
                sprintf('Value for key [%s] must be a string, %s given.', $key, gettype($value))
            );
        }

        return (string) $value;
    }

While this can be one of the most annoying upgrade steps, I think it:

  • will improve DX by providing more predictable results
  • the migration can be simplified by Rector and similar tools: I plan to create a Rector rule for https://github.com/driftingly/rector-laravel if this PR is approved

alies-dev avatar Sep 01 '25 21:09 alies-dev