IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

passage par référence [PHP 5.6]


Sujet :

Langage PHP

  1. #1
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Points : 107
    Points
    107
    Par défaut passage par référence
    Bonjour à tous,
    J'utilise des requêtes paramétrées en Mysqli. J'en ai un peu marre de mettre de '&' partout et je tente de réduire au maximum leur besoin.
    J'ai un objet PHP que je compte utiliser comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $resultat = Request::createSelect()->from('nomtable')->where('nomcolonne', Request::OPE_EGAL, $valeur, 'i')->get();
    Dans mon objet j'ai en résumé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    class Request {
    	const OPE_EQUAL = '=';
    	public $conditions = array();
     
    	public function DbRequest(){
    	}
     
    	public static function createSelect() {
    		return new DbRequest();
    	}
     
    	public function where($columnName, $operator, $value, $valueType) {
    		$this->conditions[] = array('name' => $columnName, 'ope' => $operator, 'value' => $value, 'type' => $valueType);
    		return $this;
    	}
     
    	public function whereArray(array $all) {
    		$this->conditions = $all;
    		return $this;
    	}
     
    	public function get(){
    		$result=null;
    		$params = $this->getParams();
    		$q = Db::select($sql, $result, $params); 
    		return $result;
    	}
     
    	private function getParams() {
    		// Mysqli a besoin d'un tableau de type [0=>'concaténation des types', 1=>'valeur1', ...]
    		$p = array(0 => '');
    		foreach ($this->conditions as $f) {
    			$p[0] .= $f['type'];
    			$p[] = &$f['value']; // JE VEUX GARDER LE PASSAGE PAR REFERENCE SEULEMENT ICI
    		}	
    		return $p;
    	}
    }
     
    class Db {
    	public static function select($sql, &$result, array &$params) {
    		$q = self::query($sql, $params, $result);
    		// et d'autres trucs
    	}
     
    	public static function query($query, array &$params, &$result){
    		$stmt = self::$cnx->prepare($query);
    		call_user_func_array(array($stmt, 'bind_param'), $params);
    		$stmt->execute();
    		// et d'autres trucs
    	}
    }
    Au niveau de la requête Mysqli Db::query() j'ai des erreurs Warning: Parameter 2 to mysqli_stmt::bind_param() expected to be a reference, value given
    Request est un vrai objet instancié, j'y ajoute des valeurs dans des tableaux. Quand je crée mon tableau $params il FAUT des références, donc je fais référence aux valeurs de mon objet instancié Request.
    Pourquoi alors est-ce que j'ai un problème de référence ?
    Pour éviter ces erreurs il faut que je remonte d'objet en objet jusqu'à la création de la valeur originale, ce qui me fait gérer des '&' partout dans mon code ! Et si par malheur je passe par des fonctions aux héritages un peu alambiqués le tableau perd la référence et garde seulement la valeur !
    Comment faire pour qu'il me suffise de donner toutes les valeurs à un objet Request sans passer par référence et faire référence uniquement en dernier ressort aux valeurs de CET objet LA (ligne 34 ci-dessus) ?

    Merci beaucoup pour votre aide !

  2. #2
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    lis la doc php sur l'utilisation de call_user_func_array avec mysqli_stmt::bind_param.

    Si tu ne veux pas traîner des & partout, tu devrais remplacer call_user_func_array par un simple foreach

  3. #3
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Points : 107
    Points
    107
    Par défaut
    sauf que la doc pour bind_param http://php.net/manual/fr/mysqli-stmt.bind-param.php dit que
    Le nombre de variables et la longueur de la chaîne de caractères types doivent correspondre aux paramètres de la requête.
    Et on ne peut en plus pas appeler bind_parapm plusieurs fois. Donc on ne peut pas faire de foreach avec la fonction bind_param.

    Comme j'arrive obligatoirement avec un array de mes valeurs, je ne peut pas faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
    $stmt->bind_param('sssd', $code, $language, $official, $percent);
    d'où le fait que je sois parti sur call_user_func_array()

    Je me suis donc creusé les méninges et je me suis dit que puisqu'il faut de vraies variables pour passer la référence, je pouvais les créer à la volée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static function query($query, array $params, &$result){
    	$stmt = self::$cnx->prepare($query);
    	$p = array(0 => '');
    	foreach ($params as $k => $tab) {
    		$$k = $tab['value'];
    		$p[0] .= $tab['type'];
    		$p[] = &$$k;
    	}
    	call_user_func_array(array($stmt, 'bind_param'), $p);
    	$stmt->execute();
    	// et d'autres trucs
    }
    Et ça marche

    Par contre j'aimerai bien déporter ce petit hack hors de ma fonction en faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static function params($params) {
    	$p = array(0 => '');
    	foreach ($params as $k => $tab) {
    		$$k = $tab['value'];
    		$p[0] .= $tab['type'];
    		$p[] = &$$k;
    	}
    	return $p;
    }
    public static function query($query, array $params, &$result){
    	$stmt = self::$cnx->prepare($query);
    	$p = self::params($params);
    	call_user_func_array(array($stmt, 'bind_param'), $params);
    	$stmt->execute();
    	// et d'autres trucs
    }
    mais si j'ai bien les références à l'intérieur de params(), ça devient des valeurs normales une fois le tableau donné à $p dans query(). Ce que je comprends parce que les variables créées étaient à l'intérieur de params(). Y aurait-il un moyen pour que l'externalisation fonctionne ?

  4. #4
    Membre régulier
    Profil pro
    Développeur Web
    Inscrit en
    Octobre 2010
    Messages
    153
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Octobre 2010
    Messages : 153
    Points : 107
    Points
    107
    Par défaut
    Bon ben j'ai ma solution.
    En fait je peux le faire de manière plus simple encore et mon soucis en testant cette solution précédemment c'est que je ne mettais pas la référence sur la bonne chose.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $p = array(0 => $params[0]);
    foreach ($params as $k => $v) {
    	if ($k != 0) $p[$k] = & $v;
    }
    ne marchait pas car je mettais la référence sur la valeur ! Or il faut mettre la référence sur l'index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $p = array(0 => $params[0]);
    foreach ($params as $k => $v) {
    	if ($k != 0) $p[$k] = & $params[$k]['value']; // ou &$params[$k] si la valeur à récupérer est directement le $v du foreach et non dans un sous-tableau
    }
    DONE !

  5. #5
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    ton code étant incomplet, j'ai du mal à m'y retrouver quand je te parlais du foreach, je te disais simplement de tester un truc de genre : foreach ($data as $k => &$v), c'est à dire garder le référence vers la valeur au moment du binding

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Passage par référence
    Par e1lauren dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 01/09/2006, 12h59
  2. Passage par copie vs passage par référence
    Par bolhrak dans le forum C++
    Réponses: 11
    Dernier message: 20/08/2006, 23h37
  3. Réponses: 4
    Dernier message: 26/12/2005, 17h01
  4. Passage par référence
    Par difficiledetrouver1pseudo dans le forum Langage
    Réponses: 9
    Dernier message: 28/09/2005, 11h17
  5. Problème très rapide de passage par référence
    Par Noxexplorer dans le forum ASP
    Réponses: 2
    Dernier message: 23/06/2005, 10h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo