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 :

[POO] Méthode privée ou publique [PHP 5.2]


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Par défaut [POO] Méthode privée ou publique
    Bonjour,

    J'ai lu et relu les cours et tutos, en particulier ce chapitre, mais il doit vraiment y avoir un (gros) point que j'ai loupé :

    J'ai créé une méthode "private" dans une classe et pourtant, j'accede à cette méthode depuis le code avec un objet de cette classe, comme si la méthode avait été déclarée "public".

    Je souhaiterai ne pouvoir accéder à cette méthode QUE depuis l'intérieur de la classe.

    Qu'ais-je loupé .. ? Comment procéder pour que l'accès à ma méthode privée ne soit possible QUE depuis l'intérieur de la classe ?

    Je me doute bien que c'est une belle question de noob, mais même pas honte, même pas peur

    Merci d'avance


    Un extrait de la classe en question:
    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
    class PDO3 extends PDO2 {
     
    	/* Variables de la classe */
    	private $_debug		= false;
    	protected $_pdo		= NULL;
     
     
    	/* Constructeur : héritage public obligatoire par héritage de PDO */
    	public function __construct($pdo)
    	{
    		$pdo_ext = $this->checkPdoExtension();
     
    		if (isset($pdo) && $pdo_ext) {
     
    			$this->_pdo = $pdo;
     
    		}
    		else {
    			throw new PDOException("No pdo connection");
    		}
    	}
    	/**
    	* Comptage du nbre enregistrements DISTINCTS pour un champ donné avec condition (par requête préparée)
    	* @return	: $count
    	*/
    	private function countDistinct($table_name, $field, $sql_condition) {
     
    		$sql_prep = "SELECT DISTINCT $field FROM $table_name WHERE $sql_condition" ;
    		$query	= $this->_pdo->prepare($sql_prep) ;
    		$query->execute();
    		$count = count($query->fetchColumn());
    		$query->closeCursor();
    		return $count;
    	}
     
    	/**
    	* Comptage du nbre enregistrements DISTINCTS pour un champ donné avec condition (par requete préparée)
    	* @return	: $count
    	*/
     
    	public function isUnique($table_name, $field, $sql_condition) {
    		// méthode alternative : voir http://php.developpez.com/faq/?page=pdo#pdo-count
     
    		$count = $this->countDistinct($table_name, $field, $sql_condition) ;
     
    		$unique = ($count == 1) ? true : false ;
     
    		return $unique;
    	}
    Et depuis le code, j'accède aussi bien à la méthode publique qu'à la méthode privée, alors que je pensais - voire j'espérais - me faire renvoyer sur une erreur du style Fatal error: Cannot access private method, mais non, pas d'erreur, et la méthode - supposée privée - me renvoie bien les bonnes valeurs... :
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $count = $pdo->countDistinct($table_name, $field, $sql_condition);
    $unique = ($pdo->isUnique($table_name, $field, $sql_condition))? "ok":"nok";
    if (DEBUG) echo "<br/>DEBUG: unique= $unique ($count)";

    Je n'arrive pas à trouver la cause de ce problème.

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    625
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 625
    Par défaut
    J'ai créé une méthode "private" dans une classe et pourtant, j'accepte à cette méthode depuis le code avec un objet de cette classe, comme si la méthode avait été déclarée "public".

    Je souhaiterai ne pouvoir accéder à cette méthode QUE depuis l'intérieur de la classe.

    Qu'ais-je loupé .. ? Comment procéder pour que l'accès à ma méthode privée ne soit possible QUE depuis l'intérieur de la classe ?
    private limite la visibilité au niveau de la classe... pas de l'instance.

    pour un petit exemple simple :

    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
    class A{
    	private $val;
     
    	function __construct( $val ){
    		$this->val = $val;
    	}
     
    	function test( A $a ){
    		echo $a->val;
    	}
    }
     
    $a = new A( 'titi' );
    $a->test( $a );
     
    $b = new A( 'toto' );
    $a->test( $b );
    Vu que $a est un A et $b est un A, $a accède aux privées de $b.
    C'est un truc un peu déroutant et tordu et on peut dire que c'est logique... ou pas

    Ça a ses côtés pratiques mais ça peut être aussi dangereux.

  3. #3
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    @Petibidon
    Ca n'explique pas ce que rencontre hornetbzz selon moi.

    Dans ton exemple, théoriquement on ne peut pas faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $a->val = 'bidule'; // Pas possible : attribut privé
    C'est ce phénomène qu'il rencontre à mon sens.

    Si je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class machin {
    	private function bidule() {
    		echo 'bidule<br />';
    	}
    }
    $machin = new machin();
    $machin->bidule(); // Impossible : Méthode Privée
    C'est le coup bâton
    "Fatal error: Call to private method machin::bidule() from context".


    Je suis le 2ème noob qui ne pige pas pourquoi hornetbzz parvient à utiliser une méthode privée en-dehors de la classe.

  4. #4
    Membre chevronné Avatar de BornBanane
    Homme Profil pro
    dev
    Inscrit en
    Mars 2007
    Messages
    284
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : dev

    Informations forums :
    Inscription : Mars 2007
    Messages : 284
    Par défaut
    Citation Envoyé par Petibidon Voir le message
    Vu que $a est un A et $b est un A, $a accède aux privées de $b.
    C'est un truc un peu déroutant et tordu et on peut dire que c'est logique... ou pas
    Dans ton exemple $a n'accède pas à $b. Ce sont 2 objets (de la même classe) différents. A moins de passé $val en static, aucun des deux n'a accès au $val de l'autre.

    Pour en revenir à la question, une méthode "private" renvoie bel et bien un :
    Fatal error: Call to private method ....
    Dans ton cas, cela devrait aussi le faire.

    Dans ta classe PDO2 aurais-tu une méthode "countDistinct" publique ?

  5. #5
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Citation Envoyé par francoisIT
    Dans ta classe PDO2 aurais-tu une méthode "countDistinct" publique ?
    Bonne question

    Mais aussi, pourquoi pas : est-ce que $pdo est une instance de PDO3 ? (au lieu de PDO2, qui sait ? )
    Un peu plus tordu ... mais pareil ... même pas peur

  6. #6
    Membre chevronné
    Avatar de hornetbzz
    Homme Profil pro
    Directeur commercial
    Inscrit en
    Octobre 2009
    Messages
    482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France

    Informations professionnelles :
    Activité : Directeur commercial

    Informations forums :
    Inscription : Octobre 2009
    Messages : 482
    Par défaut
    Merci pour vos commentaires !

    Il semblerait que RunCode ait bien résumé ma question :
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class machin {
    	private function bidule() {
    		echo 'bidule<br />';
    	}
    }
    $machin = new machin();
    $machin->bidule(); // Impossible : Méthode Privée: et bien si, ça marche, c'est bien ça ma question

    Et l'appel s'effectue bien depuis l'extérieur de la classe, et pas depuis une autre classe ou une classe fille de PDO3 mais depuis le code PHP.

    Une petite précision qui peut éventuellement servir: PDO3 est une extension de la classe PDO2 (singleton de connexion à la db). Et PDO2 est une extension de PDO.

    A tout hasard, voila la classe PDO2:
    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
    class PDO2 extends PDO {
     
    	protected $_dbname = 'ma_db' ; // protected car utilisée dans classe fille PDO3
     
    	private static $_instance;
    	private static $_dsn	= 'mysql:host=127.0.0.1;dbname=ma_db' ;
    	private static $_dbuser	= 'user' ;
    	private static $_dbpwd	= 'password' ;
     
    	private static $_debug	= false ;
    	private static $_ipadmin= 'XXX.XXX.XXX.XXX' ;
     
     
    	/* Constructeur : héritage public obligatoire par héritage de PDO */
    	public function __construct( ) {
    	}
     
    	/* Singleton */
    	public static function getInstance() {
     
    		if (!isset(self::$_instance)) {
     
    			try {
    				self::$_instance = new PDO(self::$_dsn , self::$_dbuser , self::$_dbpwd);
    			}
    			catch (PDOException $e) {
    				if ( self::$_debug === true && ($_SERVER['REMOTE_ADDR'] == self::$_ipadmin) ) 	{
    					echo '<br>/PDO2 Erreur N° : '.$e->getCode();
    					echo '<br/>PDO2 Erreur : '.$e->getMessage().'<br />';
    					die();
    				}
    				else {
    					echo 'Erreur de la classe PDO2 - passer en mode DEBUG';
    					die();
    				}
    			}
    		}
    		return self::$_instance; 
    	}
     
    }
    Voilà comment j'instancie et utilise les objets dans le code PHP:

    Instanciation dans le code (hors de toute classe donc):
    Code PHP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    try {
    	$connect = PDO2::getInstance();
    	$pdo = new PDO3($connect);
    }
    catch (PDOException $e) {
    	$_SESSION['ERROR'] .= ERR_41 .': ' .$e->getMessage().'<br/>';
    	$securite = false;
    }
    Utilisation des méthodes de l'objet $pdo instancié plus haut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $count = $pdo->countDistinct($table_name, $field, $sql_condition);
    $unique = ($pdo->isUnique($table_name, $field, $sql_condition))? "ok":"nok";
    if (DEBUG) echo "<br/>DEBUG: unique= $unique ($count)";
    C'est surement une grosse boulette de ma part mais je ne vois pas laquelle.

  7. #7
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $connect = PDO2::getInstance();
    $pdo = new PDO3($connect);
    Je ne suis pas aficionados de l'objet, loin de là, mais ci-dessus me semble tordue (si je peux me permettre )

    Mon raisonnement est simple.
    Comme une classe fille hérite de la classe parente, pourquoi exploiter la classe PDO2 alors que le but final est d'exploiter PDO3 ?

    Je que je veux dire, c'est que j'aurais plûtot fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $connect = PDO3::getInstance();
    $pdo = new PDO3($connect);
    M'enfin, ça me semble un peu bizarre qu'il faille passer en argument une instance venant de la même classe (getInstance) pour au final obtenir une instance (du même objet).

    En tout cas, l'un comme l'autre, PDO3 serait totalement dépendant de sa propre méthode (getInstance), ou de PDO2, pour pouvoir être instancié.
    Ca va loin ton truc, faut s'accrocher


    Comme ça, vite dit, j'aurais déporter le code getInstance du PDO2 dans le constructeur (ou autre méthode static) dans PDO3.
    Mais ça risque de ne plus te convenir.


    Ceci dit, je ne parviens pas à expliquer le phénomène que tu rencontre.
    Peut être est ce le fait que getInstance() soit static ?
    Et que l'instance $pdo soit basé de PDO2 $connect ?
    C'est un peu l'embrouille, ça va un peu trop loin pour moi sur ce coup ci

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

Discussions similaires

  1. [POO] Méthode privée / Attribut public
    Par Benoit.44 dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 17/08/2013, 16h15
  2. Réponses: 6
    Dernier message: 07/01/2009, 10h57
  3. Réponses: 7
    Dernier message: 19/03/2007, 20h25
  4. Réponses: 4
    Dernier message: 17/03/2007, 01h06
  5. Réponses: 8
    Dernier message: 04/06/2004, 09h13

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