Skip to content

Commit cc47eb6

Browse files
authored
Refactor as a single-class bundle (#33)
1 parent 31ec4c4 commit cc47eb6

File tree

12 files changed

+216
-196
lines changed

12 files changed

+216
-196
lines changed

.github/workflows/tests.yml

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,33 @@ jobs:
1010
fail-fast: true
1111
matrix:
1212
php: [8.2, 8.3, 8.4]
13-
symfony: [5.4.*, 6.4.*, 7.0.*]
14-
dependency-version: [prefer-lowest, prefer-stable]
15-
exclude:
16-
- php: 8.4
17-
symfony: 5.4.*
18-
- php: 8.4
19-
symfony: 6.4.*
20-
- php: 8.4
21-
symfony: 7.0.*
22-
23-
name: Tests P${{ matrix.php }} - SF${{ matrix.symfony }} - ubuntu-latest - ${{ matrix.dependency-version }}
13+
symfony: [^6.4, false]
14+
dependency: [stable]
15+
include:
16+
- { php: 8.4, symfony: ^7.4, dependency: highest }
17+
- { php: 8.4, symfony: ^8.0, dependency: highest }
18+
19+
env:
20+
SYMFONY_REQUIRE: ${{ matrix.symfony }}
21+
22+
name: Tests P${{ matrix.php }} - SF${{ matrix.symfony }} - ubuntu-latest - ${{ matrix.dependency }}
2423
steps:
2524

2625
- name: Checkout
2726
uses: actions/checkout@v5
2827

29-
- name: Cache dependencies
30-
uses: actions/cache@v4
31-
with:
32-
path: ~/.composer/cache/files
33-
key: dependencies-php-${{ matrix.php }}-SF${{ matrix.symfony }}-${{ matrix.dependency-version }}-composer-${{ hashFiles('composer.json') }}
34-
3528
- name: Setup PHP
3629
uses: shivammathur/setup-php@v2
3730
with:
3831
php-version: ${{ matrix.php }}
3932
extensions: dom, mbstring, zip
4033
coverage: none
41-
42-
- name: Require Symfony Version
43-
run: >
44-
composer require
45-
"symfony/config:${{ matrix.symfony }}"
46-
"symfony/dependency-injection:${{ matrix.symfony }}"
47-
"symfony/http-kernel:${{ matrix.symfony }}"
48-
--no-interaction --no-update
34+
tools: flex
4935

5036
- name: Install Composer dependencies
51-
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist
37+
uses: ramsey/composer-install@v2
38+
with:
39+
dependency-versions: ${{ matrix.dependency }}
5240

5341
- name: Integration Tests
5442
run: php ./vendor/bin/simple-phpunit

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
/composer.lock
55
/phpunit.xml
66
/vendor/
7+
/var/
78
*.swp
89
*.swo

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## v0.17.0
8+
### Changed
9+
- Refactored into a single `OpenAI\Symfony\OpenAIBundle` class
10+
- Add `project` and `base_uri` configuration options
11+
- Drop support for unsupported Symfony versions. Now requires Symfony 6.4 or 7.3+
12+
- Add support for Symfony 8.0
13+
714
## v0.12.0 (2025-05-06)
815
### Changed
916
- Changed underlying `openai/client` package version to 0.12.0

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ OPENAI_API_KEY=sk-...
4242
OPENAI_ORGANIZATION=...
4343
```
4444

45+
For more configuration options, take a look at the [Configuration Reference](#configuration-reference).
46+
4547
Finally, you may use the `openai` service to access the OpenAI API:
4648

4749
```php
@@ -57,6 +59,18 @@ echo $result['choices'][0]['text']; // an open-source, widely-used, server-side
5759

5860
For usage examples, take a look at the [openai-php/client](https://github.com/openai-php/client) repository.
5961

62+
## Configuration Reference
63+
64+
The bundle provides the following configuration options, which you can set in your `config/packages/openai.yaml` file:
65+
66+
```yaml
67+
openai:
68+
api_key: '%env(OPENAI_API_KEY)%' # Your OpenAI API key (required)
69+
organization: '%env(OPENAI_ORGANIZATION)%' # Your OpenAI organization ID (optional)
70+
project: 'proj_...' # The project ID (optional)
71+
base_uri: 'api.openai.com/v1' # The base URI for the OpenAI API (optional)
72+
```
73+
6074
---
6175
6276
OpenAI PHP for Symfony is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.

composer.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,17 @@
2020
"openai-php/client": "^0.17.0",
2121
"psr/http-client": "^1.0.3",
2222
"psr/http-factory": "^1.1.0",
23-
"symfony/config": "^5.4|^6.3|^7.1.1",
24-
"symfony/dependency-injection": "^5.4|^6.3|^7.1.5",
25-
"symfony/http-client": "^5.4|^6.3|^7.1.5",
26-
"symfony/http-kernel": "^5.4|^6.3|^7.1.5"
23+
"symfony/config": "^6.4|^7.3|^8.0",
24+
"symfony/dependency-injection": "^6.4|^7.3|^8.0",
25+
"symfony/http-client": "^6.4|^7.3|^8.0",
26+
"symfony/http-kernel": "^6.4|^7.3|^8.0"
2727
},
2828
"require-dev": {
29-
"laravel/pint": "^1.18.1",
30-
"phpstan/phpstan": "^1.12.6",
31-
"rector/rector": "^0.14.8",
32-
"symfony/phpunit-bridge": "^5.4|^6.3|^7.1.4"
29+
"laravel/pint": "^1.24.0",
30+
"phpstan/phpstan": "^2.1.22",
31+
"rector/rector": "^2.1.5",
32+
"symfony/phpunit-bridge": "^6.4.25|^7.3|^8.0",
33+
"symfony/framework-bundle": "^6.4|^7.3|^8.0"
3334
},
3435
"autoload": {
3536
"psr-4": {
@@ -53,7 +54,7 @@
5354
"scripts": {
5455
"lint": "pint -v",
5556
"refactor": "rector --debug",
56-
"test:lint": "pint --test -v",
57+
"test:lint": "pint --test -v ./src ./tests",
5758
"test:types": "phpstan analyse --ansi",
5859
"test:unit": "simple-phpunit --colors=always",
5960
"test": [

rector.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,15 @@
44

55
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
66
use Rector\Config\RectorConfig;
7+
use Rector\Php81\Rector\Array_\FirstClassCallableRector;
78
use Rector\Set\ValueObject\LevelSetList;
89
use Rector\Set\ValueObject\SetList;
910

1011
return static function (RectorConfig $rectorConfig): void {
1112
$rectorConfig->paths([
1213
__DIR__.'/src',
13-
]);
14-
15-
$rectorConfig->skip([
16-
__DIR__.'/src/Resources/config/',
14+
__DIR__.'/tests',
15+
__DIR__.'/rector.php',
1716
]);
1817

1918
$rectorConfig->rules([
@@ -28,4 +27,8 @@
2827
SetList::TYPE_DECLARATION,
2928
SetList::PRIVATIZATION,
3029
]);
30+
31+
$rectorConfig->skip([
32+
FirstClassCallableRector::class,
33+
]);
3134
};

src/DependencyInjection/Configuration.php

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/DependencyInjection/OpenAIExtension.php

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/OpenAIBundle.php

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,76 @@
44

55
namespace OpenAI\Symfony;
66

7-
use Symfony\Component\HttpKernel\Bundle\Bundle;
7+
use OpenAI\Client;
8+
use OpenAI\Contracts\ClientContract;
9+
use OpenAI\Factory;
10+
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
11+
use Symfony\Component\Config\Definition\Configurator\DefinitionConfigurator;
12+
use Symfony\Component\DependencyInjection\ContainerBuilder;
13+
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
14+
use Symfony\Component\HttpClient\Psr18Client;
15+
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
816

9-
final class OpenAIBundle extends Bundle {}
17+
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
18+
19+
final class OpenAIBundle extends AbstractBundle
20+
{
21+
protected string $extensionAlias = 'openai';
22+
23+
public function configure(DefinitionConfigurator $definition): void
24+
{
25+
$root = $definition->rootNode();
26+
assert($root instanceof ArrayNodeDefinition);
27+
$children = $root->children();
28+
$children
29+
->scalarNode('api_key')
30+
->defaultValue('%env(OPENAI_API_KEY)%')
31+
->info('OpenAI API Key used to authenticate with the OpenAI API')
32+
->isRequired();
33+
$children
34+
->scalarNode('organization')
35+
->info('OpenAI API Organization used to authenticate with the OpenAI API')
36+
->defaultValue('%env(default::OPENAI_ORGANIZATION)%')
37+
->info('');
38+
$children
39+
->scalarNode('project')
40+
->defaultNull()
41+
->info('OpenAI API project');
42+
$children
43+
->scalarNode('base_uri')
44+
->defaultNull()
45+
->info('OpenAI API base URL used to make requests. Defaults to: api.openai.com/v1');
46+
}
47+
48+
/**
49+
* @param array{api_key: string, organization: string, project: ?string, base_uri: ?string} $config
50+
*/
51+
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
52+
{
53+
$container->services()
54+
->set('openai.http_client', Psr18Client::class)
55+
->arg(0, service('http_client'));
56+
57+
$factory = $container->services()
58+
->set(Factory::class)
59+
->factory([\OpenAI::class, 'factory'])
60+
->call('withHttpClient', [service('openai.http_client')])
61+
->call('withHttpHeader', ['OpenAI-Beta', 'assistants=v2'])
62+
->call('withApiKey', [$config['api_key']])
63+
->call('withOrganization', [$config['organization']]);
64+
if ($config['project']) {
65+
$factory->call('withProject', [$config['project']]);
66+
}
67+
if ($config['base_uri']) {
68+
$factory->call('withBaseUri', [$config['base_uri']]);
69+
}
70+
71+
$container->services()
72+
->set(Client::class)
73+
->factory([service(Factory::class), 'make']);
74+
75+
$container->services()
76+
->alias(ClientContract::class, Client::class)
77+
->alias('openai', Client::class);
78+
}
79+
}

src/Resources/config/services.php

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)