L'intégration de l'exportation de données au format Excel dans un projet ThinkPHP peut être efficacement réalisée en utilisant la bibliothèque PHPExcel. Voici une approche structruée pour implémenter cette fonctionnalité tout en maintenant une architecture propre.
1. Installation de la dépendance
La première étape consiste à obtenir la bibliothèque PHPExcel et à la placer dans le répertoire vendor de votre projet ThinkPHP. Cela permet au framework de charger automatiquement les classes nécessaires via sa fonction d'auto-chargement.
2. Création du service d'exportation
Pour favoriser la réutilisabilité, il est recommandé d'encapsuler la logique de génération du fichier Excel et la configuration des en-têtes HTTP dans une classe de service dédiée.
class ExcelExportService
{
public function generateAndDownload(array $columns, array $dataset, string $filename = 'export'): void
{
vendor('phpExcel.PHPExcel');
$spreadsheet = new \PHPExcel();
$activeSheet = $spreadsheet->getActiveSheet();
// Écriture des en-têtes de colonnes
foreach ($columns as $colLetter => $colInfo) {
$activeSheet->setCellValue($colLetter . '1', $colInfo[1]);
}
// Remplissage des lignes de données
$rowIndex = 2;
foreach ($dataset as $rowData) {
foreach ($columns as $colLetter => $colInfo) {
$fieldKey = $colInfo[0];
$cellValue = $rowData[$fieldKey] ?? '';
$activeSheet->setCellValue($colLetter . $rowIndex, $cellValue);
}
$rowIndex++;
}
// Configuration des en-têtes HTTP pour le téléchargement
$this->sendDownloadHeaders($filename);
$writer = new \PHPExcel_Writer_Excel5($spreadsheet);
$writer->save('php://output');
exit;
}
private function sendDownloadHeaders(string $filename): void
{
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment; filename="' . $filename . '.xls"');
header('Content-Transfer-Encoding: binary');
}
}
3. Appel depuis le contrôleur métier
Dans votre contrôleur, vous devez récupérer les données depuis la base de données, appliquer les transformations nécessaires (comme le formatage des montants ou le nettoyage des caractères spéciaux), définir la correspondance des colonnes, puis invoquer le service d'exportation.
class TransactionController
{
public function exportRechargeRecords()
{
// Récupération des données de transaction avec jointures
$records = Db::name('transactions')
->alias('t')
->join('user u', 't.user_id = u.id')
->join('ktv k', 't.ktv_id = k.id')
->field('t.id, t.user_id, u.name as uname, t.created, t.order_id, t.price, t.coins, t.device_id, t.ktv_id, k.name as kname, t.status')
->order('t.id desc')
->select();
// Nettoyage et formatage des données
$cleanedRecords = array_map(function($record) {
$record['price'] = number_format($record['price'] / 100, 2, '.', '');
$record['uname'] = $this->removeEmoji($record['uname']);
return $record;
}, $records);
// Définition de la structure du tableau Excel
$columnMapping = [
'A' => ['id', 'ID'],
'B' => ['user_id', 'ID Utilisateur'],
'C' => ['uname', 'Nom Utilisateur'],
'D' => ['created', 'Date'],
'E' => ['order_id', 'Numéro de Commande'],
'F' => ['price', 'Montant (€)'],
'G' => ['coins', 'Pièces Rechargées'],
'H' => ['device_id', 'ID Appareil'],
'I' => ['ktv_id', 'ID KTV'],
'J' => ['kname', 'Nom KTV'],
'K' => ['status', 'Statut']
];
$exportService = new ExcelExportService();
$exportService->generateAndDownload($columnMapping, $cleanedRecords, 'recharges_' . date('Y-m-d'));
}
private function removeEmoji($string) {
return preg_replace('%(?:\xF0[\x90-\xBF][\x80-\xBF]{2}|\xF1[\x80-\xBF][\x80-\xBF]{2}|[\xF2-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})%xs', '', $string);
}
}