PHPackages                             atk14/string4 - 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. atk14/string4

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

atk14/string4
=============

String4 is a PHP class that provides methods for string manipulation.

v0.6.1(1mo ago)034.5k↓38.6%14MITPHPPHP &gt;=5.3.0CI passing

Since Nov 30Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/atk14/String4)[ Packagist](https://packagist.org/packages/atk14/string4)[ Docs](https://github.com/atk14/Http)[ RSS](/packages/atk14-string4/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (1)Dependencies (4)Versions (19)Used By (14)

String4
=======

[](#string4)

[![Tests](https://github.com/atk14/String4/actions/workflows/tests.yml/badge.svg)](https://github.com/atk14/String4/actions/workflows/tests.yml)

String4 is a PHP class for comfortable, chainable string manipulation with full UTF-8 support. It wraps a plain PHP string in an object and exposes a rich set of methods — case conversion, slugification, truncation, HTML stripping, pluralization, and more — all designed to be chained fluently.

```
echo String4::ToObject("CookieConsentsController")
    ->gsub('/Controller$/', '')
    ->singularize()
    ->underscore(); // "cookie_consent"
```

- [Installation](#installation)
- [Instantiation](#instantiation)
- [Method reference](#method-reference)
    - [Basics](#basics)
    - [Case](#case)
    - [Search &amp; replace](#search--replace)
    - [Substrings &amp; slicing](#substrings--slicing)
    - [Splitting &amp; characters](#splitting--characters)
    - [Whitespace](#whitespace)
    - [HTML](#html)
    - [Conversion &amp; formatting](#conversion--formatting)
    - [Line operations](#line-operations)
    - [Random generation](#random-generation)
    - [Encoding](#encoding)
    - [Utilities](#utilities)
- [Testing](#testing)
- [Licence](#licence)

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

[](#installation)

```
composer require atk14/string4
```

Instantiation
-------------

[](#instantiation)

**Constructor**

```
$s = new String4("Hello World");
$s = new String4("Héllo", "UTF-8");    // explicit encoding
$s = new String4($anotherString4);     // copy from another instance
```

**`String4::ToObject($string, $encoding = null)`** — static factory; returns a copy if the argument is already a `String4` instance, otherwise wraps it.

```
$s = String4::ToObject("Hello");
$s = String4::ToObject($s);            // returns a copy, safe to pass around
$s = String4::ToObject("Héllo", "ISO-8859-2");
```

Method reference
----------------

[](#method-reference)

Most methods return a **new `String4` instance** and leave the original unchanged, so calls can be chained freely.

---

### Basics

[](#basics)

#### `length()` → `int`

[](#length--int)

Returns the number of characters (not bytes) in the string. Multibyte-safe.

```
(new String4("Héllo"))->length(); // 5
(new String4(""))->length();      // 0
```

---

#### `toString()` → `string`

[](#tostring--string)

Returns the underlying plain PHP string. Calling `echo` or interpolating `"$s"` works too thanks to `__toString()`.

```
$s = new String4("Hello");
$s->toString(); // "Hello"
echo $s;        // "Hello"
echo "$s";      // "Hello"
```

---

#### `copy()` → `String4`

[](#copy--string4)

Returns an independent copy of the object.

```
$a = new String4("Hello");
$b = $a->copy();
```

---

#### `getEncoding($normalize = false)` → `string`

[](#getencodingnormalize--false--string)

Returns the encoding the string was constructed with. Pass `true` to get a normalized lowercase form (e.g. `"utf8"` instead of `"UTF-8"`).

```
$s = new String4("Hello", "UTF-8");
$s->getEncoding();      // "UTF-8"
$s->getEncoding(true);  // "utf8"
```

---

### Case

[](#case)

#### `upcase()` / `upper()` → `String4`

[](#upcase--upper--string4)

Converts all characters to uppercase. Both names are equivalent aliases.

```
(new String4("hello"))->upcase();  // "HELLO"
(new String4("héllo"))->upper();   // "HÉLLO"
```

---

#### `downcase()` / `lower()` → `String4`

[](#downcase--lower--string4)

Converts all characters to lowercase.

```
(new String4("HÉLLO"))->lower();   // "héllo"
```

---

#### `isUpper()` → `bool`

[](#isupper--bool)

Returns `true` when all characters are uppercase. Returns `false` for an empty string.

```
(new String4("HELLO"))->isUpper();  // true
(new String4("Hello"))->isUpper();  // false
(new String4(""))->isUpper();       // false
```

---

#### `isLower()` → `bool`

[](#islower--bool)

Returns `true` when all characters are lowercase. Returns `false` for an empty string.

```
(new String4("hello"))->isLower();  // true
(new String4("Hello"))->isLower();  // false
```

---

#### `capitalize()` → `String4`

[](#capitalize--string4)

Uppercases the first character, leaves the rest unchanged.

```
(new String4("hello world"))->capitalize();  // "Hello world"
```

---

#### `uncapitalize()` → `String4`

[](#uncapitalize--string4)

Lowercases the first character, leaves the rest unchanged.

```
(new String4("Hello World"))->uncapitalize();  // "hello World"
```

---

#### `camelize($options = [])` → `String4`

[](#camelizeoptions----string4)

Converts an underscored string to CamelCase. By default the first letter is uppercased; pass `["lower" => true]` for lowerCamelCase.

```
(new String4("hello_world"))->camelize();                   // "HelloWorld"
(new String4("hello_world"))->camelize(["lower" => true]);  // "helloWorld"
(new String4("some_xml_parser"))->camelize();               // "SomeXmlParser"
```

---

#### `underscore()` → `String4`

[](#underscore--string4)

Converts a CamelCase string to `snake_case`.

```
(new String4("HelloWorld"))->underscore();    // "hello_world"
(new String4("BlogPost"))->underscore();      // "blog_post"
```

---

#### `titleize($options = [])` → `String4`

[](#titleizeoptions----string4)

Capitalizes every word and replaces underscores and hyphens with spaces. Strips a trailing `_id` suffix by default; pass `["keep_id_suffix" => true]` to keep it.

```
(new String4("x-men: the last stand"))->titleize();  // "X Men: The Last Stand"
(new String4("author_id"))->titleize();               // "Author"
(new String4("author_id"))->titleize(["keep_id_suffix" => true]); // "Author Id"
```

---

### Search &amp; replace

[](#search--replace)

#### `contains($needle)` → `bool`

[](#containsneedle--bool)

Returns `true` if the string contains the given substring. When an array is passed, all elements must be present.

```
$s = new String4("Hello World");
$s->contains("Hello");             // true
$s->contains("hello");             // false  (case-sensitive)
$s->contains(["Hello", "World"]);  // true   (all must match)
$s->contains(["Hello", "Nope"]);   // false
$s->contains([]);                  // false
```

---

#### `containsOneOf(...$needles)` → `bool`

[](#containsoneofneedles--bool)

Returns `true` if the string contains at least one of the given substrings. Accepts individual arguments or a single array.

```
$s = new String4("Hello World");
$s->containsOneOf("Hi", "Hello", "Hey");   // true
$s->containsOneOf(["Hi", "Ciao", "Hey"]);  // false
```

---

#### `match($pattern, &$matches = null)` → `int|false`

[](#matchpattern-matches--null--intfalse)

Wrapper around `preg_match()`. Match groups are returned in `$matches` as `String4` instances.

```
$s = new String4("2024-03-26");
$count = $s->match('/(\d{4})-(\d{2})-(\d{2})/', $matches);
// $count   = 1
// $matches[1] is String4("2024")
// $matches[2] is String4("03")
// $matches[3] is String4("26")
```

---

#### `replace($search, $replace = null)` → `String4`

[](#replacesearch-replace--null--string4)

Replaces occurrences of `$search` with `$replace`. When `$search` is an associative array, each key is replaced with its corresponding value.

```
$s = new String4("Hello World");

$s->replace("World", "PHP");
// "Hello PHP"

$s->replace([
    "Hello" => "Hi",
    "World" => "PHP",
]);
// "Hi PHP"
```

---

#### `gsub($pattern, $replaceOrCallable)` → `String4`

[](#gsubpattern-replaceorcallable--string4)

Replaces all matches of a regular expression with a string or the return value of a callback. Wrapper around `preg_replace()` / `preg_replace_callback()`.

```
$s = new String4("Hello World");

$s->gsub('/[aeiou]/', '*');
// "H*ll* W*rld"

$s->gsub('/\b\w/', function($m) {
    return strtoupper($m[0]);
});
// "Hello World"  (capitalize first letter of each word)
```

---

#### `prepend($content)` → `String4`

[](#prependcontent--string4)

Inserts a string at the beginning.

```
(new String4("World"))->prepend("Hello ");  // "Hello World"
```

---

#### `append($content)` → `String4`

[](#appendcontent--string4)

Appends a string to the end.

```
(new String4("Hello"))->append(" World");  // "Hello World"
```

---

### Substrings &amp; slicing

[](#substrings--slicing)

#### `substr($start, $length = null)` → `String4`

[](#substrstart-length--null--string4)

Returns a substring. Multibyte-safe. Negative `$start` counts from the end.

```
$s = new String4("Lorem Ipsum");
$s->substr(0, 5);  // "Lorem"
$s->substr(6);     // "Ipsum"
$s->substr(-5);    // "Ipsum"
```

---

#### `first($limit = 1)` → `String4`

[](#firstlimit--1--string4)

Returns the first `$limit` characters.

```
(new String4("Hello"))->first();    // "H"
(new String4("Hello"))->first(3);   // "Hel"
```

---

#### `at($position)` → `String4`

[](#atposition--string4)

Returns the character at the given zero-based position.

```
(new String4("Hello"))->at(0);   // "H"
(new String4("Hello"))->at(1);   // "e"
(new String4("Hello"))->at(-1);  // "o"
```

---

#### `truncate($length, $options = [])` → `String4`

[](#truncatelength-options----string4)

Shortens the string to `$length` characters. By default appends `"..."` to indicate truncation.

Options:

- **`omission`** — string appended when truncated (default: `"..."`)
- **`separator`** — if set, the string is truncated at the last occurrence of this character before the cutoff, avoiding mid-word cuts

```
$s = new String4("Hello World, how are you?");

$s->truncate(14);
// "Hello World..."

$s->truncate(14, ["omission" => " →"]);
// "Hello World →"

$s->truncate(14, ["omission" => "", "separator" => " "]);
// "Hello World,"
```

---

### Splitting &amp; characters

[](#splitting--characters)

#### `chars($options = [])` → `array`

[](#charsoptions----array)

Returns an array of individual characters as `String4` instances. Pass `["stringify" => true]` to get plain PHP strings instead.

```
(new String4("Hi!"))->chars();
// [String4("H"), String4("i"), String4("!")]

(new String4("Hi!"))->chars(["stringify" => true]);
// ["H", "i", "!"]
```

---

#### `split($separator, $options = [])` → `array`

[](#splitseparator-options----array)

Splits the string by a plain-string separator and returns an array of `String4` instances. Pass `["stringify" => true]` for plain strings.

```
$s = new String4("one two three");
$s->split(" ");
// [String4("one"), String4("two"), String4("three")]
```

---

#### `pregSplit($separator, $options = [])` → `array`

[](#pregsplitseparator-options----array)

Like `split()` but treats the separator as a regular expression. Shorthand for `split($separator, ["preg_split" => true])`.

```
$s = new String4("one  two   three");
$s->pregSplit('/\s+/');
// [String4("one"), String4("two"), String4("three")]
```

---

### Whitespace

[](#whitespace)

#### `trim($removeHiddenCharacters = false)` → `String4`

[](#trimremovehiddencharacters--false--string4)

Strips whitespace from both ends of the string. For UTF-8 strings this covers all Unicode space characters (NBSP, Em Space, Thin Space, Ideographic Space, etc.), not just ASCII whitespace.

Pass `true` to also strip invisible/control characters (zero-width spaces, BOM, directional marks, soft hyphens, etc.).

```
$s = new String4("  Hello World  ");
$s->trim();       // "Hello World"
$s->trim(true);   // also removes zero-width spaces, BOM, etc.
```

---

#### `squish()` → `String4`

[](#squish--string4)

Trims the string (including invisible characters) and collapses all internal whitespace sequences to a single space.

```
(new String4("  Hello   World  "))->squish();  // "Hello World"
```

---

### HTML

[](#html)

#### `stripTags()` → `String4`

[](#striptags--string4)

Removes all HTML tags (thin wrapper around PHP's `strip_tags()`).

```
(new String4("Hello World"))->stripTags();  // "Hello World"
```

---

#### `stripHtml()` → `String4`

[](#striphtml--string4)

A smarter HTML-to-text converter. Compared to `stripTags()` it:

- removes block-level tags (``, ``, ``, headings, etc.) and inserts spaces so words don't run together
- removes entire content of ``, ``, ``, ``, and similar non-visible tags
- decodes HTML entities (`&amp;` → `&`, `&nbsp;` → ` `, etc.)
- normalizes whitespace in the result

```
$html = "Welcome at our website!"
      . "We are here to help you.Write us.";

(new String4($html))->stripHtml();
// "Welcome at our website! We are here to help you. Write us."
```

---

### Conversion &amp; formatting

[](#conversion--formatting)

#### `toAscii()` → `String4`

[](#toascii--string4)

Transliterates the string to ASCII, replacing accented and special characters with their closest ASCII equivalents.

```
(new String4("Héllo Wörld"))->toAscii();
// "Hello World"

(new String4("příliš žluťoučký kůň"))->toAscii();
// "prilis zlutoucky kun"
```

---

#### `toSlug($options = [])` → `String4`

[](#toslugoptions----string4)

Converts the string to a URL-friendly slug: transliterates to ASCII, lowercases, replaces non-alphanumeric characters with hyphens, and strips leading/trailing hyphens.

An integer can be passed directly as `$options` to set `max_length`.

Options:

- **`max_length`** — maximum length of the resulting slug
- **`suffix`** — string appended to the slug (also slugified itself), useful for appending IDs

```
$s = new String4("Amazing facts about foxes!");

$s->toSlug();                                            // "amazing-facts-about-foxes"
$s->toSlug(10);                                          // "amazing-fa"
$s->toSlug(["max_length" => 10]);                        // "amazing-fa"
$s->toSlug(["suffix" => "123"]);                         // "amazing-facts-about-foxes-123"
$s->toSlug(["max_length" => 20, "suffix" => "123"]);     // "amazing-facts-abc-123"
```

---

#### `toBoolean()` → `bool`

[](#toboolean--bool)

Converts the string to a boolean. Returns `false` for an empty string and for the values `"false"`, `"off"`, `"no"`, `"n"`, `"f"` (all case-insensitive). Returns `true` for everything else.

```
String4::ToObject("yes")->toBoolean();    // true
String4::ToObject("TRUE")->toBoolean();   // true
String4::ToObject("1")->toBoolean();      // true
String4::ToObject("on")->toBoolean();     // true

String4::ToObject("no")->toBoolean();     // false
String4::ToObject("false")->toBoolean();  // false
String4::ToObject("off")->toBoolean();    // false
String4::ToObject("0")->toBoolean();      // false
String4::ToObject("")->toBoolean();       // false
```

---

#### `pluralize()` → `String4`

[](#pluralize--string4)

Returns the plural form of the last word in the string (English only).

```
(new String4("apple"))->pluralize();      // "apples"
(new String4("Sad man"))->pluralize();    // "Sad men"
```

---

#### `singularize()` → `String4`

[](#singularize--string4)

Returns the singular form of the last word in the string (English only).

```
(new String4("apples"))->singularize();        // "apple"
(new String4("Happy people"))->singularize();  // "Happy person"
```

---

#### `tableize()` → `String4`

[](#tableize--string4)

Converts a CamelCase class name to the corresponding database table name: underscores and pluralizes. Handy for ORM-style conventions.

```
(new String4("Book"))->tableize();           // "books"
(new String4("BlogPost"))->tableize();       // "blog_posts"
(new String4("CookieConsent"))->tableize();  // "cookie_consents"
```

---

### Line operations

[](#line-operations)

#### `removeEmptyLines($options = [])` → `String4`

[](#removeemptylinesoptions----string4)

Removes empty lines from the string. Handles all common line endings (`\n`, `\r\n`, `\r`).

Options:

- **`max_empty_lines`** — how many consecutive empty lines to allow (default: `0` — all removed)
- **`trim_empty_lines`** — whether to trim whitespace-only lines before deciding if they are empty (default: `true`)

```
$s = new String4("line one\n\n\nline two\n\nline three");

$s->removeEmptyLines();
// "line one\nline two\nline three"

$s->removeEmptyLines(["max_empty_lines" => 1]);
// "line one\n\nline two\n\nline three"
```

---

#### `eachLineMap($callback)` → `String4`

[](#eachlinemapcallback--string4)

Applies a callback to every line and returns a new string with the mapped lines. Line endings are preserved.

```
// Trim every line
$result = $s->eachLineMap(function($line) {
    return $line->trim();
});

// Add a quote prefix to every line
$result = $s->eachLineMap(function($line) {
    return $line->prepend("> ");
});
```

---

#### `eachLineFilter($callback = null)` → `String4`

[](#eachlinefiltercallback--null--string4)

Keeps only the lines for which the callback returns `true`. When no callback is provided, empty lines are filtered out.

```
// Remove empty lines
$result = $s->eachLineFilter();

// Keep only lines that start with "#"
$result = $s->eachLineFilter(function($line) {
    return $line->match('/^#/');
});
```

---

### Random generation

[](#random-generation)

#### `String4::RandomString($length = 32, $options = [])` → `String4`

[](#string4randomstringlength--32-options----string4)

Generates a random alphanumeric string (`[A-Za-z0-9]`). Uses `random_int()` for cryptographically secure output, suitable for tokens and API keys.

`$length` can also be passed as part of `$options`.

Options:

- **`length`** — length of the generated string (default: `32`)
- **`extra_chars`** — additional characters to draw from

```
echo String4::RandomString();     // 32-character random string
echo String4::RandomString(16);   // 16-character random string

echo String4::RandomString([
    "length"      => 20,
    "extra_chars" => "#!&@",
]);
// e.g. "@vIxpVo!qD4A#n5Rb2E&"
```

---

#### `String4::RandomPassword($length = 10)` → `String4`

[](#string4randompasswordlength--10--string4)

Generates a human-friendly random password. Visually ambiguous characters (`0`, `O`, `1`, `l`, `I`) are excluded to reduce transcription errors. The result mixes letters and digits in a pronounceable pattern.

Also works well as a voucher or coupon code generator.

```
echo String4::RandomPassword();      // e.g. "68ynedeSA6"
echo String4::RandomPassword(12);    // e.g. "68ynedeSA634"
echo String4::RandomPassword(10)->upper(); // e.g. "EVUH923244"
```

---

### Encoding

[](#encoding)

#### `fixEncoding($options = [])` → `String4`

[](#fixencodingoptions----string4)

Replaces invalid UTF-8 byte sequences with a replacement character. Only has effect on UTF-8 strings. Accepts a string argument directly as a shorthand for `["replacement" => ...]`.

The default replacement is `U+FFFD` (the standard Unicode replacement character `▒`).

```
$s->fixEncoding();
// invalid bytes replaced with "▒"

$s->fixEncoding("?");
// invalid bytes replaced with "?"

$s->fixEncoding(["replacement" => "_"]);
// invalid bytes replaced with "_"
```

---

### Utilities

[](#utilities)

#### `getId()` → `string`

[](#getid--string)

Returns the string value. Exists for compatibility with the ATK14 framework, which sometimes calls `getId()` on objects to obtain their scalar representation.

Method chaining
---------------

[](#method-chaining)

All transformation methods return a new `String4` instance, so calls can be chained in any order:

```
echo String4::ToObject("  Hello World!  ")
    ->trim()
    ->lower()
    ->replace("!", "")
    ->toSlug();
// "hello-world"

echo String4::ToObject("CookieConsentsController")
    ->gsub('/Controller$/', '')
    ->singularize()
    ->underscore();
// "cookie_consent"

echo String4::ToObject("  lots  of   whitespace  \n\n\n and   newlines  ")
    ->squish();
// "lots of whitespace and newlines"
```

Testing
-------

[](#testing)

String4 is tested automatically via GitHub Actions across PHP 5.6 to PHP 8.5.

Tests use the [atk14/tester](https://packagist.org/packages/atk14/tester) wrapper for [phpunit/phpunit](https://packagist.org/packages/phpunit/phpunit).

Install development dependencies:

```
composer update --dev
```

Run the test suite:

```
cd test
../vendor/bin/run_unit_tests
```

Licence
-------

[](#licence)

String4 is free software distributed [under the terms of the MIT license](http://www.opensource.org/licenses/mit-license).

###  Health Score

51

—

FairBetter than 95% of packages

Maintenance89

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community21

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 93% 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 ~204 days

Recently: every ~73 days

Total

16

Last Release

55d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/974278?v=4)[Jaromir Tomek](/maintainers/yarri)[@yarri](https://github.com/yarri)

---

Top Contributors

[![yarri](https://avatars.githubusercontent.com/u/974278?v=4)](https://github.com/yarri "yarri (80 commits)")[![mysutka](https://avatars.githubusercontent.com/u/974669?v=4)](https://github.com/mysutka "mysutka (6 commits)")

---

Tags

string

### Embed Badge

![Health badge](/badges/atk14-string4/health.svg)

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

###  Alternatives

[nette/utils

🛠 Nette Utils: lightweight utilities for string &amp; array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.

2.1k417.9M1.7k](/packages/nette-utils)[danielstjules/stringy

A string manipulation library with multibyte support

2.4k26.2M192](/packages/danielstjules-stringy)[spatie/string

String handling evolved

5604.6M24](/packages/spatie-string)[kwn/number-to-words

Multi language standalone PHP number to words converter. Fully tested, open for extensions and new languages.

4265.3M23](/packages/kwn-number-to-words)[coduo/php-to-string

Simple library that converts PHP value into strings

26913.1M13](/packages/coduo-php-to-string)[opis/string

Multibyte strings as objects

7424.5M8](/packages/opis-string)

PHPackages © 2026

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