Circum Blog

Circum Net – IT – Conseils pratiques

SQLite: récupération d’un résultat dans un objet spécifique

PHP, SQLite

La méthode setFetchMode de la librairie PDO permet de récupérer, dans un objet spécifique, une ligne résultat d’une requête SQL (SELECT).

En fixant le premier argument de cette méthode à PDO::FETCH_CLASS et en lui fournissant le nom d’une classe (définie préalablement), c’est cette dernière qui va être invoquée et ses propriétés vont être affectées avec les valeurs des champs correspondant (le constructeur est également appelé). Voici un code fonctionnel qui illustre cela.

PDO::FETCH_CLASS

<?php
class Movie
    {
    public $title;
    public $director;
    public $description;
    public $year;

    // Les propriétés de l'objet sont fixées par PDO avant l'appel au constructeur
    // Le constructeur peut ensuite prendre le relais et intervenir sur les propriétés
    function __construct()
        {
        $this->title = strtoupper($this->title);
        }
    }

try
    {
    $dbh = new PDO('sqlite:./movies');

    $sql = 'SELECT * FROM movies';
    $stmt = $dbh->query($sql);

    // Retourne une nouvelle instance de la classe demandée
    // Le mapping est fait entre les champs et les propriétés
    $stmt->setFetchMode(PDO::FETCH_CLASS, 'Movie');

    while($obj = $stmt->fetch())
        {
        echo $obj->title . ' - ' . $obj->director . PHP_EOL;
        }

    }
catch(PDOException $e)
    {
    echo $e->getMessage();
    }
?>


PHP et son serveur web interne

PHP

Depuis sa version 5.4.0, la distribution de PHP fournit un serveur web interne.

L’aspect pratique de cette initiative réside dans le fait de disposer d’un serveur HTTP intégré au langage et donc capable de vous faire bénéficier d’un cadre de développement web sans configuration particulière ni package envahissant.
Cet outil supplémentaire est cependant limité en terme de fonctionnalités et n’est pas prévu pour la mise en production d’une application. Il n’est à envisager que dans la cadre de tests, de prototypage, d’apprentissage ou de démonstration

Pour démarrer le serveur intégré, il suffit -dans un fenêtre terminal- d’exécuter la ligne de commande suivante à la racine de votre projet :

php -S localhost:8000

Le serveur web sera alors lancé et attendra les requêtes HTTP sur l’adresse IP et le port qui lui ont été passés en argument.

Pour le tester, vous pouvez saisir l’URL http://localhost:8080 dans la barre d’adresse d’un navigateur web.



L’approche MVC

Programmation

L’approche MVC, pour Model-View-Controler ou en français Modèle-Vue-Contrôleur, privilégie la séparation du traitement des données de leur présentation. Elle préconise l’organisation du code d’interface utilisateur en trois composants distincts :

  • Modèle : en charge de la gestion des données d’une application (partie logique de l’application / règles métiers).
  • Vue : en charge du dialogue avec les utilisateurs (partie habillage de l’application / dessin des écrans).
  • Contrôleur : en charge de l’orchestration des requêtes des utilisateurs et de leur relais vers les modèles (partie liaison modèles-vues / aiguillage).

Cette approche permet aux développeurs de profiter des avantages suivants :

– séparation entre les données, la présentation et les traitements;
– souplesse;
– maintenance allégée;
– possibilité d’évolution renforcée;
– spécialisation des tâches et division claire du travail.

Architecture MVC

Architecture MVC - 3 niveaux

Le contrôleur

Le contrôleur n’effectue pas ou très peu de traitement (éventuellement un travail de préparation et/ou de redirection). Il réceptionne et gère les événements provenant de l’utilisateur, enclenche les actions à effectuer sur les données en sollicitant le modèle adéquat et renvoie la vue correspondant à la demande. On n’y retrouvera donc pas d’instruction d’habillage proprement dit.



Utilisation d’un framework

Programmation

Un framework (qui pourrait être traduit par “espace de travail modulaire”) est constitué d’un ensemble de bibliothèques et de conventions servant à la réalisation d’applications informatiques. En imposant un certain nombre de règles et de briques logicielles, un framework vise à fournir un cadre de travail rigoureux permettant de produire rapidement des applications cohérentes, fiables et aisées à maintenir.

Au nombre des avantages des frameworks on peut citer :

– la formalisation des procédures;
– la standardisation des procédures;
– la convergence des procédures;
– la modularité du code;
– la réutilisation du code.

A contrario, en ce qui concerne les inconvénients d’un recours à un framework, on pourra trouver :

– la rigidité de l’architecture;
– l’inadaptation à certains contextes (lourdeur);
– une courbe d’apprentissage parfois longue.

Il existe aujourd’hui un grand nombre de frameworks quelque soit le langage de programmation privilégié. En voici les plus évidents :

En PHP :

Zend Framework
Symfony
Laravel
Phalcon
Yii
CodeIgniter
CakePHP

En Python :

Zope
Django
Pylons



Apprentissage de PHP

PHP, Programmation

Deux questions s’imposent d’entrée de jeu : PHP est-il facile à apprendre et cela prend-il beaucoup de temps? Dans la littérature sur le sujet, on trouve de nombreux auteurs qui répondent sans préambule OUI à la première question et NON à la deuxième. Il faut cependant nuancer ces propos.

PHP, pour être bien maîtrisé, nécessite de l’étudiant la même énergie et les mêmes efforts que pour tout langage de programmation. Si certaines de ses fonctionnalités sont aisées à manipuler d’autres concepts peuvent être plus ardus (telle que l’approche “orienté objet” introduite dans la version 5 de PHP).

Le temps d’apprentissage va grandement dépendre de votre “background” et des objectifs que vous vous êtes fixés: il est évident qu’une personne ayant déjà pratiqué un langage de programmation découvrira PHP avec un oeil différent de celui du débutant en programmation. La tâche sera plus difficile pour le débutant, mais certainement pas impossible. PHP présente sans conteste les avantages d’offrir aux développeurs Web une suite de procédures clairement définies et d’application directe.



Redirection : Headers already sent by

PHP, Programmation

Lorsque l’on utilise une instruction PHP qui manipule les en-têtes HTTP (par exemple via la fonction ‘header’ permettant d’enclencher une redirection), il faut s’assurer des les appeler avant d’avoir généré le moindre flux de sortie vers le client.

En effet, dès qu’un début de contenu est envoyé via le serveur Web (soit via des instructions HTML classiques, soit via des instructions PHP d’output comme echo et print) cela implique que les en-têtes HTTP ont déjà été précisés et communiqués au client. Or, il n’est plus possible de remanier les en-têtes HTTP une fois qu’ils sont envoyés. En conséquence, si -après avoir produit du code HTML ou lancé des instructions ‘echo’- on utilise dans un script la fonction ‘header’ pour rediriger un appel de page, le moteur PHP génère automatiquement un message d’erreur ‘Headers already sent by …’.

Il y a toutefois un moyen d’éviter cette difficulté : en utilisant la bufferisation de sortie – c’est-à-dire la mise en mémoire temporaire des données de sortie. On utilisera pour cela les fonctions prédéfinies ‘ob_start’ et ‘ob_end_flush’.

ob_start()

ob_start() démarre la bufferisation de sortie. Tant qu’elle est enclenchée, les données -hormis les en-têtes- ne sont pas envoyées au navigateur, mais temporairement placées dans un buffer.

ob_end_flush()

ob_end_flush() envoie vers le client le contenu du buffer de sortie (s’il existe) et désactive la bufferisation.

Utilisation d’un buffer d’output

<?php
// Démarrage de la bufferisation de sortie
ob_start();
	
echo "Cet output est issu d'un buffer de sortie.";

// Envoi vers le client du contenu du buffer
ob_end_flush();
?>

Note : ob_gzhandler() est une fonction qui -combinée à ‘ob_start()’- permet l’envoi de données compressées aux navigateurs qui supportent les pages compressées. Elle détermine le type d’encodage accepté par un navigateur, et retourne le contenu le plus adéquat. Ce procédé réduit considérablement le poids des pages à délivrer.

Pages compressées

Pour compresser les pages à la volée : il suffit de placer en tête de fichier la ligne suivante :

<?php ob_start('ob_gzhandler'); ?>
 ... suite du code ou de l'output ...


PHP et les chaînes de caractères

PHP, Programmation

En PHP, les chaînes de caractères peuvent être définies en utilisant deux types de délimiteurs : les apostrophes doubles et les apostrophes simples.

Dans le cas d’une chaîne de caractères délimitée par des apostrophes doubles (double-quotes), les variables à l’intérieur de la chaîne de caractères seront remplacées par leur valeur. Comme en C ou en Perl, le caractère anti-slash (\) peut ici être utilisé pour “protéger” un caractère spécial.

Si la chaîne de caractères est par contre limitée par des apostrophes simples (simple-quotes), les variables présentes dans la chaîne ne seront pas substituées et le caractère anti-slash (caractère d’échappement), n’aura aucun effet (à deux exceptions près, pour \’ et \\ , afin de pouvoir utiliser les caractères simple-quote et anti-slash dans la chaîne de caractères).

De nombreux programmeurs privilégient la limitation par des apostrophes simples lorsque qu’aucune substitution n’est nécessaire. Il n’y a alors pas d’analyse de chaîne impliquée et c’est donc sensé faire gagner du temps à l’interpréteur PHP.

Quelques bonnes pratiques :

<?php
// préférez la concaténation à l'imbrication :
echo "Hello $name"; 
echo 'Hello' . $name; // recommandé

// attention aux indices de tableaux
echo $users[admin]; // faux, si si admin est une constante
echo $users['admin']; // recommandé

echo "Hello $users[admin]"; 
echo 'Hello' . $users['admin']; // recommandé
?>


Générer du PDF avec PHP

PHP, Programmation

Il s’avère souvent pratique dans une application (Web ou autre) de pouvoir fixer des données au format PDF : formulaire, certificat, version imprimable, fichier attaché. PHP 5 permet la génération dynamique de fichiers PDF.

La librairie PDFlib
En PHP, la librairie principale de production PDF est pour l’instant PDFlib. Cette API, riche en fonctionnalités, n’est cependant pas gratuite et est distribuée sous licence commerciale (une version gratuite appelée PDFlib Lite est également disponible).

Fonctionnalités proposées par PDFlib :

– mise en page standard
– images
– éléments graphiques
– annotations
– signets
– tableaux
– protection

Plus d’information et téléchargement : www.pdflib.com

FPDF
Une alternative à PDFlib consiste à utiliser la classe FPDF. Celle-ci, distribuée gratuitement, même si elle offre moins de possibilités est beaucoup plus accessible : pas d’installation préalable, pas de licence commerciale, simplicité de mise en oeuvre.

Pour l’utiliser, il suffit de télécharger le package FPDF, de le décompresser dans un répertoire accessible pour votre application et d’en inclure le fichier principal dans votre code.

Exemple de création d’un document PDF :

<?php
include('fpdf/fpdf.php');

$pdf=new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',18);
$pdf->Cell(40,10,'Bonjour à tous!');
$pdf->Output("test.pdf");
?>

Vous trouverez la documentation de cette classe sur le site www.fpdf.org.



Vérifier le type de navigateur avec PHP

PHP

En accédant aux informations véhiculées par la requête HTTP émise à partir du client, on peut détecter le type de navigateur utilisé. Pour cela, en PHP, il suffit d’invoquer le tableau super glogal $_SERVER. Celui-ci peut être vu comme une variable spéciale de PHP qui contient toutes les informations relatives au serveur et à l’exécution (comme les en-têtes HTTP, les dossiers et chemins du script).

Il est toujours possible d’utiliser la fonction ‘var_dump’ pour afficher les informations structurées d’un tableau (en l’occurence $_SERVER). Vous en découvrirez ainsi toutes les composantes et informations utiles:

<?php
var_dump($_SERVER);
?>

L’élément particulier qui nous intéresse dans ce tableau est $_SERVER[‘HTTP_USER_AGENT’]. Sa valeur décrit le client HTML utilisé pour voir la page courante (exemple : Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586).

Affichage du contenu de l’élément HTTP_USER_AGENT :

<?php
echo $_SERVER['HTTP_USER_AGENT'];
?>

Une fois sa valeur connue/récupérée, on peut l’utiliser pour optimiser l’affichage de sa page en fonction des capacités du client – notamment en exploitant la fonction prédéfinie get_browser().

HTTP_USER_AGENT et get_browser() :

<?php
$browser = get_browser($_SERVER['HTTP_USER_AGENT'], true);
print_r($browser);
?>

Les valeurs retournées reprennent les caractéristiques du navigateur : version, css, frames, JavaScript, cookie …

Vous pouvez évidemment à la suite mettre en oeuvre votre propre batterie de tests afin de détecter les propriétés/caractéristiques qui vous paraissent les plus pertinentes dans votre projet.

Détection de la plateforme du client:

<?php
$u_agent = $_SERVER['HTTP_USER_AGENT']; 
$platform = '';
if (preg_match('/linux/i', $u_agent)) 
    {
    $platform = 'linux';
    }
elseif (preg_match('/macintosh|mac os x/i', $u_agent)) 
    {
    $platform = 'mac';
    }
elseif (preg_match('/windows|win32/i', $u_agent)) 
    {
    $platform = 'windows';
    }
?>


Prolonger la durée de vie des objets en PHP

PHP, Programmation

Etant donnée que la durée de vie d’un objet n’excède pas la durée d’exécution du script qui le crée, quand un objet est détruit, les valeurs de ses attributs (les variables membres) sont perdues! Situation peu confortable si l’on pense à utiliser ces données ultérieurement ou à les échanger entre programmes.

Pour pallier cette difficulté on peut avoir recours aux opérations de sérialisation et désérialisation. Grâce à celles-ci, il est possible de conserver l’état d’un objet sur un support de stockage de façon à pouvoir en recréer une copie exacte ultérieurement ; mais également de transmettre l’objet par valeur d’une application à une autre.

La sérialisation consiste donc à stocker les valeurs des attributs d’une instance d’un objet dans une séquence linéaire. La fonction “serialize” retourne une chaîne contenant une représentation linéaire de l’objet qui lui est passé en argument, pour stockage.

La désérialisation consiste à accepter des informations stockées et à recréer des objets à partir de celles-ci. La fonction “unserialize” retourne sous forme d’objet la séquence passée en argument.

Voyons cela à travers un exemple :

Script tools.inc.php – la classe à l’origine des objets dont on veut enregistrer l’état.

<?php
class Book
   {
   private $type;
   private $price;
   private $title;

   function Book($par)
        {
        $this->type = $par;
        }

   public function setPrice($par)
        {
        $this->price = $var;
        }
        
   public function getPrice()
        {
        return $this->price;
        }
        
   public function setTitle($par)
        {
        $this->title = $par;
        }
        
   public function getTitle()
        {
        return $this->title;
        }
    }
?>
page1.php – l’instanciation de l’objet et sa sérialisation.

<?php
/* Appel à la définition de classe */
include("tools.inc.php");

$myBook = new Book('1');
$myBook->setTitle('The Black Dahlia');
$myBook->setPrice('19');	


/* Sérialisation de l'objet */
$s = serialize($myBook);

/* Ecriture de la séquence sur disque */
$fp = fopen("store", "w");
fputs($fp, $s);
fclose($fp);
?>
page2.php – la récupération de l’objet sérialisé.

<?php
/* Appel à la définition de classe */
include("tools.inc.php");

/* Récupération de la séquence */
$s = implode("", @file("store"));

/* Désérialisation et récupéartion de l'objet*/
$aBook = unserialize($s);

echo $aBook->getTitle();
/* Affiche "The Black Dahlia" */
?>