Files
e-ticket/src/Service/MeilisearchService.php
Serreau Jovann 160369f0f6 Add CI pipeline, Meilisearch service, CacheService and code quality tools
- CI: lint, PHPStan, PHP CS Fixer, ESLint, Stylelint, security audit, build
- MeilisearchService: async via Messenger, sync search
- MeilisearchMessage + handler for async operations
- CacheService with CacheKey enum (TTL per key, remember pattern)
- Meilisearch env vars in .env.local, vault and env.local.j2
- Messenger routing for MeilisearchMessage
- PHPStan level 6, ESLint, Stylelint configs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:08:54 +01:00

107 lines
3.4 KiB
PHP

<?php
namespace App\Service;
use App\Message\MeilisearchMessage;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class MeilisearchService
{
public function __construct(
private HttpClientInterface $httpClient,
private MessageBusInterface $bus,
#[Autowire(env: 'MEILISEARCH_URL')] private string $url,
#[Autowire(env: 'MEILISEARCH_API_KEY')] private string $apiKey,
) {}
public function indexExists(string $index): bool
{
try {
$response = $this->httpClient->request('GET', $this->url . "/indexes/{$index}", [
'headers' => ['Authorization' => "Bearer {$this->apiKey}"],
]);
return $response->getStatusCode() === 200;
} catch (\Throwable) {
return false;
}
}
public function createIndexIfNotExists(string $index, string $primaryKey = 'id'): void
{
if (!$this->indexExists($index)) {
$this->createIndex($index, $primaryKey);
}
}
public function createIndex(string $index, string $primaryKey = 'id'): void
{
$this->bus->dispatch(new MeilisearchMessage('createIndex', $index, ['primaryKey' => $primaryKey]));
}
public function deleteIndex(string $index): void
{
$this->bus->dispatch(new MeilisearchMessage('deleteIndex', $index));
}
public function addDocuments(string $index, array $documents): void
{
$this->bus->dispatch(new MeilisearchMessage('addDocuments', $index, ['documents' => $documents]));
}
public function updateDocuments(string $index, array $documents): void
{
$this->bus->dispatch(new MeilisearchMessage('updateDocuments', $index, ['documents' => $documents]));
}
public function deleteDocument(string $index, string|int $documentId): void
{
$this->bus->dispatch(new MeilisearchMessage('deleteDocument', $index, ['documentId' => $documentId]));
}
public function deleteDocuments(string $index, array $ids): void
{
$this->bus->dispatch(new MeilisearchMessage('deleteDocuments', $index, ['ids' => $ids]));
}
public function updateSettings(string $index, array $settings): void
{
$this->bus->dispatch(new MeilisearchMessage('updateSettings', $index, ['settings' => $settings]));
}
public function search(string $index, string $query, array $options = []): array
{
return $this->request('POST', "/indexes/{$index}/search", array_merge([
'q' => $query,
], $options));
}
public function getDocument(string $index, string|int $documentId): array
{
return $this->request('GET', "/indexes/{$index}/documents/{$documentId}");
}
public function request(string $method, string $path, ?array $body = null): array
{
$options = [
'headers' => [
'Authorization' => "Bearer {$this->apiKey}",
'Content-Type' => 'application/json',
],
];
if ($body !== null && $method !== 'GET' && $method !== 'DELETE') {
$options['json'] = $body;
}
$response = $this->httpClient->request($method, $this->url . $path, $options);
if ($response->getStatusCode() === 204) {
return [];
}
return $response->toArray(false);
}
}