But du chapitre
Dans ce chapitre nous allons voir comment adresser la sortie des différents types oracle sous forme de texte (pour ceux qui le sont) et éviter ainsi les sorties troquées des types longs par exemple. Le code qui va être produit ici sera adaptable aux autres types de données par la suite. On se concentre sur les type CLOB et NCLOB.
Une classe pour gérer les résultats de requêtes
Cette classe aura comme propriétés les noms des colonnes, leurs types et le contenu de chaque ligne.
class queryResult { private $types=array(); private $cols=array(); private $lines=array(); /** * Constructeur de classe. * * @param object $cursor * @return queryResult */ function __construct($cursor) { $nbFields=oci_num_fields($cursor); for ($i = 1; $i <= $nbFields; ++$i) { $this->cols[$i-1]=oci_field_name($cursor, $i); $this->types[$i-1]=oci_field_type($cursor, $i); } while ($cRow = oci_fetch_array( $cursor, OCI_NUM+OCI_RETURN_NULLS )) { ... } return($this); } }
C’est dans le constructeur, lors de la pahe de fetch, qu’on va analyser les lignes et les stocker sous forme de tableau de chaînes dans la propriété $lines après avoir pris les informations de type et de noms des colonnes dans les propriétés $cols et $types.Pur ce faire, pour chaque colonne de chaque ligne on va décider de la sortie en fonction du type de l’élément adressé. On crée une fonction privée poru cela, elle pourra être enrichie par la suite pour d’autres types.
/** * transforme un élément d'une ligne ent chaine en fonction de son type * * @param array $row * @param int $i * @return string */ private function tToStr(array $row, int $i): string { switch ( $this->types[$i] ) { case('CLOB'): return $row[$i]->load(); case('NCLOB'): return $row[$i]->load(); case('BLOB'): return 'Binary Lob'; case ('RAW'): return 'Type - RAW'; case ('LONG RAW'): return 'Type - RAW'; default: return $row[$i]; } }
Ensuite oncrée des “getters” pour obtenir un tableau 2D qui pourra être adressé par notre classe table2DOut écrite au chapitre 3. J’en ai écrit un classique, qui redonne un tableau associatif et une autre qui ne donne qu’un tableau dont la première ligne contient le nom de colonnes.
/** * Retourne le tableau du contenu des lignes indexé par les nos de colonnes * * @return array */ function renderAll(): array { $ret=array(); foreach( $this->lines as $line) { $ret[]=array_combine($this->cols, $line); } return $ret ; } /** * Retourne le tableau du contenu avec en ligne 0 les noms des colonnes * * @return array */ function renderHAndD(): array { $ret=$this->lines; array_unshift($ret, $this->cols); return $ret; }
J’ai donc enrichi la classe table2DOut de deux fonctions de sortie pour prendre en compte ce second type de tableau.
/** * Transforme une table PHP à deux dimensions en chaine CSV * * @param array $a * @param string $colSep * @return string */ static function csvHFirstLine (array $a, ? string $colSep = ','): string { return table2DOut::csv($a,FALSE,$colSep); } /** * Transforme une table PHP à deux dimensions dont la première ligne contient * le titres des colonnes, en table HTML * * @param array $a * @return string */ static function htmlHFirstLine (array $a): string { $out='<table "class="table"> <thead> <tr>'.PHP_EOL; $out.=' <th>'.implode('</th><th>', array_shift($a) ).'</th> </tr> </thead> <tbody>'.PHP_EOL; foreach ($a as $v) { $out.=' <tr> <td>'.implode('</td><td>', $v).'</td> </tr>'.PHP_EOL; } $out.=' </tbody> </table>'.PHP_EOL; return $out; }
Un petit test:
$user='myUser'; $password='myPassword'; $tns='myDBAlias'; $ora=new oracle ; $ora->connect( $user, $password, $tns, OCI_DEFAULT ); $out=$ora->execSqlFromFile( 'query' ); var_dump($out); echo table2DOut::html($out->renderAll()); echo table2DOut::htmlHFirstLine($out->renderHandD()); echo "<pre>".PHP_EOL; echo table2DOut::csvHFirstLine($out->renderHandD()); echo "</pre>".PHP_EOL;
On obtient la sortie attendue suivante:
D:\DevsGit\wp-lessons\lessons\Chapitre-0005\index.php:15: object(queryResult)[3] private 'types' => array (size=3) 0 => string 'VARCHAR2' (length=8) 1 => string 'CLOB' (length=4) 2 => string 'NUMBER' (length=6) private 'cols' => array (size=3) 0 => string 'SQL_ID' (length=6) 1 => string 'SQL_FULLTEXT' (length=12) 2 => string 'SHARABLE_MEM' (length=12) private 'lines' => array (size=2) 0 => array (size=3) 0 => string 'gr4whhk4ds00a' (length=13) 1 => string 'LOCK TABLE "WRH$_CELL_DISK_SUMMARY" PARTITION ("WRH$_CELL_DISK_SUMMARY_473438319_72") IN EXCLUSIVE MODE NOWAIT ' (length=113) 2 => string '36258' (length=5) 1 => array (size=3) 0 => string '2a16cph744016' (length=13) 1 => string 'LOCK TABLE "SYS"."ORA_TEMP_2_DS_100266" IN EXCLUSIVE MODE NOWAIT ' (length=66) 2 => string '16243' (length=5)
SQL_ID SQL_FULLTEXT SHARABLE_MEM gr4whhk4ds00a LOCK TABLE “WRH$_CELL_DISK_SUMMARY” PARTITION (“WRH$_CELL_DISK_SUMMARY_473438319_72”) IN EXCLUSIVE MODE NOWAIT 36258 2a16cph744016 LOCK TABLE “SYS”.”ORA_TEMP_2_DS_100266″ IN EXCLUSIVE MODE NOWAIT 16243
SQL_ID SQL_FULLTEXT SHARABLE_MEM gr4whhk4ds00a LOCK TABLE “WRH$_CELL_DISK_SUMMARY” PARTITION (“WRH$_CELL_DISK_SUMMARY_473438319_72”) IN EXCLUSIVE MODE NOWAIT 36258 2a16cph744016 LOCK TABLE “SYS”.”ORA_TEMP_2_DS_100266″ IN EXCLUSIVE MODE NOWAIT 16243 SQL_ID,SQL_FULLTEXT,SHARABLE_MEM gr4whhk4ds00a,LOCK TABLE "WRH$_CELL_DISK_SUMMARY" PARTITION ("WRH$_CELL_DISK_SUMMARY_473438319_72") IN EXCLUSIVE MODE NOWAIT ,36258 2a16cph744016,LOCK TABLE "SYS"."ORA_TEMP_2_DS_100266" IN EXCLUSIVE MODE NOWAIT ,16243
Le code cette leçon est disponible sur notre gitlab (Chapitre-0005). il doit évidemment être adapté pour pouvoir se connecter à votre base.