Utils
A broad, strict-typed standard library. Every helper is static:
Strings::toKebabCase($x).
Strings
Strings is the largest of them — every string operation the framework needs, always returning a
string rather than false, so results chain without checks.
Checking
use Framework\Utils\Strings;
Strings::isEqual("Ada", "ada"); // case-insensitive by default
Strings::startsWith("image.png", "img"); // and endsWith, contains
Strings::contains("hello", ["ell", "xyz"]); // any of several needles
Strings::match($value, "/^\d+$/"); // a regular expression
Strings::isAlphaNum($value);
Strings::hasEmoji($text); // and isOnlyEmojis
Strings::length($text);
The case checks pair with the converters below — isCamelCase, isSnakeCase,
isKebabCase, isPascalCase and isConstantCase.
Slicing & joining
Strings::substring($text, 0, 10);
Strings::substringBefore("a.b.c", "."); // "a"
Strings::substringAfter("a.b.c", "."); // "b.c"
Strings::substringBetween($text, "[", "]");
Strings::split("a, b, c", ","); // trims each part
Strings::join([ "a", "b" ], ", ");
Strings::joinKeys($map, ", "); // and joinValues
Strings::stripStart($path, "/"); // and stripEnd, stripStartEnd
Strings::addPrefix($file, "img_"); // and addSuffix, addPrefixSuffix
Case & formatting
Strings::toCamelCase("hello_world"); // "helloWorld"
Strings::toPascalCase("hello world"); // "HelloWorld"
Strings::toSnakeCase("helloWorld"); // "hello_world"
Strings::toKebabCase("Hello World"); // "hello-world"
Strings::toConstantCase("helloWorld"); // "HELLO_WORLD"
Strings::toTitleCase("john smith"); // "John Smith"
Strings::upperCaseFirst($text); // and lowerCaseFirst
Strings::padLeft($number, 3, "0"); // and padRight
Strings::makeShort($text, 80); // truncate with an ellipsis
Strings::splitToWords("helloWorld"); // [ "hello", "World" ]
Replacing, cleaning & generating
Strings::replace($text, "a", "b");
Strings::replaceStart($path, "/old", "/new"); // and replaceEnd
Strings::replacePattern($text, "/\d+/", "#");
Strings::replaceCallback($text, "/\{(\w+)\}/", $callback);
Strings::sanitize($input); // safe to store
Strings::removeHtml($html); // and toHtml, decodeHtml
Strings::normalized($text); // strip accents for comparing
Strings::random(12); // a random string
Strings::randomCode(6); // a short code
Strings::toString($value); // and toNumber, getNumber, getLetter
Arrays
Arrays works on both lists and maps, and always hands back an array of the type you asked for.
Finding & testing
use Framework\Utils\Arrays;
$rows = [ [ "id" => 1, "name" => "A" ], [ "id" => 2, "name" => "B" ] ];
Arrays::findValue($rows, "id", 2); // the whole row
Arrays::findValues($rows, "id", 2); // every matching row
Arrays::findIndex($rows, "id", 2); // its position
Arrays::getValues($rows, "name"); // [ "A", "B" ]
Arrays::getOneValue($rows, "name"); // the first name
Arrays::contains($list, $value); // and hasValue, containsKey
Arrays::isEmpty($array); // and isList, isMap, isDict
Arrays::isEqual($a, $b); // and isEqualWithKeys, isEqualJSON
Arrays::intersects($a, $b);
findIndex, findValue and findValues compare
Enums by their string value, so an enum case and its backing
string match interchangeably.Changing
Arrays::addFirst($list, $value); // and addAt
Arrays::removeFirst($list); // and removeLast, removeAt, removeValue
Arrays::removeEmpty($list); // drop empty entries
Arrays::removeDuplicates($list);
Arrays::merge($a, $b); // and mergeLists, extend
Arrays::slice($list, 0, 10); // and subArray, paginate
Arrays::sort($map, $callback); // sort() keeps keys, sortList() reindexes
Arrays::reverse($list);
Arrays::map($list, $callback);
Converting
The to… family casts a loose array into a typed one — the way request data becomes something a
model can use:
Arrays::toInts([ "1", "2", "x" ]); // [ 1, 2 ]
Arrays::toStrings($values);
Arrays::toList($value); // wrap a single value in a list
Arrays::toArray($value);
Arrays::toIntsMap([ "1" => "2" ]); // [ 1 => 2 ]
Arrays::toStringsMap($map); // and toStringIntMap, toIntStringMap
Arrays::toIntFloatMap($map); // and toStringFloatMap
Arrays::createMap($rows, "id"); // index rows by a column
Plus the small maths helpers: sum, average, max,
length, random and getDiff.
Numbers
Numbers parses, rounds and formats — including money, which it keeps in cents to avoid float
drift:
use Framework\Utils\Numbers;
Numbers::toInt("42.7"); // 43 (rounds)
Numbers::toFloat($value); // and toIntOrFloat
Numbers::isValid($value); // and isValidFloat, isValidPrice
Numbers::hasDecimals($value);
Numbers::round($value, 2); // and roundInt, roundCents
Numbers::clampInt($value, 0, 100); // and clampFloat
Numbers::divide($a, $b); // and divideInt — no division by zero
Money is stored as an integer number of cents, converted only at the edges:
Numbers::toCents(19.99); // 1999
Numbers::fromCents(1999); // 19.99
Numbers::formatCents(1999); // "19.99"
Numbers::formatPrice(1999); // "$19.99"
Numbers::applyDiscount($price, 20); // and applyIncrement
Numbers::formatInt(1234567); // "1,234,567"
Numbers::formatFloat(1234.5, 2); // "1,234.50"
Numbers::toBytesString(1048576); // "1 MB"
Numbers::percent(30, 200); // 15
Numbers::zerosPad(7, 3); // "007"
Numbers::coordinatesDistance($lat1, $lng1, $lat2, $lng2);
Dictionary
Dictionary wraps an array of loose values — decoded JSON, a config block, a database row — and
reads it as types, so nothing downstream deals with strings-that-might-be-numbers:
use Framework\Utils\Dictionary;
$dict = new Dictionary([ "name" => "Ada", "age" => "36", "active" => "1" ]);
$dict->getString("name"); // "Ada"
$dict->getInt("age"); // 36
$dict->getFloat("price");
$dict->getBool("active"); // true
$dict->getPrice("total"); // in cents
$dict->getDate("createdAt"); // a Date — and getDateParsed()
Nested values come back wrapped, so the same typed reads continue down the tree:
$dict->getDict("options"); // another Dictionary
$dict->getList("rows"); // a list of Dictionaries
$dict->getArray("tags"); // and getInts, getStrings, getJSON
$dict->findDict("id", 7); // search a list of Dictionaries
$dict->has("name"); // and hasValue, contains, containsInt
$dict->isEmpty(); // and isNotEmpty, isList, isEqual
$dict->set("name", "Ada"); // and setInt, setString, setEnum
$dict->push($value);
$dict->remove("name");
$dict->merge($other);
$dict->clone();
It implements Countable, IteratorAggregate and JsonSerializable, so it
counts, iterates and encodes like an array — and the to… converters
(toStringsMap(), toIntsMap(), toIntFloatMap(), toArray(),
toJSON()) hand back plain data when a boundary needs it.
Validation & parsing
Utils validates and parses the everyday user data — emails, phones, names and national IDs:
use Framework\Utils\Utils;
Utils::isValidEmail("a@b.com"); // true
Utils::isValidPassword($password); // strength check
Utils::isValidPhone($phone); // and isValidUsername, isValidFullName
Utils::isValidColor($value);
Utils::parseName("john smith"); // "John Smith" — and parseNameCase
Utils::generateUsername($name);
Utils::extractEmail($text); // and getEmailDomain
Utils::hideEmail("ada@example.com"); // "a**@example.com" — and hidePhone
Utils::getWhatsAppUrl($phone); // a wa.me link
Utils::getAvatarUrl($email);
The Argentine document helpers live here too — isValidDNI / dniToNumber and
isValidCUIT / parseCUIT / cuitToNumber.
JSON
Safe encode and decode, reading and writing JSON files and urls, and decoding straight into a Dictionary:
use Framework\Utils\JSON;
$json = JSON::encode(["a" => 1]); // {"a":1}
$data = JSON::decodeAsArray($json); // ["a" => 1]
$dict = JSON::decodeAsDictionary($json); // a Dictionary
JSON::isValid($json); // true
$config = JSON::readFile("config.json"); // decoded array
JSON::writeFile("out.json", $data);
$remote = JSON::readUrl("https://api.example.com/data");
URL
Parse and build urls — query params, hosts and slugs — with validation helpers:
use Framework\Utils\URL;
URL::toSlug("Hello, World!"); // "hello-world"
URL::addParams($url, ["page" => 2]); // append query params
URL::getHost("https://app.example.com/x"); // "app.example.com"
URL::getDomain("https://app.example.com/x"); // "example.com"
URL::isValid($url); // true
Server
The raw incoming request and server environment — the low level beneath the typed Request:
use Framework\Utils\Server;
Server::getIP(); // the client IP
Server::getFullUrl(); // the full request url
Server::getPlatform(); // "iOS", "Android", "Web"…
Server::getUserAgent();
Server::getPayload(); // the raw JSON body
Server::isPostRequest();
AES
Symmetric AES encryption with byte and hex helpers — this is what encrypts the database's protected values:
use Framework\Utils\AES;
$cipher = AES::encrypt($valueBytes, $keyBytes);
$bytes = AES::toHexBytes($hexString);
Encoding
Convert text between character encodings and clean up stray bytes:
use Framework\Utils\Encoding;
Encoding::toUTF8($text); // → UTF-8
Encoding::toISO8859($text); // → ISO-8859-1
Encoding::removeBOM($text); // strip a byte-order mark
CSV
Low-level CSV encode/decode and file read/write — the Import & Export module builds typed rows on top of these:
use Framework\Utils\CSV;
$rows = CSV::readFile("data.csv"); // array of rows
CSV::writeFile("out.csv", $rows);
$text = CSV::encode($rows);
Color
The brand color palette as an enum — the named hues the UI is themed with:
use Framework\Utils\Color;
Color::Blue;
Color::HotPink;
Color::getAll(); // every case (an IsEnum helper)
Cases run the spectrum from Red to Pink, plus White, Gray
and the empty None.