amsom-habitat/oracle-function-calling

Bibliothèque PHP pour faciliter l'appel de fonctions et procédures stockées Oracle via Doctrine. Supporte les paramètres CLOB volumineux et la gestion de fichiers base64.

Maintainers

Package info

gitlab.com/amsom-package/oraclefunctioncalling

Issues

pkg:composer/amsom-habitat/oracle-function-calling

Statistics

Installs: 10 748

Dependents: 0

Suggesters: 0

Stars: 0

v2.6.2 2026-03-30 10:45 UTC

README

PHP Symfony

Bibliothèque PHP pour simplifier les appels aux fonctions et procédures Oracle via Doctrine, avec support avancé des CLOB, BLOB et compression automatique des PDFs.

🚀 Fonctionnalités

  • Appels simples : Fonctions Oracle en une ligne
  • CLOB volumineux : Découpage automatique jusqu'à 50 MB
  • Fichiers base64 : Conversion automatique vers BLOB Oracle
  • Compression PDF : Réduction automatique vers une taille cible (nouveau !)
  • Gestion des erreurs : Rollback automatique et exceptions structurées
  • Réponses HTTP : Génération automatique de Response Symfony

📦 Installation

composer require amsom-habitat/oracle-function-calling

Configuration rapide

Symfony

services:
    AmsomUtilities\OracleFunctionCalling: ~
    # ou avec options
    AmsomUtilities\OracleFunctionCalling:
        arguments:
            $managerRegistry: '@doctrine'
            $fileMaxSize: 10485760 # 10MB par défaut

Variable d'environnement

FILE_MAX_SIZE=10485760

Exemples d'utilisation

📦 Installation

composer require amsom-habitat/oracle-function-calling

⚙️ Configuration

Configuration Symfony (services.yaml)

Configuration de base :

services:
    AmsomUtilities\OracleFunctionCalling:
        arguments:
            $managerRegistry: '@doctrine'

Configuration complète (recommandé) :

services:
    AmsomUtilities\OracleFunctionCalling:
        arguments:
            $managerRegistry: '@doctrine'
            $fileMaxSize: '%env(int:FILE_MAX_SIZE)%'
            $apiDocumentUrl: '%env(API_DOCUMENT_URL)%'

Variables d'environnement

# Taille maximale des fichiers (10 MB par défaut)
FILE_MAX_SIZE=10485760

# URL de l'API Document pour la compression PDF (optionnel)
API_DOCUMENT_URL=http://api_document

Configuration programmatique

$oracleCaller = new OracleFunctionCalling(
    $managerRegistry,
    20971520,  // 20 MB max
    'https://api-document.example.com'
);

// Ou avec chaînage
$oracleCaller
    ->setFileMaxSize(10 * 1024 * 1024)
    ->setApiDocumentUrl('https://api-document.example.com');

🎯 Utilisation

1. Appel simple

Pour les fonctions Oracle standard retournant une chaîne :

// Appel basique
$result = $oracleCaller->call(
    'MY_PACKAGE.MY_FUNCTION',
    "'param1', 123, 'param2'"
);

// Résultat
echo $result; // {"data": {"id": 123, "status": "success"}}

Avec rollback automatique en cas d'erreur :

$result = $oracleCaller->call(
    'MY_PACKAGE.CREATE_USER',
    "'john.doe', 'john@example.com'",
    rollbackIfFail: true  // Rollback si exception
);

2. Appel avec CLOB volumineux

Pour passer de grandes chaînes (JSON, XML, textes > 32 000 caractères) :

$largeData = json_encode($bigArray);  // Peut faire plusieurs MB

$result = $oracleCaller->largeCall(
    'MY_PACKAGE.PROCESS_DATA',
    "'user123', 'action'",     // Paramètres AVANT le CLOB
    $largeData,                 // Le CLOB volumineux
    "'additionalParam'"         // Paramètres APRÈS (optionnel)
);

Note : Les virgules de séparation sont gérées automatiquement.

3. Appel avec fichier (BLOB)

Pour envoyer des fichiers encodés en base64 :

$base64File = base64_encode(file_get_contents('document.pdf'));

$result = $oracleCaller->fileCall(
    'MY_PACKAGE.SAVE_DOCUMENT',
    "'DOC123', 'john.doe', 'document.pdf'",
    $base64File
);

// Vérifier les erreurs de taille
$decoded = json_decode($result);
if (isset($decoded->error)) {
    // Le fichier dépasse la limite autorisée
}

4. Génération de réponse HTTP

Convertit automatiquement le résultat Oracle en Response Symfony :

public function createAction(Request $request): Response
{
    $result = $this->oracleCaller->call(
        'MY_PACKAGE.CREATE_ITEM',
        "'param1', 'param2'"
    );
    
    // Retourne HTTP 201 si succès, 400 si erreur
    return $this->oracleCaller->handleResult($result, Response::HTTP_CREATED);
}

Convention Oracle obligatoire :

Succès : JSON avec propriété data

{"data": {"id": 123, "message": "Créé avec succès"}}

Erreur : JSON sans data

{"error": "Message d'erreur", "code": "ERR_001"}

🗜️ Compression automatique des PDFs

La fonctionnalité de compression PDF permet de réduire automatiquement la taille des fichiers PDF avant leur envoi à Oracle.

Configuration

# URL de l'API Document
API_DOCUMENT_URL=http://api_document

Utilisation par défaut

Détection et compression automatiques :

// Le PDF sera automatiquement détecté et compressé vers 1 MB
$result = $oracleCaller->fileCall(
    'SAVE_DOCUMENT',
    "'DOC123', 'contract.pdf'",
    $pdfBase64
);

Options de compression

$options = [
    'mimeType' => 'application/pdf',    // Force la détection PDF
    'compressPdf' => true,               // Active/désactive (défaut: true)
    'targetSize' => 500000               // Taille cible en octets (défaut: 1 Mo)
];

$result = $oracleCaller->fileCall(
    'SAVE_DOCUMENT',
    "'DOC123', 'contract.pdf'",
    $pdfBase64,
    "",  // params after
    $options
);

Exemples pratiques

Documents d'archive (compression maximale) :

$result = $oracleCaller->fileCall(
    'ARCHIVE_DOCUMENT',
    "'DOC_OLD', 'archive.pdf'",
    $pdfBase64,
    "",
    ['targetSize' => 300000]  // Compresse vers 300 KB
);

Documents légaux (haute qualité) :

$result = $oracleCaller->fileCall(
    'SAVE_LEGAL_DOC',
    "'DOC_LEGAL', 'contract.pdf'",
    $pdfBase64,
    "",
    ['targetSize' => 2000000]  // Compresse vers 2 MB (qualité préservée)
);

Désactiver la compression :

$result = $oracleCaller->fileCall(
    'SAVE_DOCUMENT',
    "'DOC123', 'signature.pdf'",
    $pdfBase64,
    "",
    ['compressPdf' => false]  // Pas de compression
);

Détection automatique des PDFs

La compression s'active uniquement pour les PDFs, détectés par :

  1. mimeType explicite : 'application/pdf'
  2. ✅ Préfixe data URI : data:application/pdf;base64,...
  3. ✅ Signature du fichier : Header %PDF

Les autres fichiers (images, Excel, Word) ne sont jamais compressés.

Comportement intelligent

  • Compression non bénéfique : Le fichier original est conservé si la compression ne réduit pas la taille
  • API indisponible : Le fichier original est utilisé avec un log d'avertissement
  • Logs détaillés : Toutes les opérations sont loguées pour le débogage
[OracleFunctionCalling] PDF compressé avec succès - Réduction: 45.32%
[OracleFunctionCalling] Compression non bénéfique, utilisation du fichier original
[OracleFunctionCalling] API_DOCUMENT_URL non configurée, compression désactivée

Tailles cibles recommandées

Cas d'usageTaille cibleDescription
Archives200-500 KBCompression maximale, qualité acceptable
Documents courants500 KB-1 MBBon équilibre qualité/taille (défaut)
Documents importants1-2 MBHaute qualité, bonne compression
Documents légaux2-3 MBQualité maximale, compression légère

📚 Exemples complets

Contrôleur Symfony - Upload de document

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use AmsomUtilities\OracleFunctionCalling;

class DocumentController extends AbstractController
{
    #[Route('/api/documents', methods: ['POST'])]
    public function uploadDocument(
        Request $request,
        OracleFunctionCalling $oracleCaller
    ): Response {
        $data = json_decode($request->getContent(), true);
        
        $options = [
            'mimeType' => $data['mimeType'],
            'targetSize' => 1000000  // 1 MB
        ];
        
        $result = $oracleCaller->fileCall(
            'DOC_PACKAGE.SAVE_DOCUMENT',
            "'{$data['title']}', '{$data['userId']}'",
            $data['fileBase64'],
            "",
            $options
        );
        
        return $oracleCaller->handleResult($result, Response::HTTP_CREATED);
    }
}

Upload multiple avec compression différenciée

#[Route('/api/documents/bulk', methods: ['POST'])]
public function uploadMultiple(
    Request $request,
    OracleFunctionCalling $oracleCaller
): Response {
    $data = json_decode($request->getContent(), true);
    $results = [];
    
    foreach ($data['files'] as $file) {
        // Taille cible selon le type de document
        $targetSize = match($file['category']) {
            'archive' => 300000,      // 300 KB
            'legal' => 2000000,       // 2 MB
            default => 1000000        // 1 MB
        };
        
        $result = $oracleCaller->fileCall(
            'DOC_PACKAGE.SAVE_DOCUMENT',
            "'{$file['title']}', '{$file['category']}'",
            $file['base64'],
            "",
            [
                'mimeType' => $file['mimeType'],
                'targetSize' => $targetSize
            ]
        );
        
        $results[] = json_decode($result);
    }
    
    return $this->json(['data' => $results]);
}

Traitement de données volumineuses

public function processBulkData(array $items): Response
{
    $largeJson = json_encode($items);
    
    $result = $this->oracleCaller->largeCall(
        'BULK_PACKAGE.PROCESS_ITEMS',
        "'user123', 'batch_001'",
        $largeJson
    );
    
    return $this->oracleCaller->handleResult($result, Response::HTTP_OK);
}

Gestion avancée des erreurs

use Symfony\Component\HttpKernel\Exception\HttpException;

public function createUser(Request $request): Response
{
    try {
        $data = json_decode($request->getContent(), true);
        
        $params = sprintf(
            "'%s', '%s', %d",
            addslashes($data['name']),
            addslashes($data['email']),
            $data['age']
        );
        
        $result = $this->oracleCaller->call(
            'USER_PACKAGE.CREATE_USER',
            $params,
            rollbackIfFail: true
        );
        
        return $this->oracleCaller->handleResult($result, Response::HTTP_CREATED);
        
    } catch (HttpException $e) {
        return $this->json([
            'error' => $e->getMessage(),
            'code' => $e->getStatusCode()
        ], $e->getStatusCode());
    }
}

🗄️ Exemples de fonctions Oracle

Fonction simple (retour JSON)

CREATE OR REPLACE FUNCTION MY_PACKAGE.CREATE_USER(
    p_name VARCHAR2,
    p_email VARCHAR2,
    p_age NUMBER
) RETURN VARCHAR2 IS
    v_id NUMBER;
BEGIN
    INSERT INTO users (name, email, age)
    VALUES (p_name, p_email, p_age)
    RETURNING id INTO v_id;
    
    COMMIT;
    
    RETURN '{"data": {"id": ' || v_id || ', "message": "User created"}}';
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        RETURN '{"error": "' || SQLERRM || '"}';
END;

Fonction avec CLOB

CREATE OR REPLACE FUNCTION MY_PACKAGE.PROCESS_BULK_DATA(
    p_user_id VARCHAR2,
    p_batch_id VARCHAR2,
    p_json_data CLOB
) RETURN VARCHAR2 IS
    v_count NUMBER := 0;
BEGIN
    -- Traiter le CLOB (parsing JSON, insertion multiple, etc.)
    -- ... votre logique ici ...
    
    COMMIT;
    
    RETURN '{"data": {"processed": ' || v_count || ', "batch": "' || p_batch_id || '"}}';
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        RETURN '{"error": "' || SQLERRM || '", "code": "BULK_ERROR"}';
END;

Fonction avec fichier (BLOB)

CREATE OR REPLACE FUNCTION DOC_PACKAGE.SAVE_DOCUMENT(
    p_title VARCHAR2,
    p_user_id VARCHAR2,
    p_file_size NUMBER,
    p_file_blob BLOB
) RETURN VARCHAR2 IS
    v_doc_id VARCHAR2(50);
BEGIN
    v_doc_id := SYS_GUID();
    
    INSERT INTO documents (id, title, user_id, file_data, file_size, created_at)
    VALUES (v_doc_id, p_title, p_user_id, p_file_blob, p_file_size, SYSDATE);
    
    COMMIT;
    
    RETURN '{"data": {"documentId": "' || v_doc_id || '", "size": ' || p_file_size || '}}';
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        RETURN '{"error": "' || SQLERRM || '"}';
END;

🔧 Configuration avancée

Constantes disponibles

OracleFunctionCalling::CLOB_CHUNK_SIZE        // 32000 caractères (32 KB)
OracleFunctionCalling::RESPONSE_SIZE          // 4000 caractères (4 KB)
OracleFunctionCalling::DEFAULT_FILE_MAX_SIZE  // 10485760 octets (10 MB)

Limites et performance

TypeLimite par défautConfigurableConsommation mémoire
Réponse Oracle4 KB❌ ConstanteFaible
Fichiers (base64)10 MB✅ Oui~40-50 MB / 10 MB fichier
CLOBIllimitée✅ OptionnelVariable selon taille

Recommandations PHP :

# php.ini
memory_limit = 256M          # Minimum recommandé
max_execution_time = 60      # Pour gros fichiers
post_max_size = 20M
upload_max_filesize = 20M

Méthodes utilitaires

// Récupérer les configurations
$maxSize = $oracleCaller->getFileMaxSize();        // int
$apiUrl = $oracleCaller->getApiDocumentUrl();      // string|null

// Modifier dynamiquement
$oracleCaller
    ->setFileMaxSize(20 * 1024 * 1024)             // 20 MB
    ->setApiDocumentUrl('https://api.example.com');

⚠️ Gestion des erreurs

Toutes les méthodes peuvent lever une HttpException :

use Symfony\Component\HttpKernel\Exception\HttpException;

try {
    $result = $oracleCaller->call('MY_FUNCTION', "'param'");
} catch (HttpException $e) {
    // $e->getStatusCode() => 500
    // $e->getMessage() => Message d'erreur Oracle
    
    logger->error('Oracle call failed', [
        'function' => 'MY_FUNCTION',
        'error' => $e->getMessage()
    ]);
}

Codes HTTP retournés :

  • 500 : Erreur Oracle (syntaxe SQL, contrainte, exception PL/SQL)
  • 400 : Erreur métier (retournée par handleResult() si JSON sans data)
  • 413 : Fichier trop volumineux (dépasse FILE_MAX_SIZE)

🧪 Tests & Débogage

Vérifier la configuration

// Dans un contrôleur ou commande Symfony
public function debug(OracleFunctionCalling $oracleCaller): void
{
    dump([
        'fileMaxSize' => $oracleCaller->getFileMaxSize(),
        'apiDocumentUrl' => $oracleCaller->getApiDocumentUrl(),
    ]);
}

Logs de compression PDF

# Rechercher les logs de compression
tail -f var/log/prod.log | grep "OracleFunctionCalling"

# Exemples de logs
[OracleFunctionCalling] PDF compressé avec succès - Réduction: 45.32%
[OracleFunctionCalling] Compression non bénéfique, utilisation du fichier original
[OracleFunctionCalling] API_DOCUMENT_URL non configurée, compression désactivée
[OracleFunctionCalling] Erreur API compression PDF (HTTP 500): ...

Tester la compression manuellement

curl -X POST http://api_document/compress_pdf_target_base64 \
  -H "Content-Type: application/json" \
  -d '{
    "pdfContent": "JVBERi0xLjQKJ...",
    "targetSize": 1000000,
    "maxQuality": 70,
    "minQuality": 20
  }'

📖 Documentation complémentaire

🤝 Support

Pour toute question ou problème :

  1. Consulter les logs de l'application
  2. Vérifier la configuration Symfony et les variables d'environnement
  3. Tester les fonctions Oracle directement via SQL Developer
  4. Contacter l'équipe de développement

📄 Licence

Propriétaire - AMSOM Habitat

🔄 Changelog

v2.0.0 (2026-03-30)

  • ✨ Ajout de la compression automatique des PDFs par taille cible
  • ✨ Support du paramètre options dans fileCall
  • ✨ Détection automatique des PDFs (3 méthodes)
  • ✅ Gestion intelligente des erreurs de compression
  • 📝 Documentation complète avec exemples pratiques

v1.x.x

  • Gestion des CLOB et BLOB
  • Appels simples de fonctions Oracle
  • Support Symfony

      "'%s', '%s', %d",
      addslashes($data['name']),
      addslashes($data['email']),
      $data['age']
    

    );

    $result = $this->oracleCaller->call('USER_PACKAGE.CREATE_USER', $params); return $this->oracleCaller->handleResult($result, Response::HTTP_CREATED); }

    
    

Upload de fichier

public function uploadDocument(Request $request): Response
{
    $data = json_decode($request->getContent(), true);
    
    $result = $this->oracleCaller->fileCall(
        'GED_PACKAGE.SAVE_DOCUMENT',
        "'{$data['documentId']}', '{$data['user']}', '{$data['filename']}'",
        $data['fileBase64'],
        ""
    );
    
    // Vérifier erreur de taille
    $decoded = json_decode($result);
    if (isset($decoded->error)) {
        return new Response($result, Response::HTTP_REQUEST_ENTITY_TOO_LARGE);
    }
    
    return $this->oracleCaller->handleResult($result, Response::HTTP_CREATED);
}

Traitement de données volumineuses

public function processBulkData(array $items): Response
{
    $largeJson = json_encode($items); // Peut dépasser 32000 caractères
    
    $result = $this->oracleCaller->largeCall(
        'DATA_PACKAGE.PROCESS_BULK',
        "'batch_001', 'import'",
        $largeJson,
        "'user@example.com'"
    );
    
    return $this->oracleCaller->handleResult($result, Response::HTTP_OK);
}

Hiérarchie de configuration

La taille maximale des fichiers est déterminée dans cet ordre (priorité décroissante) :

  1. Valeur passée au constructeur
  2. Variable d'environnement FILE_MAX_SIZE
  3. Valeur par défaut (10MB)

Prérequis

  • PHP >= 8.0
  • Doctrine ORM >= 2.13 ou >= 3.0
  • Symfony HttpFoundation >= 5.4
  • Symfony HttpKernel >= 5.4
  • Base de données Oracle avec fonctions PL/SQL configurées

Sécurité

⚠️ Important : Cette bibliothèque construit des requêtes SQL dynamiques.

  • Les noms de fonctions doivent provenir de sources fiables
  • Les paramètres doivent être correctement échappés (utilisez addslashes())
  • Les fonctions Oracle doivent avoir les permissions appropriées
  • Ne passez jamais directement les entrées utilisateur sans validation

Licence

Propriétaire - Amsom Habitat

Auteur : Amsom Habitat