PHPackages                             bermudaphp/stringy - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. bermudaphp/stringy

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

bermudaphp/stringy
==================

A comprehensive PHP string manipulation library with full Unicode support

v1.0.2(1y ago)01323MITPHPPHP ^8.0|^8.1CI failing

Since Mar 12Pushed 11mo agoCompare

[ Source](https://github.com/bermudaphp/stringy)[ Packagist](https://packagist.org/packages/bermudaphp/stringy)[ RSS](/packages/bermudaphp-stringy/feed)WikiDiscussions master Synced 5d ago

READMEChangelog (3)Dependencies (1)Versions (5)Used By (3)

bermudaphp\\stringy
===================

[](#bermudaphpstringy)

[![PHP Version Require](https://camo.githubusercontent.com/753314ba401f35f744e19dd23ff49b5a76b15f5faa86b230814bfddccdad88d7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e342d627269676874677265656e2e737667)](https://php.net/)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](https://github.com/bermudaphp/stringy/blob/master/LICENSE)[![GitHub Tests](https://camo.githubusercontent.com/6e49704ecb788870df25034f070fe1a9fa60470a2eab6c5b2047f603831d7d93/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6265726d7564617068702f737472696e67792f74657374732e796d6c3f6272616e63683d6d6173746572266c6162656c3d7465737473)](https://github.com/bermudaphp/stringy/actions/workflows/tests.yml)

*Read this documentation in [Russian](README.ru.md).*

Overview
--------

[](#overview)

bermudaphp/stringy is a comprehensive PHP string manipulation library with full Unicode support. It provides both immutable and mutable string classes with a consistent API, making string operations more reliable and convenient compared to native PHP functions.

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Basic Concepts](#basic-concepts)
- [Class Examples](#class-examples)
    - [Str (Immutable)](#str-immutable)
    - [StrMutable (Mutable)](#strmutable-mutable)
    - [StringIterator](#stringiterator)
    - [Stringy (Static Utility)](#stringy-static-utility)
    - [ClsHelper (Class Name Utility)](#clshelper-class-name-utility)
- [Working with Multibyte Strings](#working-with-multibyte-strings)
- [License](#license)
- [Contributing](#contributing)

Installation
------------

[](#installation)

```
composer require bermudaphp/stringy
```

Basic Concepts
--------------

[](#basic-concepts)

The library provides two main string classes:

- **Str**: Immutable string class. Operations return new string instances without modifying the original.
- **StrMutable**: Mutable string class. Operations modify the string in place and return the same instance.

Both implement the **StringInterface** contract, providing a consistent API for string manipulation.

Class Examples
--------------

[](#class-examples)

### Str (Immutable)

[](#str-immutable)

The immutable string class returns a new instance for every operation that would change the string.

#### Creating Immutable Strings

[](#creating-immutable-strings)

```
use Bermuda\Stdlib\Str;

// Create from string
$str = Str::from('Hello World');

// Create with specific encoding
$russianStr = Str::from('Привет мир', 'UTF-8');

// Create through constructor
$str = new Str('Hello World');

// alternative
$str = Stringy::of('Hello World');
```

Lazy Initialization with createLazy()
-------------------------------------

[](#lazy-initialization-with-createlazy)

The `createLazy()` static method allows you to create lazily initialized string objects that are only constructed when actually accessed. This can significantly improve performance by delaying expensive operations until they're truly needed.

```
// Create a lazy-initialized string object
$lazy = \Bermuda\Stdlib\Str::createLazy(static function (\Bermuda\Stdlib\Str $str) {
    $str->__construct('construct call');
});

// No initialization occurs until the object is accessed
echo $lazy->value; // Triggers initialization: "construct call"
```

### How It Works

[](#how-it-works)

Unlike traditional objects that are initialized immediately, lazy ghost objects:

Create a minimal placeholder object initially.
Only execute your initializer function when a property or method is accessed.
Initialize the object just-in-time with the values you specify.

### When to Use

[](#when-to-use)

Lazy initialization is particularly valuable when:

Resource-heavy initialization: Loading data from files, databases, or APIs.
Conditional usage: When objects may not be used in all code paths.
Performance optimization: Delaying expensive operations until absolutely necessary.
Memory management: Reducing memory usage by not initializing unused objects.

### Advanced Example

[](#advanced-example)

```
// Creating multiple lazy string objects for a report
$reportFields = [
    'title' => Str::createLazy(function($str) use ($reportId) {
        $data = $database->fetchReportTitle($reportId);
        $str->__construct($data);
    }),
    'summary' => Str::createLazy(function($str) use ($reportId) {
        $data = $database->fetchReportSummary($reportId);
        $str->__construct($data);
    }),
    'content' => Str::createLazy(function($str) use ($reportId) {
        // This potentially large content is only loaded if actually displayed
        $data = $database->fetchReportContent($reportId);
        $str->__construct($data);
    })
];

// Only the title and summary are initialized - content remains lazy
echo $reportFields['title']->toUpperCase();
echo $reportFields['summary']->truncate(100);

// If this condition is false, content is never loaded from the database
if ($showFullReport) {
    echo $reportFields['content'];
}
```

#### Basic Properties

[](#basic-properties)

```
$str = Str::from('Hello');

// Get the underlying string value
echo $str->value;                // "Hello"

// Get the current encoding
echo $str->encoding;             // "UTF-8" (default)

// Check if string contains multibyte characters
var_dump($str->isMultibyte);     // bool(false)

$russianStr = Str::from('Привет');
var_dump($russianStr->isMultibyte); // bool(true)
```

#### String Conversion and Basic Operations

[](#string-conversion-and-basic-operations)

```
$str = Str::from('Hello World');

// Convert to string
echo $str->toString();           // "Hello World"
echo $str;                       // "Hello World" (uses __toString())

// Create a copy
$copy = $str->copy();           // Creates new Str instance with same value
$copy === $str;                 // false

// Encode to different character set
$latin1 = $str->encode('ISO-8859-1');

// Get byte count (different from character count for multibyte strings)
echo $str->getBytes();          // 11

// Get string length in characters
echo $str->length();            // 11
echo count($str);               // 11 (using Countable interface)

// Check if string is empty
var_dump($str->isEmpty());      // bool(false)
var_dump(Str::from('')->isEmpty()); // bool(true)

// Check if string is blank (empty or only whitespace)
var_dump(Str::from(' ')->isBlank()); // bool(true)
```

#### Character Access

[](#character-access)

```
$str = Str::from('Hello World');

// Get character at position
echo $str->charAt(0);           // "H"
echo $str->charAt(6);           // "W"
echo $str->charAt(-1);          // "d" (negative indices count from end)

// Get character as a new string object
$firstChar = $str->at(0);       // Returns Str('H')
$lastChar = $str->at(-1);       // Returns Str('d')

// Get first and last characters
$first = $str->first();         // Returns Str('H')
$last = $str->last();           // Returns Str('d')

// Check if position exists
var_dump($str->has(5));         // bool(true)
var_dump($str->has(20));        // bool(false)

// Get index bounds
echo $str->firstIndex();        // 0
echo $str->lastIndex();         // 10

// Array access (for reading only in Str)
echo $str[0];                   // "H"
echo $str[-1];                  // "d"
```

#### Substring Operations

[](#substring-operations)

```
$str = Str::from('Hello World');

// Extract substring
echo $str->substring(0, 5);     // "Hello"
echo $str->substring(6);        // "World" (to the end)
echo $str->substring(-5);       // "World" (from 5th last character to end)

// Get start/end of string
echo $str->start(5);            // "Hello"
echo $str->end(5);              // "World"

// Remove from start/end
echo $str->removeStart(6);      // "World"
echo $str->removeEnd(6);        // "Hello"

// Get substring between delimiters
echo $str->between('H', 'o');   // "ell"

// Get substring before/after
echo $str->before('World');     // "Hello "
echo $str->after('Hello');      // " World"

// Include delimiter in before/after
echo $str->before('World', true);  // "Hello W"
echo $str->after('Hello', true);   // "Hello World"

// Split into two parts
list($first, $second) = $str->split(' ');
echo $first;                    // "Hello"
echo $second;                   // "World"

// Split by delimiter
$parts = $str->explode(' ');    // Returns array of Str objects
$parts = $str->explode(' ', PHP_INT_MAX, true); // Returns array of strings
```

#### String Comparison

[](#string-comparison)

```
$str = Str::from('Hello World');

// Compare with another string
var_dump($str->equals('Hello World'));  // bool(true)
var_dump($str->equals('hello world'));  // bool(false)
var_dump($str->equals('hello world', false)); // bool(true) - case insensitive

// Compare with any of multiple strings
var_dump($str->equalsAny(['Hello', 'World', 'Hello World'])); // bool(true)

// Check if starts with
var_dump($str->startsWith('Hello'));    // bool(true)
var_dump($str->startsWith(['Hi', 'Hello'])); // bool(true)
var_dump($str->startsWith('hello', false)); // bool(true) - case insensitive

// Check if ends with
var_dump($str->endsWith('World'));      // bool(true)
var_dump($str->endsWith(['Earth', 'World'])); // bool(true)

// Check if contains
var_dump($str->contains('lo Wo'));      // bool(true)
var_dump($str->contains(['lo', 'Wo'])); // bool(true)

// Check if contains all
var_dump($str->containsAll(['Hello', 'World'])); // bool(true)
```

#### Search Operations

[](#search-operations)

```
$str = Str::from('Hello World, Hello Earth');

// Find position of substring
echo $str->indexOf('Hello');       // 0
echo $str->indexOf('Hello', 1);    // 13 (starting from position 1)
echo $str->indexOf('hello', 0, false); // 0 (case insensitive)
var_dump($str->indexOf('Bye'));    // NULL (not found)

// Find last position of substring
echo $str->lastIndexOf('Hello');   // 13

// Count occurrences
echo $str->countSubstr('Hello');   // 2
echo $str->countSubstr('hello', false); // 2 (case insensitive)
```

#### Case Conversion

[](#case-conversion)

```
$str = Str::from('hello world');

// Convert to uppercase/lowercase
echo $str->toUpperCase();         // "HELLO WORLD"
echo $str->toLowerCase();         // "hello world"

// Capitalize first character
echo $str->capitalize();          // "Hello world"

// Uncapitalize first character
echo Str::from('Hello World')->uncapitalize(); // "hello World"

// Capitalize each word
echo $str->capitalizeWords();      // "Hello World"

// Swap case of each character
echo Str::from('Hello')->swapCase(); // "hELLO"

// Title case (smarter capitalization)
echo $str->titleize();            // "Hello World"
echo $str->titleize(['of', 'the']); // "Hello World" (with ignored words)
```

#### Format Conversion

[](#format-conversion)

```
$str = Str::from('hello_world-example');

// Convert to different formats
echo $str->toCamelCase();        // "helloWorldExample"
echo $str->toPascalCase();       // "HelloWorldExample"
echo $str->toSnakeCase();        // "hello_world_example"
echo $str->toKebabCase();        // "hello-world-example"

// Custom delimiter
echo $str->delimit('.');         // "hello.world.example"
```

#### Whitespace Handling

[](#whitespace-handling)

```
$str = Str::from('  Hello World  ');

// Trim whitespace
echo $str->trim();               // "Hello World"
echo $str->trimStart();          // "Hello World  "
echo $str->trimEnd();            // "  Hello World"

// Custom characters to trim
echo Str::from('__Hello__')->trim('_'); // "Hello"

// Remove all whitespace
echo $str->stripWhitespace();    // "HelloWorld"

// Collapse multiple whitespace to single space
echo Str::from('Hello  World')->collapseWhitespace(); // "Hello World"
```

#### String Modification

[](#string-modification)

```
$str = Str::from('Hello World');

// Insert at position
echo $str->insert(' Dear', 5);   // "Hello Dear World"

// Pad string
echo $str->pad('*', 15);         // "**Hello World**"
echo $str->padStart('-', 15);    // "----Hello World"
echo $str->padEnd('=', 15);      // "Hello World===="

// Wrap with character
echo $str->wrap('"');            // "\"Hello World\""

// Check if wrapped
var_dump(Str::from('"Hello"')->isWrapped('"')); // bool(true)

// Add to start/end
echo $str->prepend('Dear ');     // "Dear Hello World"
echo $str->append('!');          // "Hello World!"

// Add prefix/suffix if not exists
echo $str->ensurePrefix('Hello '); // "Hello World" (unchanged)
echo $str->ensureSuffix('!');    // "Hello World!"

// Remove prefix/suffix
echo Str::from('HelloWorld')->removeSuffix('World'); // "Hello"
echo Str::from('HelloWorld')->removePrefix('Hello'); // "World"
```

#### Search and Replace

[](#search-and-replace)

```
$str = Str::from('Hello World');

// Replace text
echo $str->replace('World', 'Earth'); // "Hello Earth"
echo $str->replace(['Hello', 'World'], ['Hi', 'Earth']); // "Hi Earth"
echo $str->replace('world', 'Earth', false); // "Hello Earth" (case insensitive)

// Replace first/last occurrence
echo Str::from('Hello Hello')->replaceFirst('Hello', 'Hi'); // "Hi Hello"
echo Str::from('Hello Hello')->replaceLast('Hello', 'Hi');  // "Hello Hi"

// Replace with pattern
echo $str->replaceBy('/[aeiou]/i', '*'); // "H*ll* W*rld"

// Replace with callback
$result = $str->replaceCallback('/[A-Z]/u', function($match) {
    return '_' . strtolower($match[0]);
}); // "_hello _world"
```

#### String Transformation

[](#string-transformation)

```
$str = Str::from('Hello World');

// Reverse
echo $str->reverse();           // "dlroW olleH"

// Shuffle characters
echo $str->shuffle();           // Random order, e.g. "ldWroHl eol"

// Repeat
echo Str::from('Hi ')->repeat(3); // "Hi Hi Hi "

// Truncate
echo Str::from('This is a long sentence')->truncate(10); // "This is..."
echo Str::from('This is a long sentence')->truncate(10, '---'); // "This is---"
echo Str::from('This is a long sentence')->truncate(10, '...', true); // "This..."

// Transform with callback
echo $str->transform(function($s) {
    return strtoupper($s) . '!';
}); // "HELLO WORLD!"

// Tabs and spaces
echo Str::from("Hello\tWorld")->tabsToSpaces(2); // "Hello  World"
echo Str::from("Hello  World")->spacesToTabs(2); // "Hello\tWorld"

// Format with sprintf
echo Str::from('Hello, %s!')->format('John'); // "Hello, John!"
```

#### Type Validation and Conversion

[](#type-validation-and-conversion)

```
$str = Str::from('123');

// Check types
var_dump($str->isNumeric());     // bool(true)
var_dump($str->isAlpha());       // bool(false)
var_dump($str->isAlphanumeric()); // bool(true)
var_dump($str->isHex());         // bool(true)
var_dump($str->isUpperCase());   // bool(false)
var_dump($str->isLowerCase());   // bool(false)
var_dump($str->hasUpperCase());  // bool(false)
var_dump($str->hasLowerCase());  // bool(false)
var_dump($str->hasDigits());     // bool(true)
var_dump($str->hasSymbols());    // bool(false)

// Convert to types
echo $str->toNumber();           // int(123)
var_dump(Str::from('true')->toBoolean()); // bool(true)
var_dump(Str::from('true')->isBoolean()); // bool(true)

// JSON operations
var_dump(Str::from('{"a":1}')->isJson()); // bool(true)
echo Str::from('Hello')->toJson(); // "\"Hello\""

// Other type checks
var_dump(Str::from('a:1:{s:1:"a";i:1;}')->isSerialized()); // bool(true)
var_dump(Str::from('SGVsbG8=')->isBase64()); // bool(true)
var_dump(Str::from('2023-05-17')->isDate()); // bool(true)

// Convert to date
$date = Str::from('2023-05-17')->toDate();
```

#### String Segmentation

[](#string-segmentation)

```
$str = Str::from("Hello\nWorld\nExample");

// Split into lines
$lines = $str->lines();          // Array of Str objects, one per line

// Split into words
$words = Str::from('Hello World Example')->words(); // ["Hello", "World", "Example"]

// Convert to array of characters
$chars = $str->toArray();        // ["H", "e", "l", "l", "o", ... ]
```

#### Regular Expressions

[](#regular-expressions)

```
$str = Str::from('Hello 123 World');

// Match pattern
$found = $str->match('/\d+/', $matches);
var_dump($found);               // bool(true)
echo $matches[0];               // "123"

// Match all occurrences
$found = $str->matchAll('/\w+/', $matches);
var_dump($matches[0]);          // Array with all words
```

#### Other Operations

[](#other-operations)

```
$str = Str::from('Hello World');

// Hash the string
echo $str->hash();              // SHA-256 hash
echo $str->hash('md5');         // MD5 hash

// ASCII conversion
echo Str::from('Café')->toAscii(); // "Cafe"

// Output
$str->print();                  // Outputs "Hello World"

// Iterate through characters
$str->each(function($char, $index) {
    echo "$index: $char\n";
    return true; // Continue iteration
});
```

#### Iterator Usage

[](#iterator-usage)

```
$str = Str::from('Hello');

// Get iterator
$iterator = $str->getIterator();

// Use in foreach
foreach ($iterator as $index => $char) {
    echo "$index: $char\n";
}
```

### StrMutable (Mutable)

[](#strmutable-mutable)

The mutable string class modifies the string in place and returns the same instance for method chaining.

#### Creating Mutable Strings

[](#creating-mutable-strings)

```
use Bermuda\Stdlib\StrMutable;

// Create from string
$str = StrMutable::create('Hello World');

// Create with specific encoding
$russianStr = StrMutable::create('Привет мир', 'UTF-8');

// Create through constructor
$str = new StrMutable('Hello World');

// alternative
$str = Stringy::mutable('Hello World');

// Set string value directly
$str = StrMutable::create('Hello');
$str->setString('New Value');
```

Most methods in StrMutable have the same API as Str, but modify the string in place:

```
$str = StrMutable::create('Hello World');

// Chain operations
$str->toUpperCase()
    ->trim()
    ->replace('WORLD', 'EARTH');

echo $str; // "HELLO EARTH"

// Substring modifies in place
$str->substring(0, 5);
echo $str; // "HELLO"
```

#### Array Access (Mutable)

[](#array-access-mutable)

```
$str = StrMutable::create('Hello');

// Read
echo $str[1];  // "e"

// Write
$str[0] = 'J';
echo $str;     // "Jello"

// Remove character
unset($str[4]);
echo $str;     // "Jell"
```

### StringIterator

[](#stringiterator)

The StringIterator class allows character-by-character iteration with various navigation methods.

#### Creating and Basic Usage

[](#creating-and-basic-usage)

```
use Bermuda\Stdlib\StringIterator;

// Create directly
$iterator = new StringIterator('Hello');

// Create through string object
$str = Str::from('World');
$iterator = $str->getIterator();

// Basic iteration
while ($iterator->valid()) {
    echo $iterator->current();
    $iterator->next();
}
// Outputs: "World"

// Get the string
echo $iterator->__toString(); // "World"

// Create new iterator with different string
$newIterator = $iterator->withString('Hello');
```

#### Navigation

[](#navigation)

```
$iterator = new StringIterator('Hello World');

// Get current state
echo $iterator->current();   // "H" (initial position is 0)
echo $iterator->key();       // 0 (current position)

// Move forward/backward
$iterator->next();
echo $iterator->current();   // "e"

$iterator->forward(2);       // Move 2 steps forward
echo $iterator->current();   // "l"

$iterator->backward();       // Move 1 step back
echo $iterator->current();   // "e"

// Jump to position
$iterator->moveTo(6);
echo $iterator->current();   // "W"

// Reset position
$iterator->rewind();
echo $iterator->key();       // 0

// Check position
var_dump($iterator->isStart()); // bool(true)
var_dump($iterator->isEnd());   // bool(false)

$iterator->moveTo($iterator->lastIndex());
var_dump($iterator->isEnd());   // bool(false)

$iterator->next();
var_dump($iterator->isEnd());   // bool(true)
var_dump($iterator->valid());   // bool(false)
```

#### Reading

[](#reading)

```
$iterator = new StringIterator('Hello World');

// Read next characters
$iterator->moveTo(6);
echo $iterator->readNext(5);    // "World"

// Read to the end (when length is null)
$iterator->moveTo(6);
echo $iterator->readNext();     // "World"
```

### Stringy (Static Utility)

[](#stringy-static-utility)

The Stringy class provides static utility methods for string manipulation.

```
use Bermuda\Stdlib\Stringy;

// Convert string format
echo Stringy::delimit('HelloWorld', '-');           // "hello-world"
echo Stringy::delimit('hello_world-example', '.'); // "hello.world.example"

// Trim whitespace
echo Stringy::trim('  Hello  ');                    // "Hello"
echo Stringy::trimStart('  Hello  ');               // "Hello  "
echo Stringy::trimEnd('  Hello  ');                 // "  Hello"

// With custom characters
echo Stringy::trim('__Hello__', '_');               // "Hello"

// Multibyte support
echo Stringy::trim('  Привет  ');                   // "Привет"
```

### ClsHelper (Class Name Utility)

[](#clshelper-class-name-utility)

The ClsHelper class provides utilities for working with class names and namespaces.

```
use Bermuda\Stdlib\ClsHelper;

$className = 'Bermuda\\Stringy\\StrMutable';

// Get namespace part
echo ClsHelper::namespace($className);    // "Bermuda\\Stringy"

// Get basename (class without namespace)
echo ClsHelper::basename($className);     // "StrMutable"

// Split into namespace and class name
$parts = ClsHelper::split($className);
// Returns: [0 => 'Bermuda\\Stringy', 1 => 'StrMutable']

// Validate class names
var_dump(ClsHelper::isValidName('MyClass'));          // bool(true)
var_dump(ClsHelper::isValidName('Vendor\\MyClass'));  // bool(true)
var_dump(ClsHelper::isValidName('Vendor\\MyClass', false)); // bool(false) - no namespace allowed
var_dump(ClsHelper::isValidName('0InvalidClass'));    // bool(false)
```

Working with Multibyte Strings
------------------------------

[](#working-with-multibyte-strings)

All methods in Bermuda\\Stringy properly handle multibyte strings, ensuring correct character handling for non-Latin alphabets and special characters:

### Basic Multibyte Operations

[](#basic-multibyte-operations)

```
// Create with specific encoding
$russian = Str::from('Привет, мир!', 'UTF-8');
$chinese = Str::from('你好，世界！', 'UTF-8');
$arabic = Str::from('مرحبا بالعالم!', 'UTF-8');

// Character count vs byte count
echo $russian->length();      // 12 (character count)
echo $russian->getBytes();    // More than 12 (byte count)

// Character access
echo $russian->charAt(0);     // "П"
echo $chinese->charAt(0);     // "你"

// Substring extraction
echo $russian->substring(0, 6);  // "Привет"
echo $chinese->substring(0, 2);  // "你好"

// Case conversion (where applicable)
echo $russian->toUpperCase();    // "ПРИВЕТ, МИР!"
echo $russian->toLowerCase();    // "привет, мир!"
```

### Text Transformation

[](#text-transformation)

```
// Reverse (correctly handles multibyte)
echo $russian->reverse();     // "!рим ,тевирП"

// Replace
echo $russian->replace('мир', 'свет');  // "Привет, свет!"

// Trim
echo Str::from('  Привет  ')->trim();  // "Привет"

// Character iterations
$iterator = $russian->getIterator();
foreach ($iterator as $char) {
    echo $char . ' ';  // "П р и в е т ,   м и р !"
}
```

### Array Access with Multibyte

[](#array-access-with-multibyte)

```
$mutable = StrMutable::create('Привет');
echo $mutable[0];      // "П"

$mutable[0] = 'К';
echo $mutable;         // "Кривет"

unset($mutable[5]);
echo $mutable;         // "Криве"
```

### Working with Different Scripts

[](#working-with-different-scripts)

```
// Japanese
$japanese = Str::from('こんにちは世界', 'UTF-8');
echo $japanese->length();        // 7 characters
echo $japanese->substring(0, 5); // "こんにちは"

// Thai (with combining diacritical marks)
$thai = Str::from('สวัสดีโลก', 'UTF-8');
echo $thai->length();            // Correctly counts Thai characters with marks

// Emoji
$emoji = Str::from('Hello 👋 World 🌍', 'UTF-8');
echo $emoji->length();           // Correctly counts emoji characters
echo $emoji->substring(6, 1);    // "👋"

// Mixed script text
$mixed = Str::from('Hello Привет 你好 مرحبا', 'UTF-8');
foreach ($mixed->words() as $word) {
    echo $word . "\n";  // Correctly splits words across scripts
}
```

License
-------

[](#license)

This library is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

Contributing
------------

[](#contributing)

Contributions are welcome! Please create a pull request on the GitHub repository.

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance48

Moderate activity, may be stable

Popularity10

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~249 days

Total

4

Last Release

411d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/20490712?v=4)[Andrey Shelamkoff](/maintainers/Shelamkoff)[@Shelamkoff](https://github.com/Shelamkoff)

---

Top Contributors

[![Shelamkoff](https://avatars.githubusercontent.com/u/20490712?v=4)](https://github.com/Shelamkoff "Shelamkoff (260 commits)")

---

Tags

immutablemultibytestringstring-manipulationstringsunicodeutf-8

### Embed Badge

![Health badge](/badges/bermudaphp-stringy/health.svg)

```
[![Health](https://phpackages.com/badges/bermudaphp-stringy/health.svg)](https://phpackages.com/packages/bermudaphp-stringy)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
