# Backend PHP - SQL Support Training

Backend PHP pour la plateforme e-learning Oracle SQL/PL/SQL avec connexion Oracle via OCI8.

## Structure du projet

```
api/
├── config/
│   └── database.php       # Classe de connexion Oracle (OCI8)
├── execute.php            # API pour exécuter des requêtes SQL
├── validate.php           # API pour valider les exercices
├── init-data.php          # Script d'initialisation du jeu de données
└── README.md              # Ce fichier
```

## Prérequis

### 1. Oracle Database

Vous devez avoir Oracle Database installé et en cours d'exécution :
- **Oracle Database XE** (Express Edition) - Recommandé pour le développement
- **Oracle Database Standard/Enterprise** - Pour la production

Téléchargement : https://www.oracle.com/database/technologies/xe-downloads.html

### 2. Extension PHP OCI8

L'extension OCI8 doit être activée dans PHP pour se connecter à Oracle.

#### Sur Windows (WAMP) :

1. Télécharger **Oracle Instant Client** :
   - Aller sur : https://www.oracle.com/database/technologies/instant-client/downloads.html
   - Télécharger "Instant Client Basic" pour Windows (64-bit)
   - Extraire dans `C:\oracle\instantclient_XX_X`

2. Configurer les variables d'environnement :
   - Ajouter le chemin Instant Client au PATH système
   - Exemple : `C:\oracle\instantclient_21_3`

3. Activer l'extension OCI8 dans PHP :
   - Ouvrir `php.ini` (via WAMP > PHP > php.ini)
   - Décommenter la ligne : `extension=oci8_12c`
   - Redémarrer WAMP

4. Vérifier l'installation :
   ```bash
   php -m | grep oci8
   ```

#### Sur Linux :

```bash
# Installer Oracle Instant Client
sudo apt-get install libaio1
wget https://download.oracle.com/otn_software/linux/instantclient/...
unzip instantclient-basic-linux.x64-21.1.0.0.0.zip
sudo mv instantclient_21_1 /opt/oracle/

# Installer l'extension OCI8
sudo pecl install oci8
echo "extension=oci8.so" | sudo tee /etc/php/8.1/mods-available/oci8.ini
sudo phpenmod oci8
sudo systemctl restart apache2
```

## Installation

### Étape 1 : Configuration de la base de données Oracle

1. Se connecter à Oracle en tant que SYSDBA :
   ```sql
   sqlplus sys as sysdba
   ```

2. Créer l'utilisateur pour l'application :
   ```sql
   CREATE USER SQL_TRAINING IDENTIFIED BY Training2026;
   GRANT CONNECT, RESOURCE, CREATE VIEW, CREATE SEQUENCE TO SQL_TRAINING;
   GRANT UNLIMITED TABLESPACE TO SQL_TRAINING;
   ```

3. Vérifier la création :
   ```sql
   SELECT USERNAME FROM DBA_USERS WHERE USERNAME = 'SQL_TRAINING';
   ```

### Étape 2 : Configuration du fichier .env

Le fichier `.env` a déjà été créé à la racine du projet. Modifiez-le selon votre configuration :

```env
ORACLE_HOST=localhost
ORACLE_PORT=1521
ORACLE_SID=XE
ORACLE_USER=SQL_TRAINING
ORACLE_PASSWORD=Training2026
```

### Étape 3 : Initialiser le jeu de données

Exécutez le script d'initialisation via le navigateur ou en ligne de commande :

**Via navigateur :**
```
http://localhost/pack-solutions/api/init-data.php
```

**Via ligne de commande :**
```bash
php c:\wamp64\www\pack-solutions\api\init-data.php
```

Ce script va :
- Créer 6 tables : DEPARTEMENTS, EMPLOYES, PROJETS, AFFECTATIONS, CLIENTS, COMMANDES
- Insérer des données réalistes (22 employés, 40 commandes, etc.)
- Créer des vues pour faciliter les exercices

## Utilisation des APIs

### 1. API Execute - Exécuter une requête SQL

**Endpoint :** `POST /api/execute.php`

**Corps de la requête :**
```json
{
  "sql": "SELECT * FROM EMPLOYES WHERE DEPT_ID = 1"
}
```

**Réponse (succès) :**
```json
{
  "success": true,
  "type": "SELECT",
  "data": [
    {
      "EMPLOYEE_ID": "1",
      "NOM": "Dupont",
      "PRENOM": "Jean",
      ...
    }
  ],
  "rowCount": 5,
  "executionTime": 12.45,
  "message": "5 ligne(s) retournée(s) en 12.45 ms"
}
```

**Réponse (erreur) :**
```json
{
  "success": false,
  "error": "ORA-00942: table or view does not exist",
  "executionTime": 3.21
}
```

### 2. API Validate - Valider un exercice

**Endpoint :** `POST /api/validate.php`

**Corps de la requête :**
```json
{
  "exerciseId": "ex_01",
  "userSql": "SELECT NOM, PRENOM FROM EMPLOYES WHERE DEPT_ID = 1",
  "solutionSql": "SELECT NOM, PRENOM FROM EMPLOYES WHERE DEPT_ID = 1 ORDER BY NOM"
}
```

**Réponse (correct) :**
```json
{
  "success": true,
  "correct": true,
  "message": "Bravo ! Votre requête est correcte.",
  "userRowCount": 5,
  "expectedRowCount": 5,
  "feedback": ["Excellent travail ! Vous maîtrisez bien ce concept."]
}
```

**Réponse (incorrect) :**
```json
{
  "success": true,
  "correct": false,
  "message": "Votre requête ne retourne pas le résultat attendu.",
  "userRowCount": 3,
  "expectedRowCount": 5,
  "differences": [...],
  "feedback": [
    "Votre requête ne retourne pas le bon nombre de lignes.",
    "Vérifiez vos conditions WHERE."
  ]
}
```

## Jeu de données

### Tables créées

1. **DEPARTEMENTS** (6 départements)
   - Informatique, RH, Comptabilité, Marketing, Commercial, R&D

2. **EMPLOYES** (22 employés)
   - Avec hiérarchie (managers, directeurs)
   - Différents salaires, postes, dates d'embauche

3. **PROJETS** (8 projets)
   - Statuts variés : EN_COURS, TERMINE, SUSPENDU

4. **AFFECTATIONS** (15 affectations)
   - Lien entre employés et projets
   - Rôles et heures travaillées

5. **CLIENTS** (12 clients)
   - Clients français et internationaux

6. **COMMANDES** (40 commandes)
   - Différents statuts, montants, remises
   - Historique de janvier à juillet 2024

### Vues créées

1. **V_EMPLOYES_COMPLET**
   - Employés avec département et manager

2. **V_COMMANDES_DETAIL**
   - Commandes avec informations client

3. **V_PROJETS_AFFECTATIONS**
   - Projets avec affectations des employés

## Requêtes de test

```sql
-- Tester la connexion
SELECT * FROM DEPARTEMENTS;

-- Voir tous les employés
SELECT * FROM EMPLOYES;

-- Employés par département
SELECT d.NOM_DEPT, COUNT(*) as NB_EMPLOYES
FROM EMPLOYES e
JOIN DEPARTEMENTS d ON e.DEPT_ID = d.DEPT_ID
GROUP BY d.NOM_DEPT;

-- Commandes par client
SELECT c.NOM_CLIENT, COUNT(*) as NB_COMMANDES, SUM(co.MONTANT_FINAL) as TOTAL
FROM CLIENTS c
JOIN COMMANDES co ON c.CLIENT_ID = co.CLIENT_ID
GROUP BY c.NOM_CLIENT
ORDER BY TOTAL DESC;

-- Utiliser une vue
SELECT * FROM V_EMPLOYES_COMPLET;
```

## Sécurité

### Requêtes interdites

Pour des raisons de sécurité, certaines commandes sont bloquées dans `execute.php` :
- `DROP TABLE` (sauf tables de données)
- `DROP USER`
- `DROP DATABASE`
- `TRUNCATE TABLE` (sauf tables de données)
- `ALTER SYSTEM`
- `SHUTDOWN`
- `GRANT DBA`
- `CREATE USER`

### Bonnes pratiques

1. Ne jamais exposer les credentials Oracle dans le code
2. Utiliser le fichier `.env` (ne pas le commit dans Git)
3. Limiter les privilèges de l'utilisateur SQL_TRAINING
4. Valider et filtrer toutes les entrées utilisateur

## Dépannage

### Erreur : "Call to undefined function oci_connect()"

L'extension OCI8 n'est pas activée. Vérifiez :
```bash
php -m | grep oci8
```

Si absent, suivez les étapes d'installation de l'extension OCI8 ci-dessus.

### Erreur : "ORA-12154: TNS:could not resolve the connect identifier"

Le SID Oracle est incorrect. Vérifiez dans le fichier `.env` :
```env
ORACLE_SID=XE  # Pour Oracle Express Edition
```

### Erreur : "ORA-01017: invalid username/password"

Les credentials sont incorrects. Vérifiez :
1. Le fichier `.env`
2. Que l'utilisateur SQL_TRAINING a bien été créé dans Oracle

### Erreur : "ORA-12541: TNS:no listener"

Oracle Database n'est pas démarré. Démarrez le service Oracle :

**Windows :**
```
services.msc
# Démarrer "OracleServiceXE" et "OracleOraDB19Home1TNSListener"
```

**Linux :**
```bash
sudo systemctl start oracle-xe
```

## Ressources

- [Documentation Oracle Database](https://docs.oracle.com/en/database/)
- [PHP OCI8 Documentation](https://www.php.net/manual/en/book.oci8.php)
- [Oracle Instant Client](https://www.oracle.com/database/technologies/instant-client.html)

## Support

Pour toute question ou problème, consultez :
- Le fichier [CONTEXTE-NOUVEAU.md](../CONTEXTE-NOUVEAU.md) pour le contexte du projet
- Le fichier [claud.md](../claud.md) pour les règles du projet
