trucs et astuces php et mysql
DESCRIPTION
Un voyage dans les fonctions moins connues de PHP et MySQL, avec un souci de résoudre des problèmes courants et communs.TRANSCRIPT
Trucs et astucesPHP & MySQL
Toute cette puissance au bout des doigtsMontréal, Québec, Canada
Agenda
Trucs et astuces PHP et MySQL
Issus des distributions
Rien de spécial
Encore valide en PHP 4 (mais passez en 5!)
Le mois de la fonction PHP
Questions?
Qui parle?
Damien Séguy
PHP Québec, AFUP
Expert PHP et MySQL : sécurité, audit
Auteur des documentations rédacteur en chef
http://www.nexen.net/
Au hasard
rand() et mt_rand()
array_rand() : extrait des lignes d'un tableau
Extrait les clés!
shuffle() : mélange un jeu de cartes
str_shuffle : Mélange une chaîne
Au hasard
<?php$a = range('a','d');shuffle($a);
print_r($a);
print_r(array_rand($a,3));
print str_shuffle('abcdef');// eabdcf?>
Array( [0] => c [1] => d [2] => b [3] => a)Array( [0] => 0 [1] => 1 [2] => 3)
Tableaux SQL?
Array_unique : DISTINCT
array_count_values : GROUP BY
Bien plus rapide que la précédente
Tableaux SQL?<?php$array = array("1", "MySQL", 1, "PHP", "PHP");$array = array_count_values($array);asort($array);print_r($array);?>
Array( [1] => 2 [PHP] => 2 [MySQL] => 1)
sort r u
ksort kr uk
asort ar ua
Tableaux SQL
array_multisort() : tri surplusieurs tableaux en même temps
Fonctionne comme ORDER BY
<?php$ar1 = array(5,4,3,2);$ar2 = array('a','b','c','d');array_multisort($ar1, $ar2);array_multisort($ar1, SORT_ASC, SORT_INT, $ar2);
?>
Array( [0] => 2 [1] => 3 [2] => 4 [3] => 5)Array( [0] => d [1] => c [2] => b [3] => a)
Étranges tris?
mysql> SELECT id, ordre FROM table ORDER BY ordre ASC;+----+------------+| id | ordre |+----+------------+| 1 | premier || 2 | deuxième || 3 | troisième || 4 | quatrième |+----+------------+
Est ce que ça cloche?
Étranges tris
mysql> CREATE TABLE `test` ( `id` tinyint unsigned, `ordre` enum(‘premier’,’deuxième’, ’troisième’,’quatrième’),) ENGINE=MYISAM;
Enum est une chaîne et un nombre
Utilisé en interne comme entier
Affiché par défaut comme une chaîne
Variables MySQL
Disponibles depuis la pré-histoire
Gérée au niveau des connexions
Détruites à la déconnexion
Pas de concurrence
Stockage local de scalaires
Permet de se passer de PHP
Variables MySQL
mysql> SELECT @total := sum(nombre) FROM statsPHP ;mysql> UPDATE statsPHP SET pourcentage = nombre / @total * 100;
<?php $requete = "SELECT sum(nombre) FROM statsPHP"; $res = mysqli_query($mid, $requete); $ligne = mysqli_fetch_row($res); mysqli_free_result($res);
$requete = "UPDATE statsPHP SET pourcentage = nombre / ".$ligne." * 100;"; mysqli_query($mid, $requete); ?>
Sécurité SQL<?php $requete = "SELECT droits FROM utilisateurs WHERE login = '". mysqli_real_escape_string($mid, $_POST["login"])."'"; $res = mysqli_query($mid, $requete); $droits = mysqli_fetch_row($res); ?>
<?php $requete = "SET @login :=
'".mysqli_real_escape_string($mid, $_POST["login"])."'"; $res = mysqli_query($mid, $requete);
$requete = "SELECT droits FROM utilisateurs WHERE login = @login"; $res = mysqli_query($mid, $requete); $droits = mysqli_fetch_row($res); ?>
Classementsmysql> SET @rank := 0;mysql> SELECT @rank := @rank + 1 AS rank, country, php FROM statsPHP ORDER BY php;+------+---------------+-----+| rank | country | php |+------+---------------+-----+| 1| F. Polynesia | 67 | | 2| Turk&Caicos | 55 | | 3| France | 41 | | 4| USA | 31 | | 5| Canada | 31 | | 7| Greenland | 17 | | 8| Israel | 17 | +------+---------------+-----+8 rows in set (0.00 sec)
Ex-aequomysql> SET @num := 0, @rank := 0, @prev := NULL;mysql> SELECT @num := @num + 1 AS row, @rank := if(@prev != php, @num, @rank) AS rank, country, @prev := php AS php FROM statsPHP ORDER BY php;+------+------+---------------+-----+| row | rank | country | php |+------+------+---------------+-----+| 1| 1| Polynésie Fr. | 67 | | 2| 2| Turk & Caicos | 55 | | 3| 3| France | 41 | | 4| 4| USA | 31 | | 5| 4| Canada | 31 | | 6| 6| Groënland | 17 | | 7| 6| Israel | 17 | +------+------+---------------+-----+
Variables en masse
Compact() et extract()
<?php $requete = "SELECT * FROM table WHERE login = @login"; $res = mysqli_query($mid, $requete); $resultat = mysqli_fetch_row($res);
extract($resultat); // $colonne1 = 'valeur'; $colonne2 = 'valeur'
extract($_GET); // ne l'utilisez pasimport_request_variables(); // non plus?>
PHP est dynamique
Variables variables
<?php $x = 'y'; $y = 'z'; $z = 'a';
echo $x; // affiche y echo $$x; // affiche z echo $$$x; // affiche a ?>
constantes variables
Une seule définition
Accès dynamique à une valeur constante
<?php define ("CONSTANTE", 'PHP Québec'); echo CONSTANTE; echo constant("CONSTANTE"); print_r(get_defined_constants());?>
Fonctions variables
<?php $fonc = 'foo'; $foo = 'bar'; $classe = 'bb';
$fonc($foo); // vaut foo('bar'); call_user_func($fonc, $foo);// idem
call_user_func(array($classe, $fonc), $foo); // $bb->fonc('bar'); // bb::fonc('bar'); $classe->$fonc($foo); // idem?>
Variables en masse
Compact() et extract()
<?php $x = 'a'; $y = 'b'; $z = compact('x','y'); // $z = array('x'=> 'a', 'y' => 'b');
$r = call_user_func_array('fonc', $z); // vaut fonc($x, $y) ou fonc('a', 'b');
extract($r); // $x = 'c'; $y = 'd'; $t = 'e'; list($x, $y, $t) = array_values($r); ?>
Toute cette dynamite..
Métamoteur
Gabarits
Gestion de structures dynamiques
SOAP
Personnalisation de bibliothèques
Magie de l'objet
__autoload() : Juste à temps
<?php// php.ini auto_prependfunction __autoload($classe) { include 'classes/' . $classe . '.php';}
$objet = new MaClasse();$objet2 = new MaClasse2(); ?>
Magie de l'objet__toString() :
transforme un objet en chaîne
toArray(), __toInteger()?
<?php class db { function __toString() { return "La connexion à ".$this->hote." est ". (is_null($this->mid ? 'active' : 'inactive' ).""; } }
$db = new db(); echo $db; ?>
PHP Catchable fatal error: Object of class mysqli could not be converted to string
Magie de l'objet
__sleep() et __wakeup()
Stocke un objet en session
Avant serialize()
class db { // ..... function __sleep() { unset($this->mid); } function __wakeup() { $this->mid = new mysqli("host", "user", "secret", "base"); } // ..... }
Buffer de sortie
Intercepte le contenu
Evite le bogue 'already sent'
Nettoyez : tidy
Compressez : gz
Cachez : ce sein que
<?phpob_start("ob_gzhandler");echo "Hello\n";setcookie("c", "v");ob_end_flush();?>
Caches simples
auto_prepend :
auto_append :
if ( filemtime( CACHE )+3600 < time()) { include($cachefile); exit; } ob_start();
$content = ob_get_contents(); file_put_contents(CACHE, $contents); ob_end_flush();
Connexions HTTP
PHP Enregistre l'état de la connexion
0 Normal; 1 Annulé; 2 expiré
ignore_user_abort() évite les interruptions
connexion_status() surveille l'état
Register_shutdown
Semblable au __destruct()
Fonction exécutée à l'extinction du script
Fermeture des ressources
Plus pratique que ignore_user_abort pour une bibliothèque
Variables
var_export : Crée le code pour une variable
Pratique pour les tableaux de configuration
Optimise ces tableaux
<?php
$array = array(5,4,3,2);
print var_export($array, true);
?>
array ( 0 => 5, 1 => 4, 2 => 3, 3 => 2,)
Assertions
tests dans les scripts
assertion sont gérées par directive
Par défaut, activé
Facile à supprimer echo/var_dump
Développement par contrat
Assertions
<?php assert_options(ASSERT_CALLBACK,'assert_callback'); function carre_naturel($x) { assert('is_integer( $x );' ); assert('$x < 0'); assert('$x > sqrt(PHP_INT_MAX) //* $x doit être plus petit' );
return $x * $x; } ?>
Assertions
<?php
function assert_callback($script,$line, $message){ echo 'Un problème est survenu dans le script <b>', $script,'</b>, à la ligne <b>', $line, '</b> : <br />' . $message; exit; } ?>
Déboguage
phpinfo()
get_defined_funcs()
get_extension_funcs()
get_defined_classes()
get_object_vars()
get_class_var()
<?phpReflection::export( new ReflectionClass('Exception'));?>Class [ <internal> class Exception ] { - Constants [0] {} - Static properties [0] { } - Static methods [0] { }
Débogage
get_defined_vars()
get_included_files()
__FILE__, __LINE__
__FUNCTION__, __CLASS__, __METHOD__
Débogage
debug_backtrace()
Affiche la pile PHP
Inclus les arguments utilisés
array(2) {[0]=>array(4) { ["file"] => string(10) "/tmp/a.php" ["line"] => int(10) ["function"] => string(6) "a_test" ["args"]=> array(1) { [0] => &string(6) "friend" }}[1]=>array(4) { ["file"] => string(10) "/tmp/b.php" ["line"] => int(2) ["args"] => array(1) { [0] => string(10) "/tmp/a.php" } ["function"] => string(12) "include_once" }}
Listes rapides
scandir(‘/tmp’, true);
Permet le tri sur les noms
Remplace opendir(), readdir(), closedir() et une boucle!
Glob(‘*.html’);
Listes rapides
<?phpprint_r(scandir('/tmp/', 1));print_r(glob('/tmp/sess_*'));?>
Array( [0] => sess_um8rgjj10f6qvuck91rf36srj7 [1] => sess_u58rgul68305uqfe48ic467276 [2] => mysql.sock [3] => .. [4] => .)Array( [0] => /tmp/sess_um8rgjj10f6qvuck91rf36srj7 [1] => /tmp/sess_u58rgul68305uqfe48ic467276)
URL
parse_url() : Détaille une URL
parse_string() : Découpe les paramètres
http_build_query() : Reconstruit une URL
URL
<?php$url = 'htp://login:[email protected]/ path/file.php?a=2 &b[]=3#ee';
$d = parse_url($url);print_r($d);
parse_str($d["query"]);var_dump($GLOBALS["b"]);
print http_build_query( array_merge($_GET , array(' de ' => '对了!')));?>
Array( [scheme] => htp [host] => www.site.com [user] => login [pass] => pass [path] => /path/file.php [query] => a=2 &b[]=3 [fragment] => ee)array(1) { [0]=> string(1) "3"}+de+=%E5%AF%B9%E4%BA%86%EF%BC%81
URL
<?php get_headers('http://localhost/logo.png', false);?>
Array( [0] => HTTP/1.1 200 OK [Date] => Fri, 09 Mar 2007 21:09:52 GMT [Server] => Apache/1.3.33 (Darwin) PHP/5.2.1 [X-Powered-By] => PHP/5.2.1 [En_plus] => non [Set-Cookie] => Array ( [0] => a=a [1] => a=b )
[Connection] => close [Content-Type] => text/html)
Cette conférence
http://www.nexen.net/conferences.php
Tableaux
array_combine : combine deux tableaux en un seul
<?php$a = array('vert', 'rouge', 'jaune');$b = array('avocat', 'pomme', 'banane');$c = array_combine($a, $b);
print_r($c);?>
Array( [vert] => avocat [rouge] => pomme [jaune] => banane)