Export MySQL vers CSV

    Publié le : 29-10-2019 16:25

    Introduction

    L'objectif de cet article est d'expliqué comment à partir d'une requête MySQL exécutée avec l'objet PDO, convertir le tableau associatif en fichier CSV encodé en UTF-8. Cette technique permet d'extraire et d'exporter des données CSV parfaitement exploitable pour des traitements automatisés ou des migrations sur d'autres applications.

    Prérequis :

    Je ne m'attarderais pas sur l'utilisation de l'objet PDO traité dans un article précédent Voir Objet PDO. Ni sur la compréhension de la reflection.

    La classe Export CSV :

    L'intérêt de cette classe et de centraliser à un seul et même endroit la méthode d'export des jeux de données en CSV. Elle couvre également la possibilité le formater ou de transcoder les données d'entrée (voir la méthode static Format_Value). À noter que cette dernière est optionnelle et peut très bien être supprimée.

    <?php
        namespace Export;
    
        class Csv{
    		const SPLIT_COLUMN = ';';
    		const BOM_UTF8 = "\xEF\xBB\xBF";
    
            /**
             * Convertie la datatable en fichier CSV
    		 *  @param array[] $in_Data_Table le résultat de la requête
    		 *  @param string $in_Path_File l'emplacement du fichier de sortie (incluant nom et extension)
    		 *  @param array $in_Columns (le tableau des colonnes attendues, permet de définir l'ordre restitution)
    		 *  @return array[] $in_Column_Format (tableau bi dimensionel ex : array('champ' => array(STD_CLASS => 'maClass', METHOD => 'maMethod'))
             */
            public static function Write_File($in_Data_Table,$in_Path_File,$in_Columns,$in_Column_Format){
                try{
    
    				//Création (OU écrasement) du fichier
    				$file = fopen($in_Path_File, 'w');
    
    				//Ecriture du BOM (défaut utf-8)
    				fwrite($file, self::BOM_UTF8);
    
    				//Ecriture des en têtes
    				fputcsv($file, $in_Columns,self::SPLIT_COLUMN);
    
    				//Parcours la datatable
    				foreach ($in_Data_Table as $Data_Row) {
    					$row = array();
    
    					//Pour toutes les colonnes attendues exclusivement
    					foreach ($in_Columns as $Col_Name) {
    						//Valeur brute
    						$tmpValue = self::Get_Value($Data_Row,$Col_Name);
    
    						//Transcodage / Formatage
    						$row[] = self::Format_Value($Col_Name,$tmpValue,$in_Column_Format);
    					}
    
    					//Ecriture de la ligne
    					fputcsv($file, $row,self::SPLIT_COLUMN);
    
    					unset($row);
    				}
    
    				unset($in_DataTable);
    
    				return true;
                }
                catch(Exception $e){
                    throw $e;
                }
            }
    
            /**
    		 * retourne la valeur du tableau associatif passé en paramètre par rapport à la clef soumise (si introuvable,retourne vide)
    		 * @param array $in_Data (la datarow retournée par le sql)
    		 * @param string $in_Column_Name  (le nom de la colonne souhaitée)
    		 * @return string (valeur ou valeur empty, si nom de la colonne non trouvé)
    		 */
    		private static function Get_Value($in_Data,$in_Column_Name){
    			try{
    				return isset($in_Data[$in_Column_Name]) ? stripslashes($in_Data[$in_Column_Name]) : '';
    			}
    			catch(Exception $e){
                    throw $e;
                }
            }
    
             /**
    		 * appel la méthode static de la classe spécifiée avec pour paramètre la valeur du champ
    		 * @param string $in_Column_Name (le nom de la colonne concernée)
    		 * @return string $in_Data (la valeur à traiter)
    		 * @return array[] $in_Columns_Format (tableau bi dimensionel ex : array('champ' => array(self::C => 'maClass', self::M => 'maMethod'))
    		 * @return string
    		 */
    		private static function Format_Value($in_Column_Name,$in_Data,$in_Columns_Format){
    			try{
    				if(!isset($in_Columns_Format[$in_Column_Name])){ return $in_Data; } //Pas de traitement
    
    				$arrParams = $in_Columns_Format[$in_Column_Name];
    				$nameClass = $arrParams["class"];	//Nom de la classe
    				$nameMethod = $arrParams["method"]; //Nom de la méthode
    				$argsMethod = array($in_Data); //Liste des paramètres de la méthode
    
    				$reflectionClass = new \ReflectionClass($nameClass);
    				$dynamicClass = $reflectionClass->newInstanceArgs();
    
    				$methodArguments = $argsMethod;
    				$reflectionMethod = new \ReflectionMethod($dynamicClass, $nameMethod);
    
    				if(!$reflectionMethod->isStatic()){ throw new \Exception("La méthode " . $nameMethod  . " de la classe : " . $nameClass . " n'est pas static."); }
    
    				return $reflectionMethod->invokeArgs($dynamicClass, $methodArguments);
    			}
    			catch(Exception $e){
    				throw $e;
    			}
    		}
        }
    
    
    
    ?>

    L'utilisation :

    <?php
    			//Paramètrage de la requête 
    		    $Requete = "SELECT id,email FROM clients WHERE statut =:actif";
    			$Params = array("actif"=>1);
    			
    			//Préparation de la requête 
    			$Req = $this->Obj_PDO->prepare($Requete);
    			
    			//Execution de la requête préparée
    			$Req->execute($Params);
    			$Datatable = $Req->fetchAll();
    			
    			//Préparation des colonnes souhaitées dans le fichier CSV
    			$Columns =  array(
    	 			"id","email"
    	 		);
    			//Couple classe/méthode pour formater les données d'entrées
    	 		$Columns_Format = array(
    										'id' => array("class" => 'security', "method" => 'int'),
    										'email' => array("class" => 'security', "method" => 'email')
    									);
    			
    			//Emplacement du fichier de sortie			
    			$Path_File = "Emails.csv";
    			
    			//Appel de la classe CSV
    			if(Export\Csv::Write_File($Datatable,$Path_File,$Columns,$Columns_Format)){
    				//Contrôle que le fichier existe 
    				if(!file_exists($Path_File){
    					throw new \Exception("Le fichier n'éxiste pas");
    				}
    				else{
    					echo "traitement terminé";
    				}
    			}
    ?>