lastdragon-ru/lara-asp-formatter

The Awesome Set of Packages for Laravel - The Formatter.

7.0.0 2024-11-17 07:55 UTC

README

This package provides a customizable wrapper around Intl formatters to use it inside Laravel application. And also allows defining own.

Requirements

Installation

composer require lastdragon-ru/lara-asp-formatter

Configuration

Config can be used to customize formats. Before this, you need to publish it via the following command, and then you can edit config/lara-asp-formatter.php.

php artisan vendor:publish --provider=LastDragon_ru\\LaraASP\\Formatter\\PackageProvider --tag=config

Usage

Note

The resolved formats are cached, thus run-time changes in the configuration will not be applied. You can clone the formatter instance to reset the internal cache.

The Formatter is very simple to use. Please also check Formatter to see built-in formats 🤗

<?php declare(strict_types = 1);

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\LaraASP\Formatter\Formatter;

$default = app()->make(Formatter::class); // For default app locale
$locale  = $default->forLocale('ru_RU');  // For ru_RU locale

Example::dump($default->integer(123.454321));
Example::dump($default->decimal(123.454321));
Example::dump($locale->decimal(123.454321));

The $default->integer(123.454321) is:

"123"

The $default->decimal(123.454321) is:

"123.45"

The $locale->decimal(123.454321) is:

"123,45"

You can also define separate setting for each locale:

<?php declare(strict_types = 1);

use Illuminate\Support\Facades\Date;
use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\LaraASP\Formatter\Config\Config;
use LastDragon_ru\LaraASP\Formatter\Config\Format;
use LastDragon_ru\LaraASP\Formatter\Formats\IntlDateTime\IntlDateTimeFormat;
use LastDragon_ru\LaraASP\Formatter\Formats\IntlDateTime\IntlDateTimeOptions;
use LastDragon_ru\LaraASP\Formatter\Formatter;
use LastDragon_ru\LaraASP\Formatter\PackageConfig;

Example::config(PackageConfig::class, static function (Config $config): void {
    $config->formats[Formatter::Date] = new Format(
        IntlDateTimeFormat::class,
        new IntlDateTimeOptions(
            dateType: IntlDateFormatter::SHORT,
            timeType: IntlDateFormatter::NONE,
            pattern : 'd MMM yyyy',
        ),
        [
            'ru_RU' => new IntlDateTimeOptions(
                pattern: 'dd.MM.yyyy',
            ),
        ],
    );
});

$datetime = Date::make('2023-12-30T20:41:40.000018+04:00');
$default  = app()->make(Formatter::class);
$locale   = $default->forLocale('ru_RU');

Example::dump($default->date($datetime));
Example::dump($locale->date($datetime));

The $default->date($datetime) is:

"30 Dec 2023"

The $locale->date($datetime) is:

"30.12.2023"

Adding new formats

You just need to create a class that implements Format, add into the package config, and add macros to the Formatter class.

Note

The instance will be created through container with the following additional arguments:

  • $formatter: Formatter - the current formatter instance (can be used to get locale/timezone).
  • $options (array) - formatter options defined inside app config (may contain nulls).
<?php declare(strict_types = 1);

// phpcs:disable PSR1.Files.SideEffects
// phpcs:disable PSR1.Classes.ClassDeclaration

namespace LastDragon_ru\LaraASP\Formatter\Docs\Examples\Uppercase;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\LaraASP\Formatter\Config\Config;
use LastDragon_ru\LaraASP\Formatter\Config\Format;
use LastDragon_ru\LaraASP\Formatter\Contracts\Format as FormatContract;
use LastDragon_ru\LaraASP\Formatter\Formatter;
use LastDragon_ru\LaraASP\Formatter\PackageConfig;
use Override;
use Stringable;

use function mb_strtoupper;

/**
 * @implements FormatContract<null, Stringable|string|null>
 */
class UppercaseFormat implements FormatContract {
    public function __construct() {
        // empty
    }

    #[Override]
    public function __invoke(mixed $value): string {
        return mb_strtoupper((string) $value);
    }
}

Formatter::macro('uppercase', function (Stringable|string|null $value): string {
    return $this->format('uppercase', $value);
});

Example::config(PackageConfig::class, static function (Config $config): void {
    $config->formats['uppercase'] = new Format(
        UppercaseFormat::class,
    );
});

// @phpstan-ignore method.notFound
Example::dump(app()->make(Formatter::class)->uppercase('string'));

The app()->make(Formatter::class)->uppercase('string') is:

"STRING"

Notes about built-in formats

Currency

By default, the Formatter use locale currency. You can redefine it globally through config, specify for the call, and/or add a macros for another currency.

<?php declare(strict_types = 1);

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\LaraASP\Formatter\Config\Config;
use LastDragon_ru\LaraASP\Formatter\Config\Format;
use LastDragon_ru\LaraASP\Formatter\Formats\IntlNumber\IntlCurrencyFormat;
use LastDragon_ru\LaraASP\Formatter\Formats\IntlNumber\IntlCurrencyOptions;
use LastDragon_ru\LaraASP\Formatter\Formatter;
use LastDragon_ru\LaraASP\Formatter\PackageConfig;

Example::config(PackageConfig::class, static function (Config $config): void {
    $config->formats[Formatter::Currency] = new Format(
        IntlCurrencyFormat::class,
        new IntlCurrencyOptions(
            currency: 'USD',
        ),
    );
});

Formatter::macro('eur', function (float|int|null $value): string {
    return $this->format(Formatter::Currency, [$value, 'EUR']);
});

$formatter = app()->make(Formatter::class);
$value     = 123.45;

// @phpstan-ignore method.notFound
Example::dump($formatter->eur($value));             // macro
Example::dump($formatter->currency($value));        // locale default
Example::dump($formatter->currency($value, 'EUR')); // as defined

The $formatter->eur($value) is:

"€123.45"

The $formatter->currency($value) is:

"$123.45"

The $formatter->currency($value, 'EUR') is:

"€123.45"

Duration

To format duration you can use built-in Intl formatter, but it doesn't support fraction seconds and have a different format between locales (for example, 12345 seconds is 3:25:45 in en_US locale, and 12 345 in ru_RU). These reasons make it difficult to use it in real applications. To make duration() more useful, the alternative syntax was added and used by default.

The syntax is the same as ICU Date/Time format syntax.

<?php declare(strict_types = 1);

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\LaraASP\Formatter\Formatter;

$default = app()->make(Formatter::class); // For default app locale
$locale  = $default->forLocale('ru_RU');  // For ru_RU locale

Example::dump($default->duration(123.454321));
Example::dump($locale->duration(123.4543));
Example::dump($locale->duration(1_234_543));

The $default->duration(123.454321) is:

"00:02:03.454"

The $locale->duration(123.4543) is:

"00:02:03.454"

The $locale->duration(1234543) is:

"342:55:43.000"

To use Intl Formatter, you need to change the duration format in the config:

<?php declare(strict_types = 1);

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\LaraASP\Formatter\Config\Config;
use LastDragon_ru\LaraASP\Formatter\Config\Format;
use LastDragon_ru\LaraASP\Formatter\Formats\IntlNumber\IntlDurationFormat;
use LastDragon_ru\LaraASP\Formatter\Formatter;
use LastDragon_ru\LaraASP\Formatter\PackageConfig;

Example::config(PackageConfig::class, static function (Config $config): void {
    $config->formats[Formatter::Duration] = new Format(
        IntlDurationFormat::class,
    );
});

$default = app()->make(Formatter::class); // For default app locale
$locale  = $default->forLocale('ru_RU');  // For ru_RU locale
$value   = 123.4543;

Example::dump($default->duration($value));
Example::dump($locale->duration($value));

The $default->duration($value) is:

"2:03"

The $locale->duration($value) is:

"123"

Upgrading

Please follow Upgrade Guide.

Contributing

This package is the part of Awesome Set of Packages for Laravel. Please use the main repository to report issues, send pull requests, or ask questions.