├── .github
└── workflows
│ ├── format.yml
│ └── test.yml
├── .gitignore
├── README.md
├── composer.json
├── image
└── usage.gif
├── phpunit.xml.dist
├── pint.json
├── src
├── FakerOpenAIServiceProvider.php
├── Providers
│ └── FakerOpenAIPromptProvider.php
└── config.php
├── testbench.yaml
└── tests
└── FakerOpenAITest.php
/.github/workflows/format.yml:
--------------------------------------------------------------------------------
1 | name: Format Code
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | format:
11 | runs-on: ubuntu-24.04
12 |
13 | steps:
14 | - uses: actions/checkout@v4
15 |
16 | - name: Setup PHP
17 | uses: shivammathur/setup-php@v2
18 | with:
19 | php-version: '8.2'
20 | coverage: none
21 |
22 | - name: Install Dependencies
23 | run: composer install --no-interaction --prefer-dist
24 |
25 | - name: Run Laravel Pint
26 | run: composer format
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Run Tests
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | test:
11 | runs-on: ubuntu-24.04
12 | strategy:
13 | matrix:
14 | php: ['8.2', '8.3', '8.4']
15 | fail-fast: false
16 |
17 | steps:
18 | - uses: actions/checkout@v4
19 |
20 | - name: Setup PHP
21 | uses: shivammathur/setup-php@v2
22 | with:
23 | php-version: ${{ matrix.php }}
24 | coverage: xdebug
25 |
26 | - name: Install Dependencies
27 | run: composer install --no-interaction --prefer-dist
28 |
29 | - name: Run PHPUnit Tests
30 | run: composer test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | build
3 | composer.lock
4 | vendor
5 | .phpunit.result.cache
6 | .php-cs-fixer.cache
7 | .phpunit.cache
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Faker OpenAI Provider
2 |
3 | 
4 |
5 |
6 |
7 |
8 |
9 | A Laravel package that extends FakerPHP by adding an AI-powered data generator using OpenAI. This allows you to generate more realistic and context-aware fake data in your Laravel applications.
10 |
11 | ## Installation
12 |
13 | Install the package via Composer:
14 |
15 | ```bash
16 | composer require jpcaparas/laravel-faker-openai
17 | ```
18 |
19 | The package will automatically register its service provider if you're using Laravel's package auto-discovery.
20 |
21 | ## Configuration
22 |
23 | 1. Next, execute the install command:
24 |
25 | ```bash
26 | php artisan openai:install
27 | ```
28 |
29 | This will create a `config/openai.php` configuration file in your project, which you can modify to your needs using environment variables.
30 |
31 | 2. Make sure you have your OpenAI API key set in your `.env` file:
32 |
33 | ```env
34 | OPENAI_API_KEY=your-api-key-here
35 | ```
36 |
37 | 3. The package uses `gpt-3.5-turbo` model by default.
38 |
39 | ## Usage
40 |
41 | The package adds a new `promptAI()` method to the Faker generator. You can use it in several ways:
42 |
43 | ### Basic Usage
44 |
45 | ```php
46 | $faker = app(\Faker\Generator::class);
47 |
48 | // Generate a fake name using AI
49 | $name = $faker->promptAI('name');
50 |
51 | // Generate a movie review
52 | $review = $faker->promptAI('movieReview');
53 |
54 | // Generate a movie description
55 | $description = $faker->promptAI('movieDescription');
56 | ```
57 |
58 | ... you can also use the built-in `fake()` helper:
59 |
60 | ```php
61 | $name = fake('name');
62 | ```
63 |
64 | ### With Fallback Values
65 |
66 | You can provide fallback values that will be used if the AI request fails:
67 |
68 | ```php
69 | // String fallback
70 | $name = $faker->promptAI('name', 'John Doe');
71 |
72 | // Closure fallback
73 | $name = $faker->promptAI('name', fn() => 'John Doe');
74 | ```
75 |
76 | ### Error Handling
77 |
78 | By default, errors are logged and the fallback value is returned. You can make it throw exceptions instead:
79 |
80 | ```php
81 | try {
82 | $name = $faker->promptAI('name', null, true); // Set throwOnError to true
83 | } catch (\Exception $e) {
84 | // Handle the error
85 | }
86 | ```
87 |
88 | ## How It Works
89 |
90 | The package works by:
91 | 1. Intercepting FakerPHP method calls through a prompt
92 | 2. Sending them to OpenAI's GPT model
93 | 3. Returning AI-generated responses that match FakerPHP's expected output format
94 |
95 | ## Testing
96 |
97 | Run the test suite:
98 |
99 | ```bash
100 | composer test
101 | ```
102 |
103 | ## License
104 | MIT
105 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jpcaparas/laravel-faker-openai",
3 | "description": "An opinionated Laravel package that modifies the service container Faker behaviour to allow prompts to be generated with OpenAI",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "JP Caparas",
8 | "email": "jp@jpcaparas.com"
9 | }
10 | ],
11 | "type": "library",
12 | "autoload": {
13 | "psr-4": {
14 | "JPCaparas\\FakerOpenAI\\": "src/"
15 | }
16 | },
17 | "autoload-dev": {
18 | "psr-4": {
19 | "JPCaparas\\FakerOpenAI\\Tests\\": "tests/"
20 | }
21 | },
22 | "require": {
23 | "php": "^8.2",
24 | "fakerphp/faker": "^1.24",
25 | "laravel/framework": "^10.0 || ^11.0",
26 | "nyholm/psr7": "^1.8",
27 | "openai-php/laravel": "^0.10.2",
28 | "symfony/http-client": "^7.2"
29 | },
30 | "config": {
31 | "sort-packages": true,
32 | "allow-plugins": {
33 | "php-http/discovery": true
34 | }
35 | },
36 | "require-dev": {
37 | "laravel/pint": "^1.19",
38 | "orchestra/testbench": "*"
39 | },
40 | "extra": {
41 | "laravel": {
42 | "providers": [
43 | "JPCaparas\\FakerOpenAI\\FakerOpenAIServiceProvider"
44 | ]
45 | }
46 | },
47 | "scripts": {
48 | "format": "pint",
49 | "tests": "phpunit",
50 | "tinker": "testbench tinker"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/image/usage.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpcaparas/laravel-faker-openai/ba31fafe707c0139ffd5d78920bd4fe5fadbfcae/image/usage.gif
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 | tests
10 |
11 |
12 |
13 |
14 | src
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/pint.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "laravel"
3 | }
--------------------------------------------------------------------------------
/src/FakerOpenAIServiceProvider.php:
--------------------------------------------------------------------------------
1 | registerFakerGenerator();
22 | }
23 |
24 | public function boot()
25 | {
26 | //
27 | }
28 |
29 | /**
30 | * Overridden the default Faker generator to include custom providers.
31 | *
32 | * @see \Illuminate\Database\DatabaseServiceProvider::registerFakerGenerator()
33 | */
34 | protected function registerFakerGenerator(): void
35 | {
36 | $this->app->singleton(FakerGenerator::class, function ($app, $parameters) {
37 | $locale = $parameters['locale'] ?? $app['config']->get('app.faker_locale', 'en_US');
38 |
39 | if (! isset(static::$fakers[$locale])) {
40 | $fakerFactory = FakerFactory::create($locale);
41 |
42 | $fakerFactory->addProvider(new FakerOpenAIPromptProvider);
43 |
44 | static::$fakers[$locale] = $fakerFactory;
45 | }
46 |
47 | static::$fakers[$locale]->unique(true);
48 |
49 | return static::$fakers[$locale];
50 | });
51 |
52 | // For usage on the `faker()` helper, which requires the locale to be set.
53 | $fakerLocale = $this->app['config']->get('app.faker_locale', 'en_US');
54 | $this->app->alias(FakerGenerator::class, FakerGenerator::class.':'.$fakerLocale);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Providers/FakerOpenAIPromptProvider.php:
--------------------------------------------------------------------------------
1 | promptAI('name')
23 | * @example $faker->promptAI('movieReview') // This will return a movie review
24 | * @example $faker->promptAI('movieDescription') // This will return a movie description
25 | * @example $faker->promptAI('name', 'John Doe') // This defaults to 'John Doe' if an error occurs
26 | * @example $faker->promptAI('name', fn() => 'John Doe') // This defaults to 'John Doe' if an error occurs
27 | * @example $faker->promptAI('randomNumber', fn() => 99) // This defaults to 99 if an error occurs (but why would you do this?)
28 | */
29 | public function promptAI(string $term, null|string|callable $fallback = null, $throwOnError = false): mixed
30 | {
31 | try {
32 | $result = OpenAI::chat()->create([
33 | 'model' => 'gpt-3.5-turbo',
34 | 'messages' => [
35 | [
36 | 'role' => 'user',
37 | 'content' => 'Return only the output value of \Faker\Factory::create()->'.Str::camel($term).'() without any explanation or formatting. A simple string, please.',
38 | ],
39 | ],
40 | ]);
41 |
42 | return $result->choices[0]->message->content;
43 | } catch (ErrorException|TransporterException $e) {
44 | if ($throwOnError) {
45 | throw $e;
46 | }
47 |
48 | Log::error($e->getMessage());
49 |
50 | if (is_string($fallback)) {
51 | return $fallback;
52 | }
53 |
54 | if (is_callable($fallback)) {
55 | return $fallback();
56 | }
57 |
58 | return null;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/config.php:
--------------------------------------------------------------------------------
1 | [
5 | 'model' => env('OPENAI_MODEL', 'text-davinci-003'),
6 | 'default_prompt' => env('OPENAI_DEFAULT_PROMPT', 'Generate fake data'),
7 | ],
8 | ];
9 |
--------------------------------------------------------------------------------
/testbench.yaml:
--------------------------------------------------------------------------------
1 | providers:
2 | - OpenAI\Laravel\ServiceProvider
3 | - JPCaparas\FakerOpenAI\FakerOpenAIServiceProvider
4 |
--------------------------------------------------------------------------------
/tests/FakerOpenAITest.php:
--------------------------------------------------------------------------------
1 | app->make(FakerGenerator::class);
28 |
29 | $this->assertInstanceOf(FakerGenerator::class, $faker);
30 | }
31 |
32 | public function test_it_registers_ai_prompt_provider()
33 | {
34 | $faker = $this->app->make(FakerGenerator::class);
35 |
36 | $providers = array_map(fn($provider) => get_class($provider), $faker->getProviders());
37 |
38 | $this->assertContains(FakerOpenAIPromptProvider::class, $providers);
39 | }
40 |
41 | public function test_prompt_ai_returns_generated_content()
42 | {
43 | OpenAI::fake([
44 | CreateResponse::fake(),
45 | ]);
46 |
47 | $faker = $this->app->make(FakerGenerator::class);
48 | $response = $faker->promptAI('test prompt');
49 | $this->assertNotEmpty($response, 'No response from OpenAI API');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------