Skip to main content

Toggle_actif

Documentation du module Ajax - Toggle Actif (Framework Medithau)


Sommaire


1. Contexte

Ce module Ajax permet d’activer ou désactiver dynamiquement via une checkbox la valeur booléenne actif d’un enregistrement d’une table.

Cible plusieurs modules métier (Users, Services, Alias, etc.) via un endpoint unique Ajax.


2. Structure des dossiers

/var/www/html/
├── framework/
│   ├── app/
│   │   ├── Core/
│   │   │   └── ModelRegistry.php       # Registre tables → classes modèles
│   │   ├── Modules/
│   │   │   ├── User/                   # Module Utilisateur (exemple)
│   │   │   ├── Service/                # Module Service (exemple)
│   │   │   └── Alias/                  # Module Alias (exemple)
│   │   ├── public/
│   │   │   └── Ajax/
│   │   │       └── toggle_actif.php    # Endpoint Ajax toggle actif
│   │   ├── Templates/
│   │   │   └── partials/
│   │   │       ├── table_header.php
│   │   │       ├── table_partial.php
│   │   │       └── table_footer.php
│   │   └── public/js/
│   │       └── table_helpers.js       # JS gestion toggles, interactions tableau
├── applications/
│   ├── Admin/
│   │   └── Views/
│   │       └── partials/
│   │           └── users_list.php     # Partial tableau utilisateurs
└── vendor/

3. Modèle ORM minimaliste et Registre des modèles

3.1 Classe Model.php

  • Chemin : /framework/app/Core/Model.php
  • Classe abstraite de base pour tous les modèles, ORM minimaliste
  • Fonctions principales :
    • find(id) : récupère un enregistrement par son identifiant
    • all() : récupère tous les enregistrements
    • where(colonne, valeur) : filtre les enregistrements
    • save() : insère ou met à jour un enregistrement
    • delete(force=false) : supprime un enregistrement (soft delete si false)
    • restore() : restaure un enregistrement supprimé logiquement
  • Stockage des données dans un tableau dynamique $attributes
  • Hook beforeSave() pour personnalisation avant sauvegarde
  • Méthode getEnumValues(champ) récupérant les valeurs ENUM SQL
  • Utilise PDO singleton via classe Database

3.2 Registre ModelRegistry.php

  • Chemin : /framework/src/Core/ModelRegistry.php
  • Tableau statique associant noms de tables aux classes modèles PHP
  • Exemple de mapping :
    • core_utilisateurs => \App\Modules\User\Models\Utilisateur::class
    • core_services => \Apps\Admin\Models\Service::class
    • core_alias => \Apps\Dashboard\Models\Alias::class
  • Méthode statique getModelClass(string $table): ?string pour récupérer la classe modèle
  • Unifie la résolution des modèles dans tout le framework

3.3 Exemple d’utilisation

$modelClass = ModelRegistry::getModelClass('core_utilisateurs');
if ($modelClass && class_exists($modelClass)) {
    $record = $modelClass::find(42);
    // Traitement ...
}

# 4. Architecture des partials pour affichage dynamique des tableaux

## 4.1 Objectif

- Factoriser l’affichage des tableaux HTML via des partials PHP réutilisables
- Permettre une génération dynamique des colonnes et lignes à partir des données passées
- Gestion des colonnes spéciales comme `actif` (checkbox toggle) et `deleted_at` (soft delete)
- Intégration facile dans les vues métier (ex: utilisateurs, services, alias)

## 4.2 Structure des partials

### 4.2.1 `table_header.php`

- Affiche l’en-tête du tableau, incluant :
  - Le titre du tableau
  - Les boutons d’action (ajouter, exporter, switch pour afficher éléments supprimés)
- Détecte automatiquement si la table possède les colonnes `actif` et `deleted_at`
- Génère le switch iOS style pour afficher/masquer les éléments supprimés
- Exemple d’appel :

```php
<?php
$titre = "Liste des utilisateurs";
$btnAdd = '<button class="btn" title="Ajouter"><i class="fas fa-plus"></i></button>';
$btnExport = '<button class="btn" title="Exporter"><i class="fas fa-file-export"></i></button>';

require 'table_header.php';
?>

4. Architecture des partials pour affichage dynamique des tableaux

4.1 Objectif

  • Factoriser l’affichage des tableaux HTML via des partials PHP réutilisables
  • Permettre une génération dynamique des colonnes et lignes à partir des données passées
  • Gestion des colonnes spéciales comme actif (checkbox toggle) et deleted_at (soft delete)
  • Intégration facile dans les vues métier (ex: utilisateurs, services, alias)

4.2 Structure des partials

4.2.1 table_header.php

  • Affiche l’en-tête du tableau, incluant :
    • Le titre du tableau
    • Les boutons d’action (ajouter, exporter, switch pour afficher éléments supprimés)
  • Détecte automatiquement si la table possède les colonnes actif et deleted_at
  • Génère le switch iOS style pour afficher/masquer les éléments supprimés

Exemple d’appel :

<?php
$titre = "Liste des utilisateurs";
$btnAdd = '<button class="btn" title="Ajouter"><i class="fas fa-plus"></i></button>';
$btnExport = '<button class="btn" title="Exporter"><i class="fas fa-file-export"></i></button>';

require 'table_header.php';
?>

4.2.2 table_partial.php

  • Génère le corps complet du tableau HTML <table>
  • Affiche dynamiquement les colonnes passées en paramètre sous forme d’array ['champ' => 'Libellé']
  • Affiche une checkbox dans la colonne actif si présente dans les données
  • Affiche les boutons d’action (modifier, supprimer, restaurer) selon le mode (actif/supprimé)
  • Gère l’absence de données avec un message « Aucun enregistrement »

Exemple d’appel :

<?php
$colonnes = [
    'login' => 'Login',
    'email' => 'Email',
    // autres colonnes...
];
$lignes = $utilisateurs;

require 'table_partial.php';
?>

4.2.3 table_footer.php

  • Partial simple fermant le conteneur du tableau (ex: fermeture de div)
  • Permet d’encapsuler proprement l’ensemble

4.3 Utilisation dans les vues métier

  • Exemple dans users_list.php :
<?php
// Variables $colonnes et $lignes définies en amont
$colonnes = [
    'login'      => 'Login',
    'first_name' => 'Prénom',
    'last_name'  => 'Nom',
    'email'      => 'Email',
    'role'       => 'Rôle'
];
$lignes = $utilisateurs;

?>

<div class="table-block">
    <?php
    require 'table_header.php';
    require 'table_partial.php';
    require 'table_footer.php';
    ?>
</div>
  • Ce principe permet de réutiliser la même structure pour d’autres entités (services, alias, etc.) en adaptant seulement les données $colonnes et $lignes. content = """

5. JavaScript (JS) et AJAX

5.1 Fichier principal : table_helpers.js

  • Situé dans : /framework/app/public/js/table_helpers.js
  • Rôle : gérer les interactions spécifiques aux tableaux comme toggle actif, suppression, édition.
  • Séparation nette avec helpers.js (fonctions génériques réutilisables ailleurs).
  • Exemple : fonction initToggleActive() gère la bascule de l’état actif sur checkbox avec requête AJAX.

5.2 Fonctionnalités JS abordées

  • Toggle actif (activation/désactivation)
  • Actions modifiables (boutons modifier, valider, annuler)
  • Suppression (avec confirmation)
  • Requête AJAX sécurisée avec token CSRF
  • Gestion des erreurs et retours utilisateur

5.3 Détail du code (extrait toggle actif)

function initToggleActive() {
    if (window.toggleActiveInitialized) return;
    window.toggleActiveInitialized = true;

    document.querySelectorAll('.toggle-actif').forEach(checkbox => {
        checkbox.addEventListener('change', function () {
            const row = this.closest('tr');
            const id = row.dataset.id;
            const actif = this.checked;

            fetch('/ajax/toggle_actif.php', {
                method: 'POST',
                credentials: 'include',
                headers: {
                    'Content-Type': 'application/json',
                    'X-CSRF-TOKEN': getCsrfToken()
                },
                body: JSON.stringify({
                    id: id,
                    actif: actif,
                    table: row.dataset.table
                })
            })
            .then(response => response.json())
            .then(data => {
                if (!data.success) {
                    alert('Erreur : ' + data.message);
                    checkbox.checked = !actif; // revert
                }
            })
            .catch(() => {
                alert('Erreur réseau');
                checkbox.checked = !actif; // revert
            });
        });
    });
}