[Resolu] Portée variables

Eléphant du PHP | 190 Messages

10 juil. 2012, 13:24

Bonjour,

J'ai décidé de modifier mes script pour passer des fonctions mysql_ à mysqli_ comme recommandé dans la doc php.

Prenons deux simples fonctions:
<?php
function connectionBdd(){
	global $link;
	$link = mysqli_connect('localhost','root','','base');
	if (!$link) {
		die('Erreur de connexion ('.mysqli_connect_errno().') '.mysqli_connect_error());
	}
}
function actualize($login){
	global $link;
	$sql=mysqli_query($link,'UPDATE members SET connect="'.date("Y-m-d H:i:s").'" WHERE login="'.$login.'"');
}
?>
Déja, pourquoi dois-je déclarer mon $link en GLOBAL dans ma fonction connectionBDD alors qu'avec l'ancien système (mysql_connect) ce n'était pas nécessaire ?

Ensuite, après l'avoir déclarée dans la première fonction, pourquoi ça plante si je ne la redéclare pas dans ma seconde ? Une variable GLOBALE n'est pas sensée être accessible de partout ?

Voici comment je les appelle.
session_start();
include('functions.php');
connectionBdd();
if(!empty($_SESSION['login'])){
	actualize($_SESSION['login']);
}
En appelant ma première fonction, la variable $link passe en globale, alors pourquoi la redéclarer dans ma deuxième fonction alors qu'elle existe déjà ?

Si je ne la déclare pas, j'ai un "Undefined variable: link"

Merci pour vos éclaircissements.
Modifié en dernier par Zahnzao le 10 juil. 2012, 14:44, modifié 1 fois.

ViPHP
ViPHP | 2577 Messages

10 juil. 2012, 13:36

Dans une fonction, on ne voit que les paramètres de la fonction et les variables initialisées dans la fonction. "globale" permet d'ajouter des variables qui sont vues dans le script hors fonction et dans les fonctions qui en font la demande explicite.

L'intéret est de ne pas avoir d'interférence involontaire entre les variables utilisée dans des fonctions et dans le code qui les appelle.

Par exemple dans le code suivant, il n'y a pas de mélange entre les $i des 2 boucles :
<?PHP
for ($i=0;$i<10;$i++) {
   toto($tab);
}

function toto($t) {
   for ($i=0;$i<10;$i++) {
      echo tab[$i];
   }
}
?> 

Eléphant du PHP | 190 Messages

10 juil. 2012, 13:55

Merci.

Je comprend bien, j'ai lu des tutos, mais pourquoi le fait de passer à mysqli_connect au lieu de mysql_connect à activé ce comportement ? Le code est sensiblement identique.

Anciennes fonctions: pas besoin de GLOBAL
function connectionBdd(){
     $link = mysql_connect('localhost', 'root', '');
     if (!$link) {
        die('Impossible de se connecter : ' . mysql_error());
     }
     $db_selected = mysql_select_db('base', $link);
     if (!$db_selected) {
        die ('Impossible de sélectionner la base de données : ' . mysql_error());
     }
}
function actualize($login){
        $sql=mysql_query('UPDATE members SET connect="'.date("Y-m-d H:i:s").'" WHERE login="'.$login.'"');
}
Les nouvelles telles que dans mon précédent post.
function connectionBdd(){
        global $link;
        $link = mysqli_connect('localhost','root','','base');
        if (!$link) {
                die('Erreur de connexion ('.mysqli_connect_errno().') '.mysqli_connect_error());
        }
}
function actualize($login){
        global $link;
        $sql=mysqli_query($link,'UPDATE members SET connect="'.date("Y-m-d H:i:s").'" WHERE login="'.$login.'"');
}
Je n'avais nullement besoin de les globaliser avant... Ca fonctionnait tel quel. Je voudrai juste comprendre ce que je fais.

Merci.

Eléphant du PHP | 190 Messages

10 juil. 2012, 14:09

Ok je viens de comprendre,

mysqli_connect demande un second paramètre ($link) qui doit être globaliser pour être accessible hors de la fonction.

Mais alors pourquoi je ne peux pas y accéder dans ma seconde fonction sans la reglobaliser ?

ViPHP
xTG
ViPHP | 7331 Messages

10 juil. 2012, 14:16

Tu n'as visiblement pas compris l'explication de Mazarini.
Une variable déclarée dans un autre scope nécessite d'être déclarée dans le scope que tu utilises comme étant global afin qu'il sache où aller la chercher.
Donc dans ton connect pour l'enregistrer en global scope et non en function scope.
Et dans ta seconde fonction pour savoir qu'il faut aller la chercher en global scope.
Quand tu créés une fonction d'objet, cette fonction est définie dans un scope (celui de la class en question).
Appeler cette fonction sans dire que c'est de l'instance X de l'objet c'est dire à l'interpréteur de se démerder, il regarde donc le premier scope et renvoie une erreur si non trouvée.
PHP à la différence de JEE ne cherche pas dans les scopes les un après les autres.

La différence avec mysql_query c'est que cette dernière garde dans sa propre mémoire le dernier lien bdd ouvert afin de ne pas avoir à le re-spécifier, contrairement à mysqli.

ViPHP
ViPHP | 2577 Messages

10 juil. 2012, 14:41

Dans un cas tu la rends disponible dans global et dans un autre tu lui dis d'aller la chercher dans global.

Il existe un tableau qui s'appelle $_GLOBALS (de mémoire) et qui est disponible dans toutes les fonctions. Mettre "global $link", c'est faire le lien entre $link et $_GLOBALS['link'].

Au passage, il faut bien identifier les variables globales pour ne pas les écraser. $link est un peu trop générique. Si tu fais $link = fopen($fichier), tu perdra la connexion à la base de données. Tu pourrais préférer une variable comme $database ou $mysqli que tu risque moins de réutiliser mais c'est à toi de voir.

Eléphant du PHP | 190 Messages

10 juil. 2012, 14:44

Ok ! Maintenant tout est clair.

Je vous remercie tout les deux.

ViPHP
ViPHP | 2577 Messages

10 juil. 2012, 14:58

C'est assez facile à comprendre... quand on a compris mais ca reste difficile à expliquer.

Lorsque l'on commence la programmation avec des langages qui obligent à déclarer les variables, c'est peut être plus facile puisque toutes les variables utilisées doivent être déclarées dans chaque fonction. Le "global" peut être assimilé à une déclaration de variable.