aurelbichop/recherche-entreprises-bundle
Installation
Run composer require aurelbichop/recherche-entreprises-bundle in your Symfony 7.3+ project.
Verify the bundle is registered in config/bundles.php (automatically added via Composer).
First Use Case
Inject EntrepriseSearchClientInterface into a controller/service to fetch enterprise data:
use AurelBichop\RechercheEntreprisesBundle\Client\EntrepriseSearchClientInterface;
public function search(EntrepriseSearchClientInterface $client) {
$result = $client->search('carrefour');
return $this->json($result->results);
}
Key Classes to Explore
EntrepriseSearchClientInterface: Core API client (implemented by EntrepriseSearchClient).SearchResult: Paginated response wrapper.Entreprise: Model for enterprise data (includes siren, nomComplet, siege, etc.).recherche-entreprise:search) for quick CLI testing.Quick CLI Test
Run php bin/console recherche-entreprise:search "carrefour" to verify connectivity.
EntrepriseSearchClientInterface for testability.
public function __construct(
private EntrepriseSearchClientInterface $client,
private LoggerInterface $logger
) {}
class EnterpriseService {
public function __construct(private EntrepriseSearchClientInterface $client) {}
public function getEnterpriseDetails(string $siren): ?Entreprise {
$this->client->findBySiren($siren);
// Add validation/logic here
}
}
Search by Name/Keyword
$results = $client->search('startup tech', [
'page' => 2, // Pagination support
'per_page' => 50,
]);
results->total to check for more pages.Fetch by SIREN
$entreprise = $client->findBySiren('123456789');
if (!$entreprise) {
throw new \RuntimeException("SIREN not found");
}
Bulk Operations
$sirenList = ['12345', '67890', '54321'];
$data = array_map([$client, 'findBySiren'], $sirenList);
Async Processing
Use Symfony’s HttpClient directly (via $client->getHttpClient()) for async requests:
$promises = [];
foreach ($sirenList as $siren) {
$promises[] = $client->getHttpClient()->request('GET', "/entreprises/$siren");
}
$responses = \Symfony\Contracts\HttpClient\Promise\PromiseUtils::waitAll($promises);
Entreprise objects to Symfony forms for admin panels.Entreprise as a resource:
# config/api_platform/resources.yaml
resources:
AurelBichop\RechercheEntreprisesBundle\Entity\Entreprise:
collectionOperations:
search: { method: 'GET', path: '/entreprises/search/{query}' }
$client->search('query')->then(function (SearchResult $result) {
$bus->dispatch(new EnterpriseSearchCompleted($result));
});
Extend the default timeout or add custom headers:
# config/packages/aurelbichop_recherche_entreprises.yaml
aurel_bichop_recherche_entreprises:
timeout: 15
headers:
X-Custom-Header: "value"
Rate Limiting
$cache = new \Symfony\Component\Cache\Adapter\FilesystemAdapter();
$cachedResult = $cache->get('entreprise_' . $siren, function() use ($client, $siren) {
return $client->findBySiren($siren);
});
SIREN Validation
null for invalid SIRENs. Validate manually:
if (!preg_match('/^\d{9}$/', $siren)) {
throw new \InvalidArgumentException("Invalid SIREN format");
}
Pagination Quirks
per_page max is 100. Avoid fetching large datasets in one call.$result->total vs. count($result->results) for partial pages.Deprecation Warnings
$client->getHttpClient()->getEventDispatcher()->addListener(
'response',
function (ResponseEvent $event) {
$this->logger->debug('API Response', ['status' => $event->getResponse()->getStatusCode()]);
}
);
-vvv for verbose output:
php bin/console recherche-entreprise:search "test" -vvv
Custom Responses Transform API responses with a decorator:
class CustomEntrepriseClient implements EntrepriseSearchClientInterface {
public function __construct(private EntrepriseSearchClientInterface $decorated) {}
public function findBySiren(string $siren): ?Entreprise {
$entreprise = $this->decorated->findBySiren($siren);
if ($entreprise) {
$entreprise->setCustomField('my_data', 'value');
}
return $entreprise;
}
}
Register as a service with decorates: aurelbichop_recherche_entreprises.client.
Add New Endpoints Extend the client to support unsupported API endpoints:
class ExtendedEntrepriseClient implements EntrepriseSearchClientInterface {
public function getEstablishments(string $siren): array {
$response = $this->httpClient->request('GET', "/entreprises/$siren/etablissements");
return $this->decodeResponse($response);
}
}
Event Dispatching Trigger events on search/fetch:
$client->search('query')->then(function (SearchResult $result) {
$dispatcher->dispatch(new EnterpriseSearchedEvent($result));
});
$client->batchSearch(['12345', '67890']);
$entreprise = $client->findBySiren($siren);
$details = $entreprise->getSiege()->getAdresse(); // Lazy-loaded
Mockery or PHPUnit’s createMock:
$mockClient = $this->createMock(EntrepriseSearchClientInterface::class);
$mockClient->method('search')->willReturn(new SearchResult([new Entreprise()]));
CommandTester:
$command = new SearchEntrepriseCommand($client);
$commandTester = new CommandTester($command);
$commandTester->execute(['query' => 'test']);
$this->assertStringContainsString('Results:', $commandTester->getDisplay());
How can I help you explore Laravel packages today?