Numbers written for people from a page's PHP: grouped with the locale's marks, shortened to 1.5K or 1.5 million, as a place, a percentage or a file size - and kept between bounds. These are the functions of Laravel's Number class, as plain functions. The abbreviate and ordinal pipes do the same in a template.

functionwhat it does
padNumberFormat ( $number, $decimals, $locale )the number grouped, with exactly so many decimals, the locale's way
padNumberPercentage ( $number, $precision )25 as 25%, 25.55 with a precision of 1 as 25.6%, the locale's way
padNumberAbbreviate ( $number, $precision )1500 as 2K, or 1.5K with a precision of 1 - K, M, B, T, Q
padNumberForHumans ( $number, $precision )1500000 as 2 million, or 1.5 million
padNumberFileSize ( $bytes, $precision )1536 as 2 KB, or 1.5 KB - what the bytes pipe answers
padNumberOrdinal ( $number )1st, 2nd, 3rd, 4th, 11th, 21st, 112th
padNumberClamp ( $number, $min, $max )the number, or the bound it went past

Formatting

padNumberFormat writes exactly $decimals decimals, with the thousands grouped and the decimal mark of the locale: the request's $padLocale, or the one given. padNumberPercentage takes a share already counted in hundreds - 25 is 25% - and writes it the locale's way too. Half is rounded up, so 2.5 is 3. PHP's intl extension does the writing when it is there; without it the number is written the plain number_format way.

PHP
fragments/numbers_1.php
HTML
fragments/numbers_1.pad
Result
<?php

// An order total written for the visitor - in the request's
// locale, then in two others - and a share of the sales.

$total = 1234567.891;

$en = padNumberFormat ( $total, 2 );
$nl = padNumberFormat ( $total, 2, 'nl' );
$de = padNumberFormat ( $total, 2, 'de_DE' );

$share = padNumberPercentage ( 25.55, 1 );

?>
<p>{$en} - {$nl} - {$de}</p>
<p>Share of the sales: {$share}</p>

1,234,567.89 - 1.234.567,89 - 1.234.567,89

Share of the sales: 25.6%

Short and readable

padNumberAbbreviate and padNumberForHumans write a large number in thousands, millions, billions, trillions or quadrillions, and padNumberFileSize a byte count in units of 1024. The precision is the most decimals written, the trailing zeros dropped: 1000 with a precision of 1 is 1K. The unit is chosen on the number as it will be written, so 999999 is 1M, not 1000K. Below 1000 the number has no unit, and a size below 1024 is in B. These write English, with a point before the decimals.

PHP
fragments/numbers_2.php
HTML
fragments/numbers_2.pad
Result
<?php

// Counters, a sentence and a download size, for people.

$numbers = [ 950, 1500, 48210, 1534200, 2500000000 ];

$stats = [];

foreach (
$numbers as $number )
$stats [] = [
'number' => $number,
'short' => padNumberAbbreviate ( $number, 1 ),
'words' => padNumberForHumans ( $number, 1 )
];

$download = padNumberFileSize ( 5347737, 1 );

?>
<table border="1" cellpadding="4" cellspacing="0">
<tr><th>number</th><th>abbreviate</th><th>for humans</th></tr>
{stats}
<tr><td>{$number}</td><td>{$short}</td><td>{$words}</td></tr>
{/stats}
</table>
<p>The download is {$download}.</p>
numberabbreviatefor humans
950950950
15001.5K1.5 thousand
4821048.2K48.2 thousand
15342001.5M1.5 million
25000000002.5B2.5 billion

The download is 5.1 MB.

Places and bounds

padNumberOrdinal writes the English place of a whole number - 11th, 12th and 13th take th, as do 111th to 113th. padNumberClamp keeps a number between a minimum and a maximum: a page number from the address that has to stay within the pages there are.

PHP
fragments/numbers_3.php
HTML
fragments/numbers_3.pad
Result
<?php

// The page number from the address, kept within the pages
// there are, and the places of a race.

$pages = 12;
$kept = [];

foreach ( [ -
3, 4, 40 ] as $asked )
$kept [] = [
'asked' => $asked,
'shown' => padNumberClamp ( $asked, 1, $pages )
];

$finished = [ 1, 2, 3, 11, 22, 101 ];
$ordinals = array_map ( 'padNumberOrdinal', $finished );
$places = implode ( ', ', $ordinals );

?>
{kept}
<p>Page {$asked} asked, page {$shown} shown</p>
{/kept}
<p>{$places}</p>

Page -3 asked, page 1 shown

Page 4 asked, page 4 shown

Page 40 asked, page 12 shown

1st, 2nd, 3rd, 11th, 22nd, 101st

In a template

The abbreviate pipe is padNumberAbbreviate - {$views | abbreviate}, {$views | abbreviate(1)} - and the ordinal pipe is padNumberOrdinal. A value that is not a number goes through them unchanged, as it does through bytes.

PHP
fragments/numbers_4.php
HTML
fragments/numbers_4.pad
Result
<?php

// The PHP hands over plain numbers; the template writes them
// for people.

$runners = [
[
'name' => 'Ann', 'place' => 1, 'views' => 1534200 ],
[
'name' => 'Bob', 'place' => 2, 'views' => 48210 ],
[
'name' => 'Cee', 'place' => 3, 'views' => 950 ]
];

?>
{runners}
<p>{$place | ordinal}: {$name},
{$views | abbreviate(1)} views</p>
{/runners}

1st: Ann, 1.5M views

2nd: Bob, 48.2K views

3rd: Cee, 950 views

Nothing and mistakes

NULL, FALSE and empty text are nothing to write: every function answers an empty string for them, padNumberClamp NULL. A value that is no number, a negative precision, a fraction handed to padNumberOrdinal, a locale intl does not know and a minimum above the maximum are reported as errors that name the function.