zenstruck/bytes
Small PHP bytes utility for working with file sizes: parse human-readable strings (e.g. "10 MB"), format byte counts, compare values, and convert between units. Handy for Laravel/PHP apps needing consistent size handling and validation.
Installation:
composer require zenstruck/bytes
No configuration is required—just autoload the package.
First Use Case: Parse and humanize bytes in a Blade view or controller:
use Zenstruck\Bytes\Bytes;
$bytes = Bytes::of(1500); // Parse bytes
echo $bytes->human(); // Outputs: "1.43 KB"
Where to Look First:
Parsing Bytes:
$bytes = Bytes::of(1024 * 1024); // Parse from integer (e.g., 1MB)
$bytes = Bytes::of('1MB'); // Parse from string (e.g., "1MB", "2.5GB")
Humanizing Output:
$bytes->human(); // "1 MB"
$bytes->human('si'); // "1 MiB" (binary SI units)
$bytes->human('B'); // "1048576 B" (raw bytes)
Formatting for APIs/CLI:
$bytes->format('%01.2f %s'); // "1.00 MB"
$bytes->format('%s'); // "MB" (unit only)
Validation/Constraints:
use Zenstruck\Bytes\Constraints\MaxBytes;
$validator = Validator::make(['file' => $request->file], [
'file' => ['required', new MaxBytes(5 * Bytes::MEGA)]
]);
Laravel Integration:
$request->file('avatar')->getSize() // Get bytes
->human(); // Display to user
$usage = Storage::disk('s3')->usage();
Bytes::of($usage)->human(); // "1.2 GB"
Testing:
$this->assertEquals('1.43 KB', Bytes::of(1500)->human());
Unit Confusion:
human() defaults to decimal (SI) units (e.g., "1 MB" = 1,000,000 bytes).human('binary') for binary (IEC) units (e.g., "1 MiB" = 1,048,576 bytes).Bytes::DECIMAL vs. Bytes::BINARY).String Parsing Quirks:
KB, MB, GB, TB (decimal) and KiB, MiB, GiB, TiB (binary)."1mb" works, "1" fails).Bytes::isValid('1MB') before parsing.Precision Loss:
format() with precision:
$bytes->format('%.3f %s'); // "1.429 MB" (3 decimal places)
Constraint Edge Cases:
MaxBytes throws InvalidArgumentException for invalid values. Catch or validate first:
try {
Bytes::of($request->input('size'));
} catch (\InvalidArgumentException $e) {
return back()->withError('Invalid size format.');
}
Reusable Helpers: Create a helper for common humanization:
if (!function_exists('bytes_human')) {
function bytes_human($bytes, string $unit = 'decimal'): string {
return Bytes::of($bytes)->human($unit);
}
}
Usage: bytes_human(1500) → "1.43 KB".
Localization:
Extend Humanizer to support custom units/translations:
$humanizer = new Humanizer(['KB' => 'Kilobyte']);
Bytes::of(1024)->humanizeWith($humanizer); // "1 Kilobyte"
Performance:
$cacheKey = 'max_upload_size';
$maxSize = Bytes::of(cache($cacheKey) ?? config('filesystems.max_upload'));
Debugging:
->bytes() to verify parsing:
$bytes = Bytes::of('1MB');
$bytes->bytes(); // 1000000 (decimal) or 1048576 (binary)
Testing Binary vs. Decimal:
$this->assertEquals('1 MiB', Bytes::of(1048576)->human('binary'));
$this->assertEquals('1 MB', Bytes::of(1000000)->human('decimal'));
How can I help you explore Laravel packages today?