nixn / php-util
PHP language utilities, mostly to code more in functional style.
Requires
- php: >=8.2
This package is auto-updated.
Last update: 2025-03-29 01:09:37 UTC
README
A PHP library with utility functions, mostly useful when coding in functional style, but also some other stuff.
Installation
Via composer:
composer require nixn/php-util
Components
Namespace: nixn\php
. All functions (except in Pipe) are static, so they can be called easily
(e.g. Arr::pick($array, 'a', 'b'))
).
Arr (ay)
pick(array $array, string|int ...$keys): array
Returns a new array with only the key => value mappings left, whose keys are in $keys.
$array = ['a' => 'A', 'b' => 'B', 1 => 'one', 2 => 'two']; Arr::pick($array, 'a', 2) // => ['a' => 'A', 2 => 'two']
find_by(array $array, callable $predicate, bool $return_key = false): mixed
Searches for a value in the array, based on the predicate, returning it (or its key) or null, when not found.
$array = ['a' => 'A', 'b' => 'B', 1 => 'one', 2 => 'two']; $predicate = fn($v, $k) => is_int($k) && $k % 2 == 0; Arr::find_by($array, $predicate) // => 'two' Arr::find_by($array, $predicate, true) // => 2
reduce(array $array, callable $callback, mixed $initial = null): mixed
Like array_reduce(), but the callback passes the key of the element, too.
$array = ['a' => 'A', 'b' => 'B', 1 => 'one', 2 => 'two']; $callback = fn($carry, $v, $k) => "$carry|$k"; Arr::reduce($array, $callback, "") // => "|a|b|1|2"
kvjoin(array $data, string $sep = ', ', string $kv_sep = '='): string
Like implode()/join() in legacy syntax, but outputs the keys too and takes an additional parameter$kv_sep
.
$array = ['a' => 'A', 'b' => 'B', 1 => 'one', 2 => 'two']; Arr::kvjoin($array) // => "a=A, b=B, 1=one, 2=two"
first(array $array): array
Returns the first mapping (element) of an array as key and value in an array, or null/null if the array is empty.
$array = ['a' => 'A', 'b' => 'B', 1 => 'one', 2 => 'two']; Arr::first($array) // => ['k' => 'a', 'v' => 'A'] Arr::first([]) // => ['k' => null, 'v' => null]
find(array $array, string|int ...$ks): array
Searches for a mapping in the array whose key is one of $keys, returns the key and the value or null/null (if not found) as an array.
$array = ['a' => 'A', 'b' => 'B', 1 => 'one', 2 => 'two']; Arr::find($array, 'b', 1) // => ['k' => 'b', 'v' => 'B'] Arr::find($array, 'c', 1) // => ['k' => 1, 'v' => 'one'] Arr::find($array, 'c', 3) // => ['k' => null, 'v' => null]
The return value for the last two functions are well suited for array destruction and safety on searching:
['k' => $key, 'v' => $value] = Arr::find($array, 2, 'b'); if ($key === null) echo "Not Found"; else echo "Found value $value with key $key"; // prints: Found value two with key 2
Partial
partial(callable $callable, mixed ...$args): callable
Returns a new function, which will call the callable with the provided args and can use placeholders for runtime args.
$comment_match = Partial::partial(preg_match(...), '/^\\s*(?:#|$)/'); $comment_match('# comment line') // => 1 $comment_match('normal line') // => 0 $keyword_match = Partial::partial(preg_match(...), '/php/i', Partial::PLACEHOLDER, null, 0, Partial::PLACEHOLDER); $keyword_match('Only PHP makes this possible!', 0) // => 1 $keyword_match('Only PHP makes this possible!', 10) // => 0
Str (ing)
trim_prefix(string $string, string $prefix): string
Trims a string prefix when it matches.
$str = "abcdef"; Str::trim_prefix($str, 'abc') // => "def" Str::trim_prefix($str, 'def') // => "abcdef"
trim_suffix(string $string, string $suffix): string
Trims a string suffix when it matches.
$str = "abcdef"; Str::trim_suffix($str, 'abc') // => "abcdef" Str::trim_suffix($str, 'def') // => "abc"
Util
identity(mixed $v): mixed
Just returns the input value. Useful in functional programming style.
Util::identity(42) // => 42
map(mixed $v, ?callable $fn = null, bool $null_on_not = false, bool $func = false, bool $null = true, bool $false = false, bool $empty = false, bool $zero = false): mixed
Checks$v
on (selectable) common falsy values and returns$fn($v)
or$v
(when$fn === null
) when not falsy. Returns$v
or null otherwise (depending on$null_on_not
).
$parenthesize = fn($x) => "($x)"; Util::map(0, $parenthesize) // => "(0)" Util::map(0, $parenthesize, zero: true) // => 0 Util::map(0, $parenthesize, null_on_not: true, zero: true) // => null Util::map(42, null, func: true) // => 42 Util::map(42, null, null_on_not: true, func: true) // => null
map_nots(mixed $v, ?callable $fn = null, bool $null_on_not = false, bool $func = false, mixed ... $nots): mixed
Likemap()
, but the falsy values are given as arguments ($nots
).
$parenthesize = fn($x) => "($x)"; Util::map_nots(42, $parenthesize, false, false, 42) // => 42 Util::map_nots(42, $parenthesize, true, false, 42) // => null Util::map_nots(null, $parenthesize, true, false, 42) // => "()"
when(mixed $test, mixed $v, ?callable $fn = null, bool $null = true, bool $false = true, bool $empty = false, bool $zero = false): mixed
Returns a value based on$test
,$v
and$fn
, testing based on selectable common falsy values. (See PHPdoc for more information.)
$parenthesize = fn($x) => "($x)"; Util::when(false, rand(...), $parenthesize) // => null (rand() not executed) Util::when(true, rand(...), $parenthesize) // => "(42)" Util::when(9, sqrt(...)) // => 3 (same as Util::map(9, sqrt(...)) or even just sqrt(9)) Util::when($get_from_database, fn() => $db->get(), fn($result) => $result->deep_value()) // the natural use case of this Util::when($use_title, fn() => ['title', $this->title], Hiccup::html(...)) // the natural use case for this Util::when(get_title(), fn($title) => ['title', $title], Hiccup::html(...), empty: true)
-
when_nots(mixed $test, mixed $v, ?callable $fn = null, mixed ... $nots): mixed
Likewhen()
, but the falsy values are given as arguments ($nots
). -
tree_path(mixed $element, callable $get_parent, ?callable $while = null): \Generator
For any node in a tree structure, get all parents (possibly up to a specific one) and return them from top to bottom.
$leaf = new Node('c', parent: new Node('b', parent: new Node('a'))); foreach (Util::tree_path($leaf, fn($node) => $node->parent) as $node) echo "$node->name,"; // prints: a,b,c, foreach (Util::tree_path($leaf, fn($node) => $node->parent, fn($node) => $node->name !== 'a') as $node) echo "$node->name,"; // prints: b,c,
new(string $class): \Closure
Returns a Closure for a constructor call.
$new_color = Util::new(Color::class); $color = $new_color(0, 127, 255); // $color instanceof Color
Pipe
A Pipe
object wraps an intial value and pipes it through any function which modifies it.
The resulting value can be accessed at the end.
Example:
<?php echo (new Pipe('NOW')) // wrap initial value (strtolower(...)) // map through strtolower() => 'now' ->new(DateTimeImmutable::class, Pipe::PLACEHOLDER, DateTimeZone::UTC) // create class ->format("Y_m_d") // call 'format' method magically => '2025_01_01' (that was 'now' not long ago...) (str_replace(...), '_', '-') // => '2025-01-01' (explode(...), '-', Pipe::PLACEHOLDER, 2) // => ['2025', '01-01'] ->get(0) // => '2025' (intval(...)) // => 2025 (fn($x) => $x + 1) // => 2026 ->value; // unwrap => 2026 // prints: 2026
With
A With
object wraps an object and can be used to call any method on it with chaining support (handled by the wrapper).
Note that any value returned by the method calls is discarded!
With::new(mysqli::class, 'localhost', 'db_user', 'db_password') ->set_charset('utf8mb4') ->select_db('log') ->autocommit(false) ->begin_transaction() ->execute_query('INSERT INTO ping') ->execute_query('INSERT INTO pong') ->commit() ->close();
Or just use it for initialization calls and unwrap it then:
$mysql = With::new(mysqli::class, 'localhost', 'db_user', 'db_password') ->set_charset('utf8mb4') ->select_db('log') ->autocommit(false) ->object; // unwrap
License
Copyright © 2025 nix https://keybase.io/nixn
Distributed under the MIT license, available in the file LICENSE.
Donations
If you like php-util, please consider dropping some bitcoins to 1nixn9rd4ns8h5mQX3NmUtxwffNZsbDTP
.