English | العربية | বাংলা | Bosanski | Deutsch | Español | Français | हिन्दी | Italiano | 日本語 | 한국어 | मराठी | Português | Русский | Kiswahili | தமிழ் | తెలుగు | Türkçe | اردو | Tiếng Việt | 中文
Faker Storage is a high-performance PHP package designed to generate and store large volumes of fake data files efficiently. Built with concurrency in mind, it leverages Swoole or PCNTL to generate thousands of files in parallel, making it ideal for load testing, development environments, and storage system benchmarking.
The package provides a fluent API for generating various file types including images (PNG, JPG, GIF, BMP, WEBP, AVIF), text files, CSV files, binary data, and RFC822-compliant emails. Each generator produces deterministic output when seeded, ensuring reproducible test data across environments.
use DefectiveCode\Faker\Faker;use League\Flysystem\Filesystem;use DefectiveCode\Faker\Generators\Png;use League\Flysystem\Local\LocalFilesystemAdapter; // Generate 1000 PNG images with 10 concurrent workersFaker::make(Png::class) ->width(800, 1920) ->height(600, 1080) ->toDisk(new Filesystem(new LocalFilesystemAdapter('/path/to/storage'))) ->basePath('images') ->count(1000) ->concurrency(10) ->seed(42) ->generate(); // Generate CSV filesuse DefectiveCode\Faker\Generators\Csv; Faker::make(Csv::class) ->columns(5, 10) ->rows(100, 500) ->delimiter(',') ->toDisk(new Filesystem(new LocalFilesystemAdapter('/path/to/storage'))) ->count(50) ->generate(); // Generate emails with attachmentsuse DefectiveCode\Faker\Generators\Email; Faker::make(Email::class) ->paragraphs(3, 5) ->sentences(2, 4) ->withAttachment(Png::class, 1, 3) ->toDisk(new Filesystem(new LocalFilesystemAdapter('/path/to/storage'))) ->count(100) ->generate();
Install the package via Composer:
composer require defectivecode/faker-storage
For optimal performance, install the Swoole extension:
pecl install swoole
The package will automatically use Swoole if available, falling back to PCNTL otherwise.
All generators follow the same pattern:
use DefectiveCode\Faker\Faker;use League\Flysystem\Filesystem;use DefectiveCode\Faker\Generators\Text;use League\Flysystem\Local\LocalFilesystemAdapter; Faker::make(Text::class) ->paragraphs(5, 10) // Generator-specific configuration ->toDisk(new Filesystem(new LocalFilesystemAdapter('/storage'))) ->basePath('documents') // Files will be in /storage/documents/ ->count(100) // Generate 100 files ->concurrency(4) // Use 4 workers ->seed(123) // For deterministic output ->generate();
Faker Storage uses League Flysystem for storage abstraction:
use League\Flysystem\Filesystem;use League\Flysystem\Local\LocalFilesystemAdapter; // Local storage$filesystem = new Filesystem(new LocalFilesystemAdapter('/path/to/storage')); Faker::make(Png::class) ->toDisk($filesystem) ->generate();
use Aws\S3\S3Client;use League\Flysystem\Filesystem;use League\Flysystem\AwsS3V3\AwsS3V3Adapter; $client = new S3Client([ 'credentials' => [ 'key' => 'your-key', 'secret' => 'your-secret', ], 'region' => 'us-east-1', 'version' => 'latest',]); $adapter = new AwsS3V3Adapter($client, 'your-bucket-name');$filesystem = new Filesystem($adapter); Faker::make(Png::class) ->toDisk($filesystem) ->basePath('uploads/images') ->generate();
Pass additional options to the filesystem adapter:
Faker::make(Png::class) ->toDisk($filesystem) ->diskOptions([ 'visibility' => 'public', 'ACL' => 'public-read', 'CacheControl' => 'max-age=31536000', ]) ->generate();
Control parallel execution with the concurrency() method:
// Use 10 worker threads/processesFaker::make(Png::class) ->concurrency(10) ->generate(); // Swoole-specific: Set both threads and coroutines per threadFaker::make(Png::class) ->concurrency(threads: 4, coroutines: 8) // 4 workers, 8 coroutines each ->generate();
By default, files are named using UUID v4:
// Generates: e7f0a8d3-5c2b-4f9e-8a1d-3b4c5d6e7f8a.pngFaker::make(Png::class)->generate();
use DefectiveCode\Faker\NameGenerator; // UUID-based (default)NameGenerator::setDefault('uuid'); // Generates: e7f0a8d3-5c2b-4f9e-8a1d-3b4c5d6e7f8a.png // Sequential numberingNameGenerator::setDefault('sequence'); // Generates: 1.png, 2.png, 3.png, ...
Provide a closure to customize file names:
use DefectiveCode\Faker\NameGenerator; // Custom closureFaker::make(Png::class) ->nameGenerator(function (int $seed, int $completedFiles, $generator) { return "custom-{$completedFiles}-{$seed}.png"; }) ->generate(); // Date-based namingFaker::make(Png::class) ->nameGenerator(function (int $seed, int $completedFiles, $generator) { return date('Y/m/d') . "/image-{$completedFiles}.png"; }) ->generate();
Set a seed to generate the same files across runs:
Faker::make(Png::class) ->seed(42) ->count(10) ->generate();
Each file gets a unique deterministic seed derived from the base seed and file index.
All image generators support dimension and quality configuration.
use DefectiveCode\Faker\Generators\Png; Faker::make(Png::class) ->width(800, 1920) // Random width between 800-1920px ->height(600, 1080) // Random height between 600-1080px ->withAlpha(true) // Enable alpha/transparency channel ->grid(5) // Optional: Generate 5x5 symmetric pattern ->toDisk($filesystem) ->generate();
use DefectiveCode\Faker\Generators\Jpg; Faker::make(Jpg::class) ->width(800, 1920) // Random width between 800-1920px ->height(600, 1080) // Random height between 600-1080px ->grid(5) // Optional: Generate 5x5 symmetric pattern ->toDisk($filesystem) ->generate();
use DefectiveCode\Faker\Generators\Gif; Faker::make(Gif::class) ->width(800, 1920) // Random width between 800-1920px ->height(600, 1080) // Random height between 600-1080px ->withAlpha(true) // Enable alpha/transparency channel ->grid(5) // Optional: Generate 5x5 symmetric pattern ->toDisk($filesystem) ->generate();
use DefectiveCode\Faker\Generators\Bmp; Faker::make(Bmp::class) ->width(800, 1920) // Random width between 800-1920px ->height(600, 1080) // Random height between 600-1080px ->grid(5) // Optional: Generate 5x5 symmetric pattern ->toDisk($filesystem) ->generate();
use DefectiveCode\Faker\Generators\Webp; Faker::make(Webp::class) ->width(800, 1920) // Random width between 800-1920px ->height(600, 1080) // Random height between 600-1080px ->withAlpha(true) // Enable alpha/transparency channel ->grid(5) // Optional: Generate 5x5 symmetric pattern ->toDisk($filesystem) ->generate();
use DefectiveCode\Faker\Generators\Avif; Faker::make(Avif::class) ->width(800, 1920) // Random width between 800-1920px ->height(600, 1080) // Random height between 600-1080px ->withAlpha(true) // Enable alpha/transparency channel ->grid(5) // Optional: Generate 5x5 symmetric pattern ->toDisk($filesystem) ->generate();
Generates a random image format:
use DefectiveCode\Faker\Generators\RandomImage; Faker::make(RandomImage::class) ->width(800, 1920) ->height(600, 1080) ->withAlpha(false) // Random from: AVIF, BMP, GIF, JPEG, PNG, WEBP ->toDisk($filesystem) ->generate(); Faker::make(RandomImage::class) ->width(800, 1920) ->height(600, 1080) ->withAlpha(true) // Random from: AVIF, GIF, PNG, WEBP ->toDisk($filesystem) ->generate();
Generate plain text files with paragraphs:
use DefectiveCode\Faker\Generators\Text; Faker::make(Text::class) ->paragraphs(5, 10) // 5-10 paragraphs per file ->sentences(3, 6) // 3-6 sentences per paragraph ->toDisk($filesystem) ->generate();
Output Example:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Generate CSV files with random data:
use DefectiveCode\Faker\Generators\Csv; Faker::make(Csv::class) ->columns(5, 10) // 5-10 columns ->rows(100, 500) // 100-500 rows ->delimiter(',') // Column delimiter ->enclosure('"') // Field enclosure ->escape('\\') // Escape character ->eol("\n") // Line ending ->toDisk($filesystem) ->generate();
Output Example:
"John Doe","john@example.com","555-1234","New York","Engineer""Jane Smith","jane@example.com","555-5678","Los Angeles","Designer""Bob Johnson","bob@example.com","555-9012","Chicago","Manager"
Generate random binary data:
use DefectiveCode\Faker\Generators\Binary; Faker::make(Binary::class) ->length(1024, 1048576) // 1KB - 1MB ->toDisk($filesystem) ->generate();
Generate RFC822-compliant email files:
use DefectiveCode\Faker\Generators\Email; Faker::make(Email::class) ->paragraphs(3, 5) // Paragraphs in email body ->sentences(2, 4) // Sentences per paragraph ->withAttachment(Png::class, 1, 3) // Add 1-3 PNG attachments ->toDisk($filesystem) ->generate();
Generated emails include:
To: Random name and emailFrom: Random name and emailSubject: Random sentenceDate: Current timestampMessage-ID: Deterministic ID based on seedAttach files using generator class names or instances:
use DefectiveCode\Faker\Generators\Email;use DefectiveCode\Faker\Generators\Png;use DefectiveCode\Faker\Generators\Pdf; Faker::make(Email::class) ->withAttachment(Png::class, 1, 3) // 1-3 PNG attachments ->generate(); // Attach using configured generator instance$pngGenerator = new Png(Png::getDefaultConfig());$pngGenerator->width(400, 800)->height(300, 600); Faker::make(Email::class) ->withAttachment($pngGenerator, 2, 5) ->generate();
Output Example:
To: John Doe <john.doe@example.com>From: Jane Smith <jane.smith@example.com>Subject: Important meeting tomorrowDate: Fri, 03 Jan 2026 10:30:00 +0000Message-ID: <3e92e5c2b0d632b3a36fbbb17484b7fe@example.com>Content-Type: multipart/mixed; boundary="----=_Part_123" ------=_Part_123Content-Type: text/plain; charset=utf-8Content-Transfer-Encoding: quoted-printable Lorem ipsum dolor sit amet, consectetur adipiscing elit... ------=_Part_123Content-Type: image/png; name="attachment.png"Content-Disposition: attachment; filename="attachment.png"Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==------=_Part_123--
Create your own generators by implementing the Generator interface:
use DefectiveCode\Faker\Configs\Config;use DefectiveCode\Faker\Concerns\SetsSeed;use DefectiveCode\Faker\Generators\Generator;use DefectiveCode\Faker\Concerns\PreparesFaker; class MyCustomGenerator implements Generator{ use PreparesFaker; use SetsSeed; public function __construct(public Config $config) {} public static function getDefaultConfig(): Config { return new MyCustomConfig([ 'contentType' => 'application/x-custom', 'nameGenerator' => NameGenerator::default('extension'), ]); } public function generate(): mixed { // Your generation logic here $data = $this->faker->randomElement(['foo', 'bar', 'baz']); $stream = fopen('php://temp', 'w+'); fwrite($stream, $data); return $stream; }} // Use your custom generatorFaker::make(MyCustomGenerator::class) ->toDisk($filesystem) ->generate();
Each generator uses a configuration class extending Config:
use DefectiveCode\Faker\Configs\Config; class MyCustomConfig extends Config{ public int $minValue = 1; public int $maxValue = 100;}
These methods are available on all Faker instances:
make(string $generator): FakerCreate a new Faker instance with the specified generator:
Faker::make(Png::class)
toDisk(Filesystem $filesystem): FakerSet the storage destination (required):
Faker::make(Png::class) ->toDisk(new Filesystem(new LocalFilesystemAdapter('/storage')))
basePath(string $basePath): FakerSet the base path within the filesystem:
Faker::make(Png::class) ->basePath('images/uploads') // Files stored in /storage/images/uploads/
count(int $count): FakerSet the number of files to generate:
Faker::make(Png::class) ->count(1000)
concurrency(int $threads, ?int $coroutines = null): FakerConfigure parallel execution:
// Basic concurrencyFaker::make(Png::class) ->concurrency(4) // Swoole-specific: threads and coroutinesFaker::make(Png::class) ->concurrency(threads: 4, coroutines: 8)
seed(int $seed): FakerSet seed for deterministic generation:
Faker::make(Png::class) ->seed(42)
nameGenerator(Closure $generator): FakerCustomize file naming:
Faker::make(Png::class) ->nameGenerator(function (int $seed, int $completedFiles, $generator) { return "file-{$completedFiles}.png"; })
diskOptions(array $diskOptions): FakerPass options to the filesystem adapter:
Faker::make(Png::class) ->diskOptions([ 'visibility' => 'public', 'ACL' => 'public-read', ])
generate(): voidExecute file generation:
Faker::make(Png::class)->generate();
Thanks for choosing our open source package! Please take a moment to check out these support guidelines. They'll help you get the most out of our project.
Our open-source project is fueled by our awesome community. If you have questions or need assistance, StackOverflow and other online resources are your best bets.
The reality of managing an open-source project means we can't address every reported bug or feature request immediately. We prioritize issues in the following order:
Bugs that impact our paid products will always be our top priority. In some cases, we may only address bugs that affect us directly.
If you've identified a bug and have a solution, please submit a pull request. After issues affecting our products, we give the next highest priority to these community-driven fixes. Once reviewed and approved, we'll merge your solution and credit your contribution.
For issues outside the mentioned categories, you can opt to fund their resolution. Each open issue is linked to an order form where you can contribute financially. We prioritize these issues based on the funding amount provided.
Open source thrives when its community is active. Even if you're not fixing bugs, consider contributing through code improvements, documentation updates, tutorials, or by assisting others in community channels. We highly encourage everyone, as a community, to help support open-source work.
To reiterate, DefectiveCode will prioritize bugs based on how they impact our paid products, community pull requests, and the financial support received for issues.
Copyright © Defective Code, LLC. All rights reserved
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.