novara/base

Why do it right if you can do it like this?

v1.5.2 2024-11-24 17:52 UTC

This package is auto-updated.

Last update: 2025-02-24 18:24:02 UTC


README

Novara

License: MIT

Variables? Disgusting!

Say "No!" to variables! Don't introduce state to your code.

9/10 Variables can be replaced with functional programming. I say let's ignore the remaining one and just do it!

— Someone Somewhere

This is an exercise in pain tolerance.

Installation

composer require novara/base

Usage

Superglobals

Superglobals (including $GLOBALS) can be accessed read-only.

// $GLOBALS
Novara::Globals::GLOBALS();

// $_GET
Novara::Globals::GET();

// ...

include() and require()

Enforce novarity¹ by replacing require and include with the library functions.

Novara::Import::require(__DIR__ . '/autoload.php');

ⓘ You can also autoload via the \Novara\Base\Autoloader\Loader class. See composer.json and autoload.php.

throwIf()

Throws an Exception if the condition evaluates to true. Returns false if no Exception was thrown.

Novara::Exception::throwIf(
    UserService::getUserName() !== 'admin',
    new Exception('This can\'t be right!'),
);

spread()

Reuse a value across multiple calls without creating a dedicated variable.

// This variable infested block:
$unnecessaryVariable = SomeService::getWhatever(); // Buffer to not call getWhatever() thrice
doAThing($unnecessaryVariable);
doAnotherThing($unnecessaryVariable);
if ($unnecessaryVariable > 100) {
    echo 'Wow!';
}

// becomes utter beauty:
Novara::Call::spread(
    SomeService::getWhatever(),
    doAThing(...),
    doAnotherThing(...),
    fn () => func_get_arg(0) > 100 && print 'Wow!',
);

spread() will return true if all calls return a truthy value, otherwise false.

pass()

Novara::Call::pass() re-scopes a value as parameter of a function call. Passing allows returning the value from the internal call.

Novara::Call::pass(
    MyService::calculateSomethingComplex('foo', 123, func_get_arg(0)),
    fn () => someFunction(func_get_arg(0)) ?: anotherFunction(func_get_arg(0)),
)

args()

The Novara::Call::args() function allows you to ensure novarity yet still have named arguments.

Novara::Call::args(
    [
        'name',
        'age',
    ],
    func_get_args(),
)->age === ...

This can be combined with passing or spreading.

// Reuse args through passing
return Novara::Call::pass(
    Novara::Call::args(
        [
            'name',
            'age',
        ],
        func_get_args(),
    ),
    fn () => 'Name: ' . func_get_arg(0)->name . '; Age: ' . func_get_arg(0)->age,
);

// Share the args through spreading
return Novara::Call::spread(
    Novara::Call::args(
        [
            'name',
            'age',
        ],
        func_get_args(),
    ),
    function () {
        ... func_get_arg(0)->name ...
    },
    function () {
        ... func_get_arg(0)->age ...
    },
);

replaceKey()

Copy-on-write with changed value by key of passed array.

Novara::Map::replaceKey(
    [
        'foo' => 13,
        'bar' => 14,
    ],
    'bar',
    37,
);

// results in
[
    'foo' => 13,
    'bar' => 37,
]

appendToKey()

Copy-on-write with appended value by key of passed array.

Array must be multidimensional.

Novara::Map::appendToKey(
    [
        'foo' => [1234],
        'bar' => [13],
    ],
    'bar',
    [37],
);

// results in
[
    'foo' => [1234],
    'bar' => [13, 37],
]

Why do this?

There a many good reasons to use Novara!

  • You want functional programming? We enforce it!
  • Stateless -> Exactly
  • XDEBUG is just too easy to use? Get rid of breakpoints!
  • Your keyboard conveniently broke in a specific way, not letting you use the Dollar ($) symbol

Jokes aside

I made this to prove I point. I have yet to find that point...

¹ "novarity" describes the complete absence of variables inside a PHP-Script.