web-dev-qa-db-fra.com

Quand utiliser soi-même plus de $ ceci?

Dans PHP 5, quelle est la différence entre self et $this?

Quand est-ce approprié?

1924
Casey Watson

Réponse courte

Utilisez $this pour faire référence à l'objet actuel. Utilisez self pour faire référence à la classe actuelle. En d'autres termes, utilisez $this->member pour les membres non statiques, utilisez self::$member pour les membres statiques.

Réponse complète

Voici un exemple d'utilisation correcte de - de $this et de self pour des variables de membre non statiques et statiques:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

Voici un exemple d'utilisation incorrecte de $this et self pour des variables de membre non statiques et statiques:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

Voici un exemple de polymorphisme avec $this pour les fonctions membres:

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

Voici un exemple de suppression du comportement polymorphe en utilisant self pour les fonctions membres:

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

L'idée est que $this->foo() appelle la fonction membre foo() de quel que soit le type exact de l'objet actuel. Si l'objet est de type X, il appelle donc X::foo(). Si l'objet est de type Y, il appelle Y::foo(). Mais avec self :: foo (), X::foo() est toujours appelé.

De http://www.phpbuilder.com/board/showthread.php?t=10354489 :

Par http://board.phpbuilder.com/member.php?145249-laserlight

1644
John Millikin

Le mot-clé self NOT fait simplement référence à la "classe actuelle", du moins pas d'une manière qui vous limite aux membres statiques. Dans le contexte d'un membre non statique, self fournit également un moyen de contourner la vtable ( voir le wiki sur vtable ) pour l'objet actuel. De même que vous pouvez utiliser parent::methodName() pour appeler la version parents d'une fonction, vous pouvez également appeler self::methodName() pour appeler l'implémentation en cours d'une méthode.

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

Cela produira:

Bonjour, je suis Ludwig le geek
Au revoir de Ludwig la personne

sayHello() utilise le pointeur $this. La vtable est donc appelée pour appeler Geek::getTitle(). sayGoodbye() utilise self::getTitle(), la vtable n'est donc pas utilisée et Person::getTitle() est appelée. Dans les deux cas, nous traitons de la méthode d'un objet instancié et avons accès au pointeur $this dans les fonctions appelées.

733
nbeagle

N'UTILISEZ PAS _self::_, utilisez _static::_

Il y a un autre aspect de soi :: qui mérite d'être mentionné. Ce qui est contrariant _self::_ fait référence à la portée au moment de la définition et non au moment de l’exécution . Considérez cette classe simple avec deux méthodes:

_class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}
_

Si nous appelons Person::status() nous verrons "La personne est en vie". Maintenant, considérons ce qui se passe lorsque nous faisons une classe qui hérite de ceci:

_class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}
_

En appelant Deceased::status(), nous nous attendrions à voir "La personne est décédée". Cependant, nous voyons que "La personne est en vie", car la portée contient la définition de méthode originale lorsque l'appel à self::getStatus() a été défini.

PHP 5.3 a une solution. l'opérateur de résolution static:: implémente la "liaison statique tardive", ce qui est une manière élégante de dire qu'elle est liée à la portée de la classe appelée. Modifiez la ligne dans status() en static::getStatus() et vous obtiendrez les résultats escomptés. Dans les anciennes versions de PHP, vous devrez trouver un kludge pour le faire.

Voir Documentation PHP

Donc, pour répondre à la question pas comme demandé ...

_$this->_ fait référence à l'objet actuel (une instance d'une classe), alors que _static::_ fait référence à une classe

449
Sqoo

Pour bien comprendre ce dont nous parlons lorsque nous parlons de self par rapport à $this, nous devons creuser ce qui se passe au niveau conceptuel et pratique. Je ne pense pas que les réponses donnent une réponse appropriée, voici donc ma tentative.

Commençons par parler de ce que sont un objet et un objet .

Classes Et Objets, Conceptuellement

Alors, quel est a classe ? Beaucoup de gens le définissent comme un modèle ou un modèle pour un objet. En fait, vous pouvez en lire plus À propos des classes dans PHP Ici . Et dans une certaine mesure, c'est ce que c'est vraiment. Regardons une classe:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

Comme vous pouvez le constater, il existe une propriété sur cette classe appelée $name et une méthode (fonction) appelée sayHello().

Il est important très de noter que la classe est une structure statique. Ce qui signifie que la classe Person, une fois définie, est toujours la même où que vous regardiez.

En revanche, un objet est ce qu'on appelle une instance d'une classe. Ce que cela signifie, c'est que nous prenons le "plan" de la classe et l'utilisons pour créer une copie dynamique. Cette copie est maintenant spécifiquement liée à la variable dans laquelle elle est stockée. Par conséquent, toute modification apportée à une instance est locale pour cette instance.

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

Nous créons de nouvelles instances d'une classe à l'aide de l'opérateur new.

Par conséquent, nous disons qu'une classe est une structure globale et qu'un objet est une structure locale. Ne vous inquiétez pas de cette drôle de syntaxe ->, nous allons l'expliquer dans un instant.

Une autre chose dont nous devrions parler, c'est que nous pouvons vérifier si une instance est un instanceof une classe particulière: $bob instanceof Person qui retourne un booléen si le L'instance $bob a été créée à l'aide de la classe Person, ou d'un enfant de Person.

Etat définissant

Alors, creusons un peu ce que contient une classe. Il y a 5 types de "choses" qu'une classe contient:

  1. Propriétés - Considérez-les comme des variables que chaque instance contiendra.

    class Foo {
        public $bar = 1;
    }
    
  2. Propriétés statiques - Considérez-les comme des variables partagées au niveau de la classe. Cela signifie qu'ils ne sont jamais copiés par chaque instance.

    class Foo {
        public static $bar = 1;
    }
    
  3. Méthodes - Il s'agit de fonctions que chaque instance contiendra (et agira sur des instances).

    class Foo {
        public function bar() {}
    }
    
  4. Méthodes statiques - Il s'agit de fonctions partagées par toute la classe. Ils font not == opèrent sur les instances, mais uniquement sur les propriétés statiques.

    class Foo {
        public static function bar() {}
    }
    
  5. Constantes - Constantes résolues par classe. Ne pas aller plus loin ici, mais en ajoutant pour être complet:

    class Foo {
        const BAR = 1;
    }
    

Donc, fondamentalement, nous stockons des informations sur la classe et le conteneur d’objets en utilisant des "astuces" sur static , qui identifient si les informations sont partagées (et donc statiques) ou non (et donc dynamiques). ).

Etat et Méthodes

À l'intérieur d'une méthode, l'instance d'un objet est représentée par la variable $this. L'état actuel de cet objet est là, et la modification (modification) de toute propriété entraînera une modification de cette instance (mais pas des autres).

Si une méthode est appelée de manière statique, la variable $this n'est pas définie . En effet, aucune instance n'est associée à un appel statique.

La chose intéressante ici est la façon dont les appels statiques sont effectués. Alors parlons de la façon dont nous accédons à l'état:

État d'accès

Alors maintenant que nous avons stocké cet état, nous devons y accéder. Cela peut devenir un peu délicat (ou manière plus que peu), divisons donc cela en deux points de vue: de l'extérieur d'une instance/classe (par exemple à partir d'un appel de fonction normal, ou de la portée globale), et à l'intérieur d'une instance/classe (à partir d'une méthode sur l'objet).

De l'extérieur d'une instance/classe

En dehors d'une instance/classe, nos règles sont assez simples et prévisibles. Nous avons deux opérateurs, et chacun nous dit immédiatement s'il s'agit d'une instance ou d'une classe statique:

  • -> - opérateur-objet - Ceci est toujours utilisé lorsque nous avons accès à une instance.

    $bob = new Person;
    echo $bob->name;
    

    Il est important de noter que l'appel de Person->foo n'a pas de sens (puisque Person est une classe, pas une instance). C'est donc une erreur d'analyse.

  • :: - scope-resolution-operator - Ceci est toujours utilisé pour accéder à une propriété ou à une méthode de classe statique.

    echo Foo::bar()
    

    De plus, nous pouvons appeler une méthode statique sur un objet de la même manière:

    echo $foo::bar()
    

    Il est important de noter que lorsque nous faisons cela de l'extérieur , l'instance de l'objet est masquée par la méthode bar(). Cela signifie que c'est exactement la même chose que de courir:

    $class = get_class($foo);
    $class::bar();
    

Par conséquent, $this n'est pas défini dans l'appel statique.

De l'intérieur d'une instance/classe

Les choses changent un peu ici. Les mêmes opérateurs sont utilisés, mais leur signification devient considérablement floue.

L'opérateur d'objet -> est toujours utilisé pour effectuer des appels vers l'état d'instance de l'objet.

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

L'appel de la méthode bar() sur $foo (une instance de Foo) à l'aide de l'opérateur d'objet: $foo->bar() entraînera la version de l'instance de $a.

C'est ce que nous attendons.

La signification de l'opérateur :: bien que modifiée. Cela dépend du contexte de l'appel à la fonction en cours:

  • Dans un contexte statique

    Dans un contexte statique, tous les appels effectués à l'aide de :: seront également statiques. Regardons un exemple:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    L'appel de Foo::bar() appellera la méthode baz() de manière statique, et donc $this sera not être rempli. Il convient de noter que, dans les versions récentes de PHP (5.3+), ceci provoquera une erreur E_STRICT, car nous appelons des méthodes non statiques de manière statique.

  • Dans un contexte d'instance

    D'autre part, dans un contexte d'instance, les appels effectués à l'aide de :: dépendent du destinataire de l'appel (la méthode que nous appelons). Si la méthode est définie comme static, elle utilisera un appel statique. Si ce n'est pas le cas, il transmettra les informations sur l'instance.

    Donc, en regardant le code ci-dessus, appeler $foo->bar() retournera true, puisque l'appel "statique" se produit à l'intérieur d'un contexte d'instance.

Avoir un sens? Je ne le pensais pas. C'est confu.

Mots-clés raccourcis

Parce que tout lier en utilisant des noms de classe est plutôt sale, PHP fournit 3 mots-clés de "raccourci" de base pour faciliter la résolution de périmètre.

  • self - Ceci fait référence au nom de la classe actuelle. Donc, self::baz() est identique à Foo::baz() dans la classe Foo (n'importe quelle méthode).

  • parent - Ceci fait référence au parent de la classe en cours.

  • static - Ceci fait référence à la classe appelée. Grâce à l'héritage, les classes enfants peuvent remplacer des méthodes et des propriétés statiques. Donc, les appeler en utilisant static au lieu d’un nom de classe nous permet de déterminer l’origine de l’appel plutôt que le niveau actuel.

Exemples

La meilleure façon de comprendre cela est de commencer à regarder quelques exemples. Choisissons un cours:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

Maintenant, nous examinons également l'héritage ici. Ignorer un instant qu'il s'agit d'un mauvais modèle d'objet, mais regardons ce qui se passe lorsque nous jouons avec ceci:

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

Ainsi, le compteur d'ID est partagé entre les deux instances et les enfants (car nous utilisons self pour y accéder. Si nous utilisions static, nous pourrions le remplacer dans une classe enfant).

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

Notez que nous exécutons la méthode Person::getName() à chaque fois. Mais nous utilisons la parent::getName() pour le faire dans l’un des cas (le cas enfant). C'est ce qui rend cette approche puissante.

Mot de prudence # 1

Notez que le contexte d'appel est ce qui détermine si une instance est utilisée. Donc:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

N'est-ce pas toujours vrai.

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

Maintenant, c'est vraiment bizarre ici. Nous appelons une classe différente, mais le $this qui est transmis à la méthode Foo::isFoo() est l'instance de $bar.

Cela peut causer toutes sortes de bugs et conceptuels WTF-ery. Je suggérerais donc fortement d'éviter l'opérateur :: dans les méthodes d'instance, sauf pour ces trois mots clés "raccourcis" virtuels (static, self et parent). .

Mot de prudence n ° 2

Notez que les méthodes et propriétés statiques sont partagées par tout le monde. Cela les rend fondamentalement des variables globales. Avec tous les mêmes problèmes qui viennent avec globals. Donc, j'hésiterais vraiment à stocker des informations dans des méthodes/propriétés statiques, à moins que vous ne soyez à l'aise avec le fait que ce soit vraiment global.

Mot de prudence # 3

En général, vous voudrez utiliser ce que l'on appelle Late-Statique-Binding en utilisant static au lieu de self. Notez cependant qu’il ne s’agit pas de la même chose, alors dire "utilisez toujours static au lieu de self est vraiment à courte vue. Au lieu de cela, réfléchissez à l’appel que vous voulez faire et pensez si vous le souhaitez. les classes enfant doivent pouvoir remplacer cet appel résolu par statique .

TL/DR

Dommage, retournez le lire. C'est peut-être trop long, mais c'est tellement long parce que c'est un sujet complexe

TL/DR # 2

OK bien. En bref, self est utilisé pour référencer le nom de la classe actuelle dans une classe, où $this fait référence à l'objet actuel exemple. Notez que self est un raccourci copier/coller. Vous pouvez le remplacer en toute sécurité par le nom de votre classe et tout ira bien. Mais $this est une variable dynamique qui ne peut pas être déterminée à l'avance (et peut-être même pas votre classe).

TL/DR # 3

Si l'opérateur d'objet est utilisé (->), vous savez toujours que vous avez affaire à une instance. Si l'opérateur de résolution est utilisé (::), vous avez besoin d'informations supplémentaires sur le contexte (sommes-nous déjà dans un contexte d'objet? Sommes-nous en dehors d'un objet? Etc.).

241
ircmaxell

self (pas $ self) fait référence au type de la classe, où comme $this se réfère au courant instance de la classe. self est utilisé dans les fonctions de membre statique pour vous permettre d'accéder aux variables de membre statique. $this est utilisé dans les fonctions membres non statiques et constitue une référence à l'instance de la classe sur laquelle la fonction membre a été appelée.

Comme this est un objet, vous l'utilisez comme: $this->member

Comme self n’est pas un objet, c’est essentiellement un type qui fait automatiquement référence à la classe actuelle, vous l’utilisez comme suit: self::member

115
MrZebra

$this-> est utilisé pour faire référence à une instance spécifique de variables d'une classe (variables membres) ou de méthodes.

Example: 
$derek = new Person();

$ derek est maintenant une instance spécifique de Person. Chaque personne a un prénom et un nom, mais $ derek a un prénom et un nom spécifiques (Derek Martin). Dans l'instance $ derek, nous pouvons nous référer à ceux-ci comme $ this-> prénom_nom et $ this-> dernier_nom

ClassName :: est utilisé pour faire référence à ce type de classe et à ses variables statiques, méthodes statiques. Si cela vous aide, vous pouvez remplacer mentalement le mot "statique" par "partagé". Parce qu'ils sont partagés, ils ne peuvent pas faire référence à $ this, qui fait référence à une instance spécifique (non partagée). Les variables statiques (c'est-à-dire que statique $ db_connection) peuvent être partagées entre toutes les instances d'un type d'objet. Par exemple, tous les objets de base de données partagent une seule connexion (static $ connection).

Exemple de variables statiques: Prétendons que nous avons une classe de base de données avec une seule variable membre: static $ num_connections; Maintenant, mettez ceci dans le constructeur:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

Tout comme les objets ont des constructeurs, ils ont aussi des destructeurs, qui sont exécutés lorsque l'objet meurt ou n'est pas défini:

function __destruct()
{
    $num_connections--;
}

Chaque fois que nous créons une nouvelle instance, notre compteur de connexions augmente d’un compteur. Chaque fois que nous détruisons ou cessons d'utiliser une instance, le compteur de connexion diminue d'un compteur. De cette manière, nous pouvons surveiller le nombre d'instances de l'objet de base de données utilisé:

echo DB::num_connections;

Comme $ num_connections est statique (partagé), il reflétera le nombre total d'objets de base de données actifs. Vous avez peut-être vu cette technique utilisée pour partager des connexions de base de données entre toutes les instances d'une classe de base de données. Ceci est fait car la création de la connexion à la base de données prend beaucoup de temps, il est donc préférable de n'en créer qu'une et de la partager (cela s'appelle un motif Singleton).

Des méthodes statiques (par exemple, public statique View :: format_phone_number ($ digits)) peuvent être utilisées SANS la première instanciation d’un de ces objets (c’est-à-dire qu’elles ne font pas référence à $ this).

Exemple de méthode statique:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

Comme vous pouvez le constater, la fonction statique publique prettyName ne sait rien de l'objet. Il s'agit simplement de travailler avec les paramètres que vous transmettez, comme une fonction normale qui ne fait pas partie d'un objet. Pourquoi s'embêter, alors, si nous pouvions simplement l'avoir comme partie intégrante de l'objet?

  1. Tout d’abord, l’attachement de fonctions à des objets vous permet de garder les choses organisées afin que vous sachiez où les trouver.
  2. Deuxièmement, cela évite les conflits de noms. Dans un grand projet, il est probable que deux développeurs créent des fonctions getName (). Si l'un crée un ClassName1 :: getName () et que l'autre crée ClassName2 :: getName (), il n'y a aucun problème. Pas de conflit. Yay méthodes statiques!

SELF :: Si vous codez à l'extérieur de l'objet contenant la méthode statique à laquelle vous souhaitez faire référence, vous devez l'appeler. en utilisant le nom de l'objet View :: format_phone_number ($ phone_number); Si vous codez à l'intérieur de l'objet contenant la méthode statique à laquelle vous souhaitez faire référence, vous pouvez soit utilisez le nom de l'objet View :: format_phone_number ($ pn), OR, vous pouvez utiliser le raccourci self :: format_phone_number ($ pn)

Il en va de même pour les variables statiques: Exemple: View :: templates_path versus self :: templates_path

Dans la classe DB, si nous faisions référence à une méthode statique d'un autre objet, nous utiliserions le nom de l'objet: Exemple: Session :: getUsersOnline ();

Mais si la classe DB voulait se référer à sa propre variable statique, elle dirait simplement self: Exemple: self :: connection;

J'espère que ça aide à clarifier les choses :)

96
lo_fye

De cet article de blog :

  • self fait référence à la classe actuelle
  • self peut être utilisé pour appeler des fonctions statiques et référencer des variables membres statiques
  • self peut être utilisé dans des fonctions statiques
  • self peut également désactiver le comportement polymorphe en contournant la vtable
  • $this fait référence à l'objet actuel
  • $this peut être utilisé pour appeler des fonctions statiques
  • $this ne doit pas être utilisé pour appeler des variables de membre statique. Utilisez self à la place.
  • $this ne peut pas être utilisé à l'intérieur de fonctions statiques
29
okconfused

En PHP, vous utilisez le mot-clé self pour accéder aux propriétés et méthodes statiques.

Le problème est que vous pouvez remplacer $this->method() par self::method() n'importe où, même si method() est déclaré statique ou non. Alors lequel devriez-vous utiliser?

Considérons ce code:

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

Dans cet exemple, self::who() affichera toujours ‘parent’, tandis que $this->who() dépendra de la classe de l’objet.

Nous pouvons maintenant voir que self fait référence à la classe dans laquelle il est appelé, tandis que $this fait référence à classe de l'objet en cours.

Vous ne devez donc utiliser self que lorsque $this n'est pas disponible ou lorsque vous ne souhaitez pas autoriser les classes descendantes à remplacer la méthode actuelle.

25
ramin rostami

Dans une définition de classe, $ this fait référence à l'objet actuel, tandis que self fait référence à la classe actuelle.

Il est nécessaire de faire référence à un élément de classe à l'aide de self et à un élément d'objet à l'aide de $ this.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
21
Tarun Singhal

Voici un exemple d'utilisation correcte de $ this et self pour les variables de membre non statiques et statiques:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?> 
20
Mohit Bumb

Selon http://www.php.net/manual/en/language.oop5.static.php il n'y a pas de $self. Il n'y a que $this, pour faire référence à l'instance actuelle de la classe (l'objet), et self, qui peut être utilisé pour faire référence à des membres statiques d'une classe. La différence entre une instance d'objet et une classe entre en jeu ici.

20
cruizer

self fait référence à la classe actuelle (dans laquelle elle est appelée),

$this fait référence à l'objet actuel. Vous pouvez utiliser statique au lieu de soi. Voir l'exemple:

    class ParentClass {
            function test() {
                    self::which();  // output 'parent'
                    $this->which(); // output 'child'
            }

            function which() {
                    echo 'parent';
            }
    }

    class ChildClass extends ParentClass {
            function which() {
                    echo 'child';
            }
    }

    $obj = new ChildClass();
    $obj->test();

Sortie: enfant parent

15
Kabir Hossain

Je crois que la question n'était pas de savoir si vous pouvez appeler le membre statique de la classe en appelant ClassName::staticMember. La question était quelle était la différence entre utiliser self::classmember et $this->classmember.

Par exemple, les deux exemples suivants fonctionnent sans erreur, que vous utilisiez self:: ou $this->

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}
14
dr evil

Comme personne ici n’a parlé de performances, voici un petit repère que j’ai fait (5.6):

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

Ce sont les résultats pour 2 000 000 courses, et voici le code que j'ai utilisé:

<?php

require '../vendor/autoload.php';

// My small class to do benchmarks
// All it does is looping over every test x times and record the
//   time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);

class Foo
{
    public function calling_this()
    {
        $this->called();
    }

    public function calling_self()
    {
        self::called();
    }

    public function calling_static()
    {
        static::called();
    }

    public static function called()
    {
    }
}

$b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

$b->run();
14
tleb
  • Le pointeur d'objet $ this to fait référence à l'objet actuel.
  • La valeur de classe "statique" fait référence à l'objet actuel.
  • La valeur de classe "self" fait référence à la classe exacte dans laquelle elle a été définie.
  • La valeur de classe "parent" fait référence au parent de la classe exacte dans laquelle elle a été définie.

Voir l'exemple suivant qui montre la surcharge.

<?php

class A {

    public static function newStaticClass()
    {
        return new static;
    }

    public static function newSelfClass()
    {
        return new self;
    }

    public function newThisClass()
    {
        return new $this;
    }
}

class B extends A
{
    public function newParentClass()
    {
        return new parent;
    }
}


$b = new B;

var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A


class C extends B
{
    public static function newSelfClass()
    {
        return new self;
    }
}


$c = new C;

var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"

La plupart du temps, vous voulez faire référence à la classe actuelle, raison pour laquelle vous utilisez static ou $this. Cependant, il y a des moments où vous besoinself parce que vous voulez la classe d'origine quelle que soit son extension. (Très, très rarement)

14
Xeoncross

Lorsque self est utilisé avec l'opérateur ::, il fait référence à la classe actuelle, ce qui peut être fait à la fois dans des contextes statiques et non statiques. $this fait référence à l'objet lui-même. De plus, il est parfaitement légal d'utiliser $this pour appeler des méthodes statiques (mais pas pour faire référence à des champs).

13
mrDjouk

$this se réfère à l'objet de la classe en cours, self se réfère à la classe en cours (Not object). La classe est le modèle de l'objet. Donc, vous définissez une classe, mais vous construisez des objets.

Donc, en d'autres termes, utilisez self for static et this for none-static members or methods.

également dans le scénario enfant/parent self / parent est principalement utilisé pour identifier les membres et méthodes de la classe enfant et parent.

7
Rakesh Singh

De plus, puisque $this:: n'a pas encore été discuté.

À titre informatif uniquement, à partir de PHP 5.3 lorsque vous utilisez des objets instanciés pour obtenir la valeur de la portée actuelle, par opposition à static::, vous pouvez également utiliser $this:: de cette manière.

http://ideone.com/7etRHy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

L'utilisation du code ci-dessus n'est pas une pratique courante ou recommandée, mais simplement pour illustrer son utilisation, et consiste plutôt à agir comme un "Le saviez-vous?" en référence à la question de l'affiche originale.

Il représente également l'utilisation de $object::CONSTANT par exemple echo $foo::NAME; par opposition à $this::NAME;

7
fyrye

J'ai rencontré la même question et la réponse simple est:

  • $ this nécessite une instance de la classe
  • self :: n'a pas

Chaque fois que vous utilisez méthodes statiques ou attributs statiques et que vous souhaitez les appeler sans qu'un objet de la classe ne soit instancié, vous devez utiliser self :: pour les appeler, car $ this nécessite toujours que l'objet soit créé.

6
Mike

Utilisez self si vous souhaitez appeler une méthode d'une classe sans créer un objet/une instance de cette classe, économisez ainsi RAM (utilisez parfois self à cette fin). En d'autres termes, il appelle en fait une méthode de manière statique. Utilisez this pour la perspective d'objet.

5
minhajul

Cas 1: Utiliser self peut être utilisé pour les constantes de classe

 class classA {
 const FIXED_NUMBER = 4; 
 self :: POUNDS_TO_KILOGRAMS 
} 

Si vous voulez l'appeler en dehors de la classe, utilisez classA::POUNDS_TO_KILOGRAMS pour accéder aux constantes.

Cas 2: Pour les propriétés statiques

 class classC {
 fonction publique __construct () {
 self :: $ _ counter ++; $ this-> num = self :: $ _ counter; 
} 
} 
2
li bing zhao

Selon php.net, il existe trois mots-clés spéciaux dans ce contexte: self, parent et static. Ils sont utilisés pour accéder aux propriétés ou aux méthodes depuis la définition de la classe.

$this, d'autre part, est utilisé pour appeler une instance et des méthodes de n'importe quelle classe tant que cette classe est accessible.

1
Fil