> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Manipulación de cadenas (clase Str)

> Aprende a trabajar con cadenas de texto mediante la clase Str y Stringable (Fluent Strings) de Laravel, con ejemplos prácticos.

## Qué es la clase Str

La clase `Illuminate\Support\Str` proporciona un amplio conjunto de métodos para manipular cadenas. En lugar de invocar las funciones nativas de PHP una a una, ofrece una interfaz unificada y expresiva.

Laravel ofrece dos estilos:

* **Método estático**: `Str::slug($title, '-')`. Ideal para una operación puntual.
* **Estilo fluido (encadenamiento)**: `Str::of($title)->slug('-')->limit(50)`. Perfecto para encadenar varias operaciones.

```php theme={null}
use Illuminate\Support\Str;

// Método estático
$slug = Str::slug('My New Blog Post', '-');
// 'my-new-blog-post'

// Fluido (Str::of)
$result = Str::of('  My New Blog Post: Part 1  ')
    ->trim()
    ->slug('-')
    ->limit(30);
// 'my-new-blog-post-part-1'
```

<Info>
  El helper global `str()` equivale a `Str::of()`. Puedes escribir cosas como `str('hello')->upper()`.
</Info>

## Conversión de mayúsculas

Métodos para convertir la caja o el formato de una cadena. Útiles para nombres de columnas de BD o claves de respuestas de API.

### `Str::camel()` / `Str::snake()` / `Str::kebab()` / `Str::studly()`

```php theme={null}
use Illuminate\Support\Str;

// camelCase (empieza en minúscula)
Str::camel('foo_bar');        // 'fooBar'
Str::camel('user_profile_id'); // 'userProfileId'

// snake_case
Str::snake('fooBar');         // 'foo_bar'
Str::snake('UserProfile');    // 'user_profile'

// kebab-case
Str::kebab('fooBar');         // 'foo-bar'

// StudlyCase (PascalCase)
Str::studly('foo_bar');       // 'FooBar'
Str::studly('user-profile');  // 'UserProfile'
```

### `Str::lower()` / `Str::upper()` / `Str::title()`

```php theme={null}
use Illuminate\Support\Str;

Str::lower('LARAVEL');         // 'laravel'
Str::upper('laravel');         // 'LARAVEL'
Str::title('hello world');     // 'Hello World'
```

## Slugs y URLs

### `Str::slug()`: genera slugs amigables para URL

Imprescindible para generar URLs de artículos o páginas. Sustituye espacios y caracteres especiales por otros seguros para URL.

```php theme={null}
use Illuminate\Support\Str;

Str::slug('Laravel framework', '-');
// 'laravel-framework'

Str::slug('My New Blog Post', '-');
// 'my-new-blog-post'

Str::slug('Hello World!', '_');
// 'hello_world'
```

<Tip>
  Si el título contiene caracteres no ASCII (por ejemplo, en japonés), el slug puede quedar vacío. Considera combinarlo con una librería de transliteración o usar IDs y timestamps en la URL.
</Tip>

### Usar `Str::of()` para generar y sanear un slug de una tacada

```php theme={null}
use Illuminate\Support\Str;

$title = '  My New Blog Post: Part 1!  ';

$slug = Str::of($title)
    ->trim()
    ->slug('-')
    ->limit(50);
// 'my-new-blog-post-part-1'
```

## Truncar cadenas

### `Str::limit()`: truncar por número de caracteres

Genera texto de vista previa cuando muestras artículos o comentarios en un listado.

```php theme={null}
use Illuminate\Support\Str;

$text = 'Laravel es un framework PHP para construir aplicaciones web elegantes.';

// Trunca a 20 caracteres (por defecto añade "..." al final)
Str::limit($text, 20);
// 'Laravel es un framew...'

// Personaliza el sufijo
Str::limit($text, 20, ' → seguir leyendo');
// 'Laravel es un framew → seguir leyendo'

// No corta en mitad de una palabra
Str::limit('The quick brown fox jumps over the lazy dog', 20, preserveWords: true);
// 'The quick brown fox...'
```

### `Str::words()`: truncar por número de palabras

```php theme={null}
use Illuminate\Support\Str;

Str::words('Perfectly balanced, as all things should be.', 3, ' >>>');
// 'Perfectly balanced, as >>>'
```

## Búsqueda y comprobación

### `Str::contains()`: comprueba si contiene una subcadena

```php theme={null}
use Illuminate\Support\Str;

Str::contains('This is my name', 'my');
// true

// Con un array (any-of)
Str::contains('This is my name', ['my', 'your']);
// true

// Ignorar mayúsculas
Str::contains('This is my name', 'MY', ignoreCase: true);
// true
```

### `Str::startsWith()` / `Str::endsWith()`

```php theme={null}
use Illuminate\Support\Str;

Str::startsWith('https://laravel.com', 'https://');
// true

Str::startsWith('https://laravel.com', ['https://', 'http://']);
// true

Str::endsWith('photo.jpg', '.jpg');
// true

Str::endsWith('photo.jpg', ['.jpg', '.png', '.gif']);
// true
```

### `Str::is()`: patrones con comodines

```php theme={null}
use Illuminate\Support\Str;

Str::is('foo*', 'foobar');
// true

Str::is('*/user/*', '/admin/user/profile');
// true

// Ignorando mayúsculas
Str::is('F*', 'foo', ignoreCase: true);
// true
```

## Conversión y reemplazo

### `Str::replace()`: reemplazo simple

```php theme={null}
use Illuminate\Support\Str;

Str::replace('8.x', '13.x', 'Laravel 8.x');
// 'Laravel 13.x'

// Sin distinguir mayúsculas
Str::replace('laravel', 'Symphony', 'I love Laravel', caseSensitive: false);
// 'I love Symphony'
```

### `Str::replaceArray()`: reemplazo secuencial con array

```php theme={null}
use Illuminate\Support\Str;

$string = 'Horario: de ? a ?';

$result = Str::replaceArray('?', ['09:00', '17:00'], $string);
// 'Horario: de 09:00 a 17:00'
```

### `Str::replaceMatches()`: reemplazo con regex

```php theme={null}
use Illuminate\Support\Str;

// Quitar todo lo que no sea número de un teléfono
Str::replaceMatches('/[^0-9]/', '', '(03) 1234-5678');
// '0312345678'

// Reemplazo dinámico con closure
Str::replaceMatches('/\d+/', fn ($matches) => '[' . $matches[0] . ']', '1 y 2 y 3');
// '[1] y [2] y [3]'
```

### `Str::remove()`: elimina subcadenas

```php theme={null}
use Illuminate\Support\Str;

Str::remove('e', 'Peter Piper picked a peck of pickled peppers.');
// 'Ptr Pipr pickd a pck of pickld ppprs.'

// Varias subcadenas a la vez
Str::remove(['foo', 'bar'], 'foo and bar and baz');
// ' and  and baz'
```

### `Str::squish()`: elimina espacios redundantes

```php theme={null}
use Illuminate\Support\Str;

Str::squish('  Laravel   Framework  ');
// 'Laravel Framework'
```

## Operaciones alrededor de una subcadena

### `Str::before()` / `Str::after()`

```php theme={null}
use Illuminate\Support\Str;

// Todo lo que hay antes
Str::before('test@example.com', '@');
// 'test'

// Todo lo que hay después
Str::after('test@example.com', '@');
// 'example.com'

// A partir de la última aparición
Str::afterLast('App\Http\Controllers\UserController', '\\');
// 'UserController'

Str::beforeLast('App\Http\Controllers\UserController', '\\');
// 'App\Http\Controllers'
```

### `Str::between()`: extraer entre dos subcadenas

```php theme={null}
use Illuminate\Support\Str;

Str::between('[debug] Error occurred in module', '[', ']');
// 'debug'
```

### `Str::start()` / `Str::finish()`: forzar el inicio o el final

Si ya empieza (o termina) con ese carácter, no lo añade otra vez.

```php theme={null}
use Illuminate\Support\Str;

// Empezar con '/'
Str::start('users/profile', '/');
// '/users/profile'

Str::start('/users/profile', '/');
// '/users/profile' (no lo duplica)

// Terminar con '/'
Str::finish('https://example.com', '/');
// 'https://example.com/'
```

### `Str::chopStart()` / `Str::chopEnd()`: elimina prefijo o sufijo

```php theme={null}
use Illuminate\Support\Str;

Str::chopStart('https://laravel.com', 'https://');
// 'laravel.com'

// Varios patrones
Str::chopStart('http://laravel.com', ['https://', 'http://']);
// 'laravel.com'

Str::chopEnd('UserController.php', '.php');
// 'UserController'
```

## Enmascarado y seguridad

### `Str::mask()`: enmascara una cadena

Útil para ocultar parte de emails o números.

```php theme={null}
use Illuminate\Support\Str;

// A partir del carácter 4, enmascara con '*'
Str::mask('yamada@example.com', '*', 4);
// 'yama**************'

// Solo muestra los últimos 4 (offset negativo)
Str::mask('1234-5678-9012-3456', '*', -4);
// '***************3456'

// Enmascara un rango
Str::mask('yamada@example.com', '*', 3, 5);
// 'yam*****example.com'
```

### `Str::excerpt()`: extrae con contexto

Ideal para snippets de resultados de búsqueda.

```php theme={null}
use Illuminate\Support\Str;

$text = 'Laravel es un framework PHP para construir aplicaciones web elegantes.';

Str::excerpt($text, 'PHP', ['radius' => 10]);
// '...framework PHP para constr...'
```

## Cadenas aleatorias e identificadores

### `Str::random()`: genera una cadena aleatoria

Útil para tokens o claves de reset de contraseña.

```php theme={null}
use Illuminate\Support\Str;

Str::random(32);
// 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' (32 caracteres alfanuméricos)
```

### `Str::uuid()` / `Str::ulid()`: generar UUID/ULID

```php theme={null}
use Illuminate\Support\Str;

(string) Str::uuid();
// '550e8400-e29b-41d4-a716-446655440000'

// UUID ordenable en el tiempo (UUIDv7)
(string) Str::uuid7();

// ULID (identificador ordenable)
(string) Str::ulid();
// '01ARZ3NDEKTSV4RRFFQ69G5FAV'
```

### `Str::password()`: contraseña segura

```php theme={null}
use Illuminate\Support\Str;

Str::password(12);
// 12 caracteres aleatorios con mayúsculas, minúsculas, números y símbolos
```

### `Str::counted()`: forma singular/plural con la cifra

Devuelve el singular o el plural en función del número y lo acompaña con el valor formateado.

```php theme={null}
use Illuminate\Support\Str;

Str::counted('order', 1);
// '1 order'

Str::counted('order', 1000);
// '1,000 orders'
```

También con estilo fluido:

```php theme={null}
Str::of('order')->counted(3);
// '3 orders'
```

<Tip>
  Ideal para mostrar recuentos en inglés en la interfaz (por ejemplo, «1 item» vs «2 items»). La separación de miles se aplica automáticamente.
</Tip>

## Fluent Strings (encadenamiento)

Comenzando con `Str::of()` (o `str()`) obtienes una instancia de `Stringable` sobre la que encadenar métodos. Cuando quieras usarla como string, castea con `(string)` o úsala en un contexto de cadena.

```php theme={null}
use Illuminate\Support\Str;

$result = Str::of('  hello world  ')
    ->trim()
    ->title()
    ->append('!')
    ->toString();
// 'Hello World!'
```

### Ejemplos prácticos

**Generar el slug de un post**

```php theme={null}
use Illuminate\Support\Str;

$slug = Str::of('  My New Blog Post: Part 1  ')
    ->trim()
    ->lower()
    ->slug('-')
    ->limit(50);
// 'my-new-blog-post-part-1'
```

**Extraer el dominio de una URL**

```php theme={null}
use Illuminate\Support\Str;

$domain = Str::of('https://www.example.com/path/to/page')
    ->after('//')
    ->before('/')
    ->chopStart('www.');
// 'example.com'
```

**Sanear la entrada del usuario**

```php theme={null}
use Illuminate\Support\Str;

$clean = Str::of($userInput)
    ->squish()          // Colapsa espacios redundantes
    ->limit(255)        // Limita la longitud
    ->toString();
```

**Convertir un nombre de clase en ruta de archivo**

```php theme={null}
use Illuminate\Support\Str;

$path = Str::of('App\Http\Controllers\UserController')
    ->replace('\\', '/')
    ->append('.php')
    ->toString();
// 'App/Http/Controllers/UserController.php'
```

### Encadenamiento condicional (`when()`)

```php theme={null}
use Illuminate\Support\Str;

$result = Str::of('Laravel')
    ->when($isUppercase, fn ($str) => $str->upper())
    ->append(' Framework');
// Si $isUppercase es true: 'LARAVEL Framework'
// Si es false: 'Laravel Framework'
```

### `pipe()`: intercalar cualquier callback

```php theme={null}
use Illuminate\Support\Str;

$result = Str::of('my-slug')
    ->pipe(fn ($str) => $str->replace('-', '_'))
    ->upper()
    ->toString();
// 'MY_SLUG'
```

## Métodos habituales sobre `Str::of()`

Los métodos disponibles son prácticamente los mismos que los estáticos. Los más comunes:

```php theme={null}
use Illuminate\Support\Str;

$str = Str::of('Hello, World!');

$str->length();           // 13
$str->upper();            // 'HELLO, WORLD!'
$str->lower();            // 'hello, world!'
$str->trim();             // 'Hello, World!'
$str->slug();             // 'hello-world'
$str->camel();            // 'hello,World!' (no elimina símbolos)
$str->contains('World'); // true
$str->startsWith('Hello'); // true
$str->endsWith('!');      // true
$str->replace(',', '');   // 'Hello World!'
$str->prepend('>>> ');    // '>>> Hello, World!'
$str->append(' <<<');     // 'Hello, World! <<<'
$str->reverse();          // '!dlroW ,olleH'
$str->wordCount();        // 2
```

## Resumen

<AccordionGroup>
  <Accordion title="Métodos habituales de Str">
    | Método                                  | Uso                                 |
    | --------------------------------------- | ----------------------------------- |
    | `Str::slug($str)`                       | Slug amigable para URL              |
    | `Str::limit($str, $n)`                  | Trunca por número de caracteres     |
    | `Str::contains($str, $needle)`          | Comprueba si contiene una subcadena |
    | `Str::startsWith($str, $needle)`        | Comprueba si empieza por            |
    | `Str::endsWith($str, $needle)`          | Comprueba si termina en             |
    | `Str::replace($search, $replace, $str)` | Reemplaza                           |
    | `Str::camel($str)`                      | Convierte a camelCase               |
    | `Str::snake($str)`                      | Convierte a snake\_case             |
    | `Str::kebab($str)`                      | Convierte a kebab-case              |
    | `Str::studly($str)`                     | Convierte a StudlyCase              |
    | `Str::upper($str)`                      | A mayúsculas                        |
    | `Str::lower($str)`                      | A minúsculas                        |
    | `Str::squish($str)`                     | Elimina espacios redundantes        |
    | `Str::after($str, $search)`             | Obtiene lo que hay después          |
    | `Str::before($str, $search)`            | Obtiene lo que hay antes            |
    | `Str::between($str, $from, $to)`        | Obtiene lo que hay entre dos        |
    | `Str::mask($str, '*', $index)`          | Enmascara                           |
    | `Str::random($length)`                  | Cadena aleatoria                    |
    | `Str::uuid()`                           | Genera un UUID                      |
    | `Str::of($str)`                         | Punto de entrada al estilo fluido   |
  </Accordion>

  <Accordion title="Estático frente a Fluent (Str::of)">
    **Cuándo usar el método estático**:

    * Una o dos transformaciones.
    * Código sencillo y legible.

    ```php theme={null}
    $slug = Str::slug($title);
    ```

    **Cuándo usar Fluent (`Str::of`)**:

    * Tres o más transformaciones.
    * Con lógica condicional (`when()`).
    * Cuando quieres leer el proceso de arriba abajo.

    ```php theme={null}
    $slug = Str::of($title)
        ->trim()
        ->lower()
        ->slug()
        ->limit(50);
    ```
  </Accordion>

  <Accordion title="Str frente a funciones nativas de PHP">
    Usar la clase `Str` en lugar de `strtolower()`, `substr()`, `str_replace()`, etc. te aporta:

    * Soporte seguro de caracteres multibyte (usa internamente `mb_*`).
    * Encadenamiento para agrupar transformaciones.
    * Una interfaz coherente (no hace falta memorizar el orden de los argumentos).
    * Coherencia con el estilo de código de Laravel.
  </Accordion>
</AccordionGroup>


## Related topics

- [Clase Lottery](/es/advanced/lottery.md)
- [Trait Macroable](/es/advanced/macroable.md)
- [Mensajes de orden superior en colecciones](/es/advanced/higher-order-messages.md)
- [Pinning y seguridad en GitHub Actions](/es/advanced/github-actions-pinning.md)
- [Scopes de Eloquent](/es/advanced/eloquent-scopes.md)
