cable8mm / n-format
Laravel package for Korean and Japanese number formatting with Eloquent casts, value objects, ordinal support, currency formatting, and smart price rounding
Requires
- php: ^8.2
- ext-intl: *
- illuminate/contracts: ^12.0|^13.0
- illuminate/database: ^12.0|^13.0
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^10.11.0|^11.2.0
- phpunit/phpunit: ^10.0|^11.0|^12.0
Suggests
- laravel/pint: Provides fixing all codes for coding style
Provides
None
Conflicts
None
Replaces
None
README
Laravel 애플리케이션에서 숫자, 통화, 퍼센트, 서수 표현을 일관되게 다루기 위한 PHP 패키지입니다. PHP의 NumberFormatter를 확장한 NFormat API와 함께 Laravel 서비스 프로바이더, 설정 파일, Eloquent 캐스트, 불변 값 객체를 제공합니다.
v2부터 N-Format은 NFormat 클래스 하나만 제공하던 래퍼에서 Laravel 통합을 포함하는 패키지로 확장되었습니다.
요구 사항
- PHP 8.2 이상
intlPHP 확장- Laravel 12 또는 13
설치
composer require cable8mm/n-format
Laravel의 패키지 자동 검색을 지원하므로 별도로 서비스 프로바이더를 등록할 필요가 없습니다.
설정
기본 설정은 한국어·대한민국 원화입니다.
// config/n-format.php return [ 'locale' => 'ko_KR', 'currency' => 'KRW', ];
설정 파일이 필요하면 애플리케이션으로 게시합니다.
php artisan vendor:publish --tag=n-format
게시한 설정은 모든 NFormat 메서드와 값 객체의 기본값으로 사용됩니다. 특정 호출에서 로케일이나 통화를 직접 전달하여 기본값을 덮어쓸 수도 있습니다.
기본 사용법
use Cable8mm\NFormat\NFormat; NFormat::currency(358762); // ₩358,762 NFormat::decimal(12346); // 12,346 NFormat::spellOut(5); // 오 NFormat::ordinalSpellOut(10); // 열번째 NFormat::currencySpellOut(12346); // 12,346 원 NFormat::percent(12346); // 1,234,600% NFormat::rawPercent(12346); // 12,346%
percent()는 입력값에 100을 곱하고, rawPercent()는 입력값을 100으로 나눈 뒤 퍼센트로 표시합니다.
PHP 8.2 이상에서는 파라미터 이름을 지정하는 named arguments도 사용할 수 있습니다. 긴 호출에서 각 값의 의미를 명확하게 표현할 수 있습니다.
NFormat::currency( number: 12346, zero: '-', locale: 'ja_JP', currency: 'JPY', ); // ¥12,346 NFormat::price(number: 12346, roundDigits: -2); // 12300
메서드 파라미터 이름은 공개 API의 일부이므로, named arguments를 사용하는 경우 파라미터 이름 변경에 주의해야 합니다.
호출별로 로케일과 통화를 지정할 수 있습니다.
NFormat::$locale = 'ja_JP'; NFormat::spellOut(5); // 五 NFormat::currency(12346, '0', 'ja_JP', 'JPY'); // ¥12,346
currency()의 두 번째 인자는 0 또는 null일 때 사용할 대체 문자열입니다. 세 번째와 네 번째 인자가 각각 로케일과 통화입니다.
가격 반올림
price()는 지정한 자릿수로 반올림하고, smartPrice()는 통화 드라이버의 규칙에 따라 자릿수별로 반올림합니다.
NFormat::price(12346, -2); // 12300 NFormat::smartPrice(12346); // 12300 NFormat::smartPrice(1234678); // 1230000
기본 KRW 규칙은 다음과 같습니다.
- 1~2자리: 반올림하지 않음
- 3자리: 10의 자리
- 4~5자리: 100의 자리
- 6자리: 1,000의 자리
- 7자리 이상: 10,000의 자리
Eloquent 캐스트
v2는 Eloquent 속성을 불변 값 객체로 변환하는 두 가지 캐스트를 제공합니다.
AsCurrency:Money값 객체 반환AsNumber:Number값 객체 반환
use Cable8mm\NFormat\Casts\AsCurrency; use Cable8mm\NFormat\Casts\AsNumber; use Illuminate\Database\Eloquent\Model; class Product extends Model { protected function casts(): array { return [ 'price' => AsCurrency::class, 'jpy' => AsCurrency::class.':ja_JP,JPY', 'discount' => AsNumber::class, 'count' => AsNumber::class.':ja_JP', ]; } }
읽을 때는 값 객체가 반환되고, 저장할 때는 통화 기호와 천 단위 구분자를 제거한 숫자만 데이터베이스에 저장됩니다.
$product = new Product; $product->price = '₩12,350원'; echo $product->price; // 12350 (raw value) echo $product->price->currency(); // ₩12,350 echo $product->price->price(-2); // 12400 echo $product->price->smartPrice(); // 12400 echo $product->price->spellOut(); // 12,350 원 echo $product->price->value(); // 12350
currency()는 금액이 0이어도 통화 형식으로 표시합니다. 무료 상품처럼 0원을 별도 문구로 표시하려면 display()를 사용합니다.
$product->price = 0; echo $product->price; // 0 (raw value) echo $product->price->currency(); // ₩0 echo $product->price->display(); // 무료 echo $product->price->freeLabel(); // 무료 echo $product->price->spellOut(); // 0 원 echo $product->price->displaySpelled(); // 무료
기본 번역은 한국어 무료, 영어 Free, 일본어 無料이며, AsCurrency에 지정한 로케일을 기준으로 선택합니다. 번역 파일은 다음 명령으로 게시할 수 있습니다.
php artisan vendor:publish --tag=n-format-translations
번역 키는 n-format::messages.free입니다.
Number는 기본적으로 천 단위 구분자를 사용해 출력합니다.
$product->discount = 12346; echo $product->discount; // 12,346 echo $product->discount->percent(); // 1,234,600% echo $product->discount->rawPercent(); // 12,346% echo $product->discount->spellOut(); // 일만이천삼백사십육 echo $product->discount->ordinalSpellOut(); // 열번째 echo $product->discount->value(); // 12346
두 값 객체는 Stringable, JsonSerializable을 구현합니다. 문자열로 출력하면 포맷된 값을 사용하고, JSON으로 직렬화하면 원시 숫자를 사용합니다.
Blade에서도 그대로 사용할 수 있습니다.
{{ $product->price }} {{ $product->discount->percent() }}
숫자·통화 캐스트는 숫자와 포맷된 숫자 문자열을 저장할 수 있습니다. null, 빈 문자열, 숫자로 변환할 수 없는 값은 null로 저장되거나 읽힙니다.
드라이버 확장
로케일별 서수 표현과 통화별 가격 규칙은 드라이버로 분리되어 있습니다. 다음 인터페이스를 구현한 뒤 등록하면 지원 범위를 확장할 수 있습니다.
use Cable8mm\NFormat\Drivers\Contracts\OrdinalDriver; final class EnUsOrdinalDriver implements OrdinalDriver { public function spellOut(int $number): string { return match ($number) { 1 => 'first', 2 => 'second', default => $number.'th', }; } } NFormat::registerOrdinal('en_US', new EnUsOrdinalDriver); NFormat::ordinalSpellOut(2, 'en_US'); // second
통화 드라이버는 currencySpellOut()과 roundDigits()를 구현합니다.
use Cable8mm\NFormat\Drivers\Contracts\CurrencyDriver; final class UsdCurrencyDriver implements CurrencyDriver { public function currencySpellOut(string $formatted): string { return $formatted.' dollars'; } public function roundDigits(): array { return [3 => -1, 4 => -2, 5 => -2]; } } NFormat::registerCurrency('USD', new UsdCurrencyDriver);
기본 제공 드라이버는 ko_KR 서수 표현과 KRW 통화 규칙입니다. 등록되지 않은 드라이버를 요청하면 ordinalSpellOut()과 currencySpellOut()은 NumberFormatter의 기본 결과를 반환합니다.
API
| 메서드 | 설명 |
|---|---|
spellOut(int, ?string) |
숫자를 단어로 변환 |
ordinalSpellOut(int, ?string) |
서수 표현 |
currency(int|float|null, string, ?string, ?string) |
통화 포맷 |
currencySpellOut(int|float, ?string, ?string) |
통화와 단어를 함께 표시 |
decimal(int|float|null, string, ?string) |
천 단위 구분자 포맷 |
percent(int|float, ?string) |
100을 곱한 퍼센트 |
rawPercent(int|float, ?string) |
100으로 나눈 퍼센트 |
price(int|float, ?int) |
지정 자릿수 반올림 |
smartPrice(int|float, ?string) |
통화 규칙에 따른 반올림 |
registerOrdinal(string, OrdinalDriver) |
로케일 드라이버 등록 |
registerCurrency(string, CurrencyDriver) |
통화 드라이버 등록 |
개발
composer install composer test # PHPUnit 테스트 composer inspect # 코드 스타일 검사 composer check # 스타일 검사와 테스트 composer lint # 코드 스타일 자동 수정
라이선스
N-Format은 MIT 라이선스로 제공됩니다.