Contacts

Membres statiques de la classe. Ne les laissez pas ruiner votre code. Méthodes statiques PHP Dealer statique php p

Ce n'est un secret pour personne qu'ils aiment poser des questions délicates lors des entretiens. Pas toujours adéquat, pas toujours lié à la réalité, mais le fait demeure - ils demandent. Bien sûr, la question est différente de la question, et parfois une question qui à première vue vous semble stupide vise en réalité à tester votre niveau de connaissance de la langue dans laquelle vous écrivez.

Essayons de démonter une de ces questions "petit à petit" - que signifie le mot "statique" en PHP et pourquoi est-il utilisé ?

Le mot-clé static a trois significations différentes en PHP. Analysons-les par ordre chronologique, telles qu'elles apparaissent dans la langue.

La première valeur est une variable locale statique

fonction foo () ($ a = 0; echo $ a; $ a = $ a + 1;) foo (); // 0 truc (); // 0 truc (); // 0

En PHP, les variables sont locales. Cela signifie qu'une variable définie et affectée d'une valeur à l'intérieur d'une fonction (méthode) n'existe que pendant l'exécution de cette fonction (méthode). Lorsque la méthode se termine, la variable locale est détruite et lorsque la méthode est à nouveau saisie, elle est recréée. Dans le code ci-dessus, une telle variable locale est la variable $ a - elle n'existe qu'à l'intérieur de la fonction foo() et est recréée à chaque fois que cette fonction est appelée. Incrémenter une variable dans ce code n'a pas de sens, car sur la ligne de code suivante la fonction finira son travail et la valeur de la variable sera perdue. Peu importe combien de fois nous appelons la fonction foo (), elle produira toujours 0 ...

Cependant, tout change si l'on met le mot-clé static avant l'affectation :

Fonction foo () (static $ a = 0; echo $ a; $ a = $ a + 1;) foo (); // 0 truc (); // 1 truc (); // 2

Le mot-clé static, écrit avant d'affecter une valeur à une variable locale, a les effets suivants :

  1. L'affectation est effectuée une seule fois, la première fois que la fonction est appelée
  2. La valeur de la variable ainsi marquée est sauvegardée après la fin de la fonction
  3. Lors des appels ultérieurs à la fonction, au lieu de l'affectation, la variable reçoit la valeur précédemment enregistrée
Cette utilisation du mot statique est appelée variable locale statique.
Pièges des variables statiques
Bien sûr, comme toujours en PHP, il y a quelques pièges.

La première pierre est que seules des constantes ou des expressions constantes peuvent être affectées à une variable statique. Voici le code :
statique $ a = bar ();
conduira inévitablement à une erreur d'analyseur. Heureusement, à partir de la version 5.6, il est devenu possible d'affecter non seulement des constantes, mais également des expressions constantes (par exemple, "1 + 2" ou ""), c'est-à-dire des expressions qui ne dépendent pas d'un autre code et peuvent être calculées au moment de la compilation

La deuxième pierre - les méthodes existent en un seul exemplaire.
Tout est un peu plus compliqué ici. Pour comprendre l'essentiel, je vais donner le code :
classe A (fonction publique foo () (static $ x = 0; echo ++ $ x;)) $ a1 = new A; $ a2 = nouveau A ; $ a1-> foo (); // 1 $ a2-> foo (); // 2 $ a1-> foo (); // 3 $ a2-> foo (); // 4
Contrairement à l'attente intuitive « différents objets - différentes méthodes », nous pouvons clairement voir dans cet exemple que les méthodes dynamiques en PHP « ne se propagent pas ». Même si nous avons cent objets de cette classe, la méthode n'existera que dans une seule instance, juste un $ différent qui lui sera transmis à chaque fois qu'elle est appelée.

Ce comportement peut être inattendu pour un développeur non formé et peut être une source d'erreurs. Il est à noter qu'hériter d'une classe (et d'une méthode) conduit au fait qu'une nouvelle méthode est toujours créée :

Classe A (fonction publique foo () (statique $ x = 0; echo ++ $ x;)) la classe B étend A () $ a1 = nouveau A; $ b1 = nouveau B ; $ a1-> foo (); // 1 $ b1-> foo (); // 1 $ a1-> foo (); // 2 $ b1-> foo (); // 2

Conclusion : les méthodes dynamiques en PHP existent dans le contexte des classes, pas des objets. Et ce n'est qu'à l'exécution qu'il y a une substitution "$ this = current_object"

Deuxième sens - propriétés statiques et méthodes des classes

Dans le modèle objet PHP, il est possible de définir des propriétés et des méthodes non seulement pour les objets - instances d'une classe, mais aussi pour la classe dans son ensemble. Le mot-clé static est également utilisé pour cela :

Classe A (public static $ x = "foo"; public static function test () (retour 42;)) echo A :: $ x; // "foo" echo A :: test (); // 42
Pour accéder à ces propriétés et méthodes, des constructions à double virgule ("Paamayim Nekudotayim") telles que CLASSNAME :: $ VariableName et CLASSNAME :: MethodName () sont utilisées.

Il va sans dire que les propriétés statiques et les méthodes statiques ont leurs propres bizarreries et pièges dont il faut être conscient.

La première fonctionnalité est banale - il n'y a pas de $ this. En fait, cela découle de la définition même d'une méthode statique - puisqu'elle est associée à une classe, pas à un objet, la pseudo-variable $ this n'y est pas disponible, qui pointe vers l'objet courant dans les méthodes dynamiques. Ce qui est parfaitement logique.

Cependant, vous devez savoir que, contrairement à d'autres langages, PHP ne détecte pas la situation "$ ceci est écrit dans une méthode statique" au stade de l'analyse ou de la compilation. Cette erreur ne peut se produire qu'à l'exécution si vous essayez d'exécuter du code avec $ this dans une méthode statique.

Un code comme celui-ci :
classe A (public $ id = 42 ; fonction publique statique foo () (écho $ this-> id ;))
ne conduira à aucune erreur à moins que vous n'essayiez d'utiliser la méthode foo () de manière inappropriée :
$ a = nouveau A ; $ a-> foo (); (et obtenez immédiatement "Erreur fatale : utiliser $ this lorsqu'il n'est pas dans le contexte de l'objet")

La deuxième caractéristique est que la statique n'est pas un axiome !
classe A (fonction publique statique foo () (echo 42;)) $ a = new A; $ a-> foo ();
C'est vrai, oui. Une méthode statique, si elle ne contient pas $ this dans votre code, peut être appelée dans un contexte dynamique comme une méthode objet. Ce n'est pas un bug de PHP.

L'inverse n'est pas tout à fait vrai :
classe A (fonction publique foo () (echo 42;)) A :: foo ();
Une méthode dynamique qui n'utilise pas $ this peut être exécutée dans un contexte statique. Cependant, vous recevrez un avertissement de niveau E_STRICT "La méthode non statique A :: foo () ne doit pas être appelée statiquement". C'est à vous de décider de suivre strictement les normes du code ou de supprimer les avertissements. Le premier est bien entendu préférable.

Et au fait, tout ce qui est écrit ci-dessus ne s'applique qu'aux méthodes. L'utilisation d'une propriété statique via "->" est impossible et conduit à une erreur fatale.

Le troisième sens, apparemment le plus difficile, est la liaison statique tardive.

Les développeurs du langage PHP ne se sont pas arrêtés à deux sens du mot-clé "statique" et ont ajouté dans la version 5.3 une autre "fonctionnalité" du langage, qui est implémentée par le même mot ! On l'appelle Late Static Binding ou LSB.

La façon la plus simple de comprendre l'essence de LSB est d'utiliser des exemples simples :

Modèle de classe (public static $ table = "table"; public static function getTable () (return self :: $ table;)) echo Model :: getTable (); // "tableau"
Le mot-clé self en PHP signifie toujours "le nom de la classe où ce mot est écrit". Dans ce cas, self est remplacé par la classe Model et self :: $ table est remplacé par Model :: $ table.
Cette capacité de langage est appelée liaison statique précoce. Pourquoi tôt ? Parce que la liaison de self et d'un nom de classe spécifique ne se produit pas au moment de l'exécution, mais à des étapes antérieures - l'analyse et la compilation du code. Eh bien, "statique" - parce que nous parlons de propriétés et de méthodes statiques.

Modifions un peu notre code :

Modèle de classe (public static $ table = "table"; public static function getTable () (return self :: $ table;)) class L'utilisateur étend le modèle (public static $ table = "users";) echo User :: getTable () ; // "tableau"

Vous comprenez maintenant pourquoi PHP se comporte de manière peu intuitive dans cette situation. self était associé à la classe Model à une époque où l'on ne savait rien de la classe User, c'est pourquoi elle pointe vers Model.

Comment être?

Pour résoudre ce dilemme, un mécanisme de liaison "tardive", au stade de l'exécution, a été inventé. Cela fonctionne très simplement - il suffit d'écrire "static" à la place du mot "self" et la connexion sera établie avec la classe qui appelle le code donné, et non avec celle où il est écrit :
class Model (public static $ table = "table"; public static function getTable () (return static :: $ table;)) class L'utilisateur étend le modèle (public static $ table = "users";) echo User :: getTable () ; // "utilisateurs"

Il s'agit de la "liaison statique tardive" cryptique.

Il est à noter que pour plus de commodité en PHP, outre le mot "static", il existe également une fonction spéciale get_call_class(), qui vous indiquera dans le contexte de quelle classe votre code est en cours d'exécution.

Bonnes entrevues !



Il existe deux types de développeurs PHP dans le monde. Certains préfèrent les méthodes statiques parce qu'elles sont faciles à utiliser, tandis que d'autres, au contraire, considèrent les méthodes statiques comme mauvaises et ne les utilisent pas dans leur pratique.
Dans cet article, je vais essayer, en utilisant mon expérience avec plusieurs frameworks, d'expliquer pourquoi certains développeurs ignorent les meilleures pratiques et utilisent tout un tas de méthodes statiques.

Qui aime les méthodes statiques ?

Ils sont particulièrement souvent utilisés par les développeurs qui ont déjà utilisé le framework CodeIgniter dans leur travail.

Aussi, la plupart des développeurs Kohana et Laravel font partie des adeptes des méthodes statistiques.
On ne peut que mentionner le fait que les programmeurs qui décident de commencer à écrire leurs propres choses refusent généralement d'utiliser CodeIgniter.

Pourquoi demandes-tu?

CodeIgniter supportait PHP 4 avant que les méthodes statiques ne soient ajoutées dans PHP 5. De plus, CodeIgniter utilise un "super objet" qui fournit un accès égal à toutes les classes affectées à un contrôleur. Ainsi, ils deviennent disponibles pour une utilisation dans tout le système.

Cela signifie que les classes sont accessibles à partir de n'importe quel modèle à l'aide de la méthode __get (), qui recherchera la propriété demandée en utilisant get_instance () -> ($ var)... Auparavant, lorsque la fonction __get () n'était pas prise en charge dans PHP 4, la construction foreach était utilisée pour cela via les paramètres CI_Controller, puis elle était affectée à la variable $ this dans le modèle.

Dans la bibliothèque, vous devez appeler get_instance. La bibliothèque n'applique pas la classe, il n'y a donc aucun moyen de contourner la fonction __get ().

Le volume…

Cela s'avère être une structure assez lourde pour accéder au code. La même fonctionnalité exacte peut être obtenue sans effort supplémentaire en utilisant une méthode statique.

Et il ne sert à rien de parler d'une telle conception. Ok, vous pouvez accéder aux données de session dans votre modèle. Mais pourquoi ferais-tu ça ?

"Solution"

Les développeurs Kohana ont été les premiers à travailler sérieusement sur les méthodes statiques. Ils ont apporté les modifications suivantes :
// était $ this-> input-> get ("foo"); // est devenu Input :: get ("foo");
Pour de nombreux développeurs CodeIgniter avec leur héritage PHP 4 qui ont migré vers le framework Kohana pour tirer parti de PHP 5, ce n'est pas inhabituel. Mais moins il y a de personnages, mieux c'est, non ?

Quel est le problème?

De nombreux développeurs PHP (en particulier ceux qui connaissent bien Symfony et Zend) diront : "C'est évident - utilisez l'injection de dépendances !" Mais peu de développeurs de la communauté CodeIgniter ont une réelle expérience de ce processus, car il est assez complexe.

Un autre fait à propos du framework Fuel PHP est que jusqu'à présent, la plupart des méthodes statiques agissent comme une interface. Par exemple, la logique a toujours des problèmes statiques, en particulier lorsque le concept HMVC est impliqué.

C'est un pseudo-code que je n'ai pas utilisé dans FuelPHP depuis 1.1 :
la classe ControllerA étend le contrôleur (fonction publique action_foo () (echo Input :: get ("param");))
Code assez standard. Cette méthode affichera la valeur ? barre = dans la méthode.

Que se passe-t-il lorsque nous faisons une requête HMVC à une méthode donnée ?
class ControllerB étend Controller (fonction publique action_baz () (echo Input :: get ("param"); ​​​​echo "&"; echo Request :: forge ("controllera / foo? param = val1") -> execute () ;) )
En appelant dans le navigateur contrôleurb / baz, vous verrez la sortie "val1", mais si vous tapez controllerb / baz? param = override vous obtenez les deux appels pour obtenir une méthode qui renvoie la même valeur.

Pertinence

Le code global ne vous donnera aucun type de relation. Un exemple vaut mieux que n'importe quel mot :
$ this-> request-> input-> get ("param");
L'objet demandé contiendra une instance complètement nouvelle pour chaque requête, puis une entrée d'objet sera générée pour chaque requête, qui ne contiendra que l'entrée d'une requête spécifique. Cela est vrai pour les plans de FuelPHP 2.0 et résout le problème de l'injection de dépendance ainsi que le problème avec HMVC.

Qu'en est-il de la syntaxe approximative?

Les développeurs Symfony- ou Zend- n'en souffrent pas, mais ceux qui utilisent CodeIgniter auront longtemps des cauchemars à propos de "retourner à PHP 4".

$ cela fait toujours référence à l'objet "actuel", et vous ne devriez certainement pas l'utiliser pour accéder au code global.

$ this-> request-> input-> get () peut ressembler à une forme étendue de la syntaxe CodeIgniter, mais nous ne sommes en réalité que dans le contrôleur. Lorsqu'un contrôleur instancie une nouvelle requête imbriquée, le constructeur de requête reçoit également une instance en entrée.

Si vous êtes dans un modèle ou une autre classe, alors un accès comme $ this-> request-> input-> foo () ne fonctionnera pas, car $ this n'est pas un contrôleur.

Input :: get ("foo") crée une façade pour les instances de logique en arrière-plan. Mais cela ne résout pas les problèmes liés au travail du code mondial. Les plus paresseux lors des tests d'applications peuvent basculer entre les deux modes sans avoir à utiliser pleinement le nouveau framework.

Il y a une excellente vidéo de Taylor Otwell (créateur ou laravel 4) dans laquelle il décrit comment remplacer le code statique par une seule instance vérifiée via son conteneur DiC.

Laravel 4 - Injection de contrôleur IoC et tests unitaires de UserScape sur Vimeo.

Ceci est une excellente présentation de la façon dont vous pouvez contourner l'utilisation de méthodes statiques dans Laravel. Bien que certains frameworks modernes ressemblent beaucoup à Kohana à première vue, ils résolvent même les tâches les plus courantes de manières complètement différentes.

Sur cette triste note...

Je suis actuellement en train de convertir PyroCMS de CodeIgniter en Laravel. Essayer de passer directement du code PHP 4 global à l'injection de dépendance parfaite est un suicide absolu. Une étape intermédiaire avant d'utiliser le chargeur CI consiste à utiliser le code de chargement automatique PHP 5, PSR-2 avec un tas de méthodes statiques. En attendant, nous sommes toujours chez CodeIgniter.

La transition du code statique au code DiC peut être facilement montrée lorsque nous effectuons enfin la transition vers Laravel.

Passer de CodeIgniter étroitement couplé à PSR-2 testable est un défi majeur. L'équipe Pyro est en route - et ce sera épique.

PHP a la capacité de définir une méthode comme statique. Une méthode statique n'a pas accès aux propriétés de l'objet. De telles méthodes ne peuvent être appelées que dans le contexte d'une classe, pas dans le contexte d'un objet.

La chose la plus importante à comprendre est que les propriétés et méthodes statiques appartiennent à des classes, pas à des objets.

Un exemple deviendra immédiatement clair. Créons un objet Math (abréviation de mathématiques en anglais).

Méthodes statiques PHP
"; $ math_1 = new Math (); $ math_2 = new Math (); $ math_3 = new Math (); $ math_4 = new Math (); echo" Objets créés : ". Math :: getCount ();?>

Cette classe fournit des outils pour travailler avec des fonctions mathématiques sans avoir à créer un objet. La classe a un constructeur qui incrémente la propriété statique $ count de un. La classe mémorise la valeur de cette propriété car elle est statique.

Soit dit en passant, le mot static est utilisé pour déclarer une méthode ou une propriété comme statique, et le mot self avec un double deux-points " ::" est utilisé pour accéder à une propriété statique.

Tout cela est mieux compris par comparaison, surtout lorsqu'on compare un exemple fonctionnel avec un exemple défectueux. Développons un peu notre exemple.

Méthodes statiques PHP compteur ++; ) fonction statique publique calcSin ($ x) (retour sin ($ x);) fonction statique publique calcSQRT ($ x) (retour sqrt ($ x);) fonction statique publique getCount () (retour self :: $ count;) public function getCounter() (return $ this-> counter;)) echo Math :: calcSin (1); écho "
"; echo Math :: calcSQRT (9); echo"
"; $ math_1 = new Math (); $ math_2 = new Math (); $ math_3 = new Math (); $ math_4 = new Math (); echo" Objets créés : ". Math :: getCount (); echo"
"; echo" Objets créés : ". $ math_4-> getCounter ();?>

Dans cet exemple, nous avons ajouté la propriété $ counter habituelle à la classe, elle a également augmenté de un dans le constructeur. Mais la propriété normale appartient à l'objet, elle ne persiste donc pas entre les appels aux objets. A toute création d'une instance d'une classe (objet), la propriété sera égale à zéro, dans le constructeur elle sera augmentée de un.

Une propriété statique appartient à la classe, sa valeur est donc préservée.

Vous trouverez ci-dessous quelques exemples supplémentaires illustrant le fonctionnement des propriétés et méthodes statiques.

Tenter d'utiliser la variable $ this dans une méthode statique entraînera une erreur (Erreur fatale : utiliser $ this lorsqu'il n'est pas dans le contexte de l'objet).

Méthodes statiques PHP âge. "vieille."; // il s'agit d'une erreur "Utilisation de $ this lorsqu'il n'est pas dans le contexte de l'objet". )) $ TestClass = new TestClass (); $ TestClass-> sayHello (); ?>

Au fait, sans la ligne :

$ TestClass-> sayHello ();

il n'y aura pas d'erreur, mais dès que vous essayez d'exécuter une méthode statique avec la variable $ this dans votre code, vous recevez immédiatement un message d'erreur.

Si vous supprimez le mot statique dans cet exemple, il n'y aura aucune erreur.

Si vous faites référence à une propriété d'un objet à partir d'une méthode statique, cela entraînera une erreur. Vous ne pouvez accéder aux propriétés statiques qu'à l'aide de la construction self :: $ age. Notez qu'il y a un signe $ devant le nom de la variable, contrairement à la construction $ this-> age.

Méthodes statiques PHP dis bonjour (); ?>

La suppression du mot statique devant le nom de la propriété dans cet exemple entraîne une erreur « Accès à la propriété statique non déclarée ».

Il n'y a pas de propriétés statiques dans les objets de classe.

Méthodes statiques PHP "; print_r ($ ClasseTest); echo""; ?>

Une méthode statique peut être appelée à l'aide de la construction self :: method (). Exemple:

Méthodes statiques PHP printBonjour (); ?>

Une propriété statique peut être obtenue dans le contexte d'une classe en utilisant la syntaxe :

echo ClasseTest :: $ age;

De plus, une tentative d'accès à une propriété ordinaire de cette manière entraînera une erreur : « Erreur fatale : accès à une propriété statique non déclarée ».

Une propriété statique peut être modifiée dans le contexte d'une classe en utilisant la syntaxe :

ClasseTest :: $ âge + = 20 ; // Par exemple

Un autre exemple de code avec des méthodes et propriétés statiques

Dans cet exemple, il existe encore des options simples pour utiliser des méthodes et des propriétés statiques. Plus le code est simple que vous comprenez, mieux vous vous souviendrez du matériel.

Méthodes statiques PHP ".TestClass :: $ age; // echo TestClass :: $ txt; // Erreur : erreur fatale : accès à une propriété statique non déclarée. Echo"
"; TestClass :: sayHi (); echo"
"; TestClass :: sayHello (); // Et voici comment j'ai eu accès à une variable statique via un objet ($ obj :: $ age) ... echo"
"; $ obj = new TestClass; echo" Accéder à une variable statique via un objet : ". $ obj :: $ age;?>

Notez, et c'est important, dans cet exemple, nous avons abordé la méthode sayHi() non statique en utilisant la syntaxe pour appeler les membres de classe statiques.

Résumé

  • Le point principal est que les propriétés statiques appartiennent à des classes, pas à des objets.
  • A partir d'une méthode statique, vous ne pouvez pas accéder aux propriétés et méthodes ordinaires d'une classe, $ this-> name ne fonctionne pas ici.
  • À partir d'une méthode statique, vous pouvez faire référence aux propriétés statiques en utilisant self :: $ name.
  • Les propriétés statiques de classe ne sont pas disponibles pour les objets.
  • Une méthode normale peut accéder à une propriété statique en utilisant self :: $ name.
  • Une propriété statique peut être obtenue dans le contexte d'une classe en utilisant la syntaxe : TestClass :: $ age.
  • Une méthode régulière peut être appelée dans le contexte à la fois d'un objet ($ objet-> méthode ()) et d'une classe en utilisant la syntaxe TestClass :: méthode ().
  • En utilisant la syntaxe $ object :: $ age, j'ai pu accéder à une propriété statique via un objet.

Parallèles avec JavaScript

JavaScript a une telle classe appelée Math, qui contient de nombreuses fonctions mathématiques différentes.

Pour effectuer des calculs mathématiques (calcul du sinus ou de l'exposant) en JavaScript, vous n'avez pas besoin de créer un objet de la classe Math, car ses méthodes sont statiques. Avant d'apprendre PHP, je ne comprenais en rien ce que c'était, et ce n'est qu'après avoir étudié les cours et les objets en PHP dans ma tête que tout s'est mis en place.

En fait, il est très pratique d'avoir un accès direct aux méthodes mathématiques de la classe Math, en évitant la création d'un objet.

J'ai longtemps eu envie d'écrire sur ce sujet. La première impulsion a été l'article de Miško Hevery "Les méthodes statiques sont la mort à la testabilité". J'ai écrit un article en réponse mais je ne l'ai jamais publié. Mais récemment, j'ai vu quelque chose que l'on peut appeler "Programmation orientée classe". Cela a ravivé mon intérêt pour le sujet et voici le résultat.

La "programmation orientée classe" concerne l'utilisation de classes constituées uniquement de méthodes et de propriétés statiques, et la classe n'est jamais instanciée. Dans cet article je vais parler de :

  • il n'offre aucun avantage par rapport à la programmation procédurale
  • ne pas abandonner les objets
  • la présence de membres statiques de la classe ! = mort aux épreuves
Bien que cet article concerne PHP, les concepts s'appliquent également à d'autres langages.

Dépendances

Habituellement, le code dépend d'un autre code. Par exemple:

$ foo = substr ($ bar, 42);
Ce code dépend de la variable $ bar et de la fonction substr. $ bar est juste une variable locale définie légèrement plus haut dans le même fichier et dans la même portée. substr est une fonction principale de PHP. Tout est simple ici.

Maintenant, un exemple comme celui-ci :

Class BloomFilter (... fonction publique __construct ($ m, $ k) (...) fonction statique publique getK ($ m, $ n) (retour ceil (($ m / $ n) * log (2)); ) ...)
Cette petite fonction d'assistance fournit simplement un wrapper pour un algorithme spécifique qui vous aide à calculer un bon nombre pour l'argument $ k utilisé dans le constructeur. Parce que elle doit être appelée avant que la classe ne soit instanciée, elle doit être statique. Cet algorithme n'a pas de dépendances externes et il est peu probable qu'il soit remplacé. Il s'utilise comme ceci :

m$ = 10000; $ n = 2000 ; $ b = nouveau BloomFilter ($ m, BloomFilter :: getK ($ m, $ n));
Cela ne crée aucune dépendance supplémentaire. La classe dépend d'elle-même.

  • Constructeur alternatif. Un bon exemple est la classe DateTime intégrée à PHP. Il peut être instancié de deux manières différentes :

    $ date = nouvelle DateHeure ("2012-11-04"); $ date = DateTime :: createFromFormat ("j-m-A", "04-11-2012");
    Dans les deux cas, le résultat sera une instance DateTime, et dans les deux cas, le code est lié à la classe DateTime d'une manière ou d'une autre. La méthode statique DateTime :: createFromFormat est un constructeur d'objet alternatif qui renvoie le même que new DateTime, mais avec des fonctionnalités supplémentaires. Là où vous pouvez écrire une nouvelle classe, vous pouvez écrire une classe :: méthode (). Cela ne crée aucune nouvelle dépendance.

  • Le reste des cas d'utilisation des méthodes statiques affecte la liaison et peut former des dépendances implicites.

    Un mot sur l'abstraction

    Pourquoi toute cette histoire de dépendance ? Abstraction! Au fur et à mesure que votre produit grandit, sa complexité augmente. Et l'abstraction est la clé de la gestion de la complexité.

    Par exemple, vous avez une classe Application qui représente votre application. Il communique avec la classe User, qui est une représentation de l'utilisateur. Qui reçoit les données de la base de données. La classe Database a besoin d'un DatabaseDriver. DatabaseDriver a besoin de paramètres de connexion. Etc. Si vous appelez simplement Application :: start () de manière statique, qui appellera User :: getData () de manière statique, qui appellera la base de données de manière statique, et ainsi de suite, en espérant que chaque couche gérera ses dépendances, vous pouvez obtenir un terrible désordre si quelque chose ne va pas, pas de cette façon. Il est impossible de deviner si l'appel Application :: start() fonctionnera, car il n'est pas du tout évident de savoir comment les dépendances internes se comporteront. Pire encore, la seule façon d'influencer le comportement de Application :: start() est de changer le code source de cette classe et le code des classes qu'elle appelle et le code des classes qui appellent ces classes ... dans la maison que Jack a construit.

    L'approche la plus efficace lors de la création d'applications complexes consiste à créer des parties distinctes sur lesquelles vous pourrez compter à l'avenir. Les parties auxquelles vous pouvez arrêter de penser, dont vous pouvez être sûr. Par exemple, lors de l'appel de la base de données statique :: fetchAll (...), il n'y a aucune garantie que la connexion à la base de données a déjà été établie ou le sera.

    Fonction (base de données $ base de données) (...)
    Si le code à l'intérieur de cette fonction est exécuté, cela signifie que l'instance de base de données a été transmise avec succès, ce qui signifie que l'instance d'objet de base de données a été créée avec succès. Si la classe Database est conçue correctement, vous pouvez être sûr que le fait d'avoir une instance de cette classe signifie la possibilité d'effectuer des requêtes sur la base de données. S'il n'y a pas d'instance de la classe, le corps de la fonction ne sera pas exécuté. Cela signifie que la fonction n'a pas à se soucier de l'état de la base de données, la classe Database le fera elle-même. Cette approche vous permet d'oublier les dépendances et de vous concentrer sur la résolution des problèmes.

    Sans la possibilité de ne pas penser aux dépendances et aux dépendances de ces dépendances, il est presque impossible d'écrire une application complexe. La base de données peut être une petite classe wrapper ou un monstre multicouche géant avec un tas de dépendances, elle peut commencer comme un petit wrapper et se transformer en un monstre géant au fil du temps, vous pouvez hériter de la classe Database et transmettre un descendant à la fonction, tout cela n'a pas d'importance pour votre fonction (Database $ database), tant que l'interface publique de Database n'est pas modifiée. Si vos classes sont correctement séparées du reste de l'application à l'aide de l'injection de dépendances, vous pouvez tester chacune d'elles en utilisant des stubs au lieu de leurs dépendances. Une fois que vous avez suffisamment testé la classe pour vous assurer qu'elle fonctionne comme prévu, vous pouvez sortir de votre tête simplement en sachant que vous devez utiliser une instance de base de données pour travailler avec la base de données.

    La programmation orientée classe est un non-sens. Apprenez à utiliser la POO.

    Reg.ru : domaines et hébergement

    Le plus grand registraire et fournisseur d'hébergement en Russie.

    Plus de 2 millions de noms de domaine en service.

    Promotion, courrier pour domaine, solutions d'affaires.

    Plus de 700 000 clients dans le monde ont déjà fait leur choix.

    * Passez votre souris pour interrompre le défilement.

    Retour en avant

    Méthodes statiques et propriétés en PHP

    Dans les documents précédents, nous avons maîtrisé les fonctionnalités de base de la programmation orientée objet en PHP et nous nous tournons maintenant vers l'étude d'aspects plus complexes et intéressants.

    Avant cela, nous avons toujours travaillé avec des objets. Nous avons caractérisé les classes comme des modèles à travers lesquels les objets sont créés, et les objets comme des composants actifs, dont nous appelons les méthodes et dont nous accédons aux propriétés.

    Cela a conduit à la conclusion qu'en programmation orientée objet, le vrai travail est effectué à l'aide d'instances de classe. Et les classes ne sont finalement que des modèles pour créer des objets.

    Mais en réalité, tout n'est pas si simple. Nous pouvons accéder à la fois aux méthodes et aux propriétés dans le contexte d'une classe, pas d'un objet. Ces méthodes et propriétés sont appelées "statiques" et doivent être déclarées à l'aide du mot-clé statique.

    Classe StaticExample (static public $ aNum = 0; static public function sayHello () (print "Bonjour!";))

    Méthodes statiques sont des fonctions utilisées dans le contexte d'une classe. Ils ne peuvent eux-mêmes accéder à aucune des propriétés normales de la classe, car ces propriétés appartiennent à des objets.

    Cependant, à partir de méthodes statiques, comme vous l'avez probablement déjà deviné, vous pouvez accéder aux propriétés statiques. Et si vous modifiez une propriété statique, toutes les instances de cette classe pourront accéder à la nouvelle valeur.

    Étant donné que l'élément statique est accessible via la classe et non via l'instance d'objet, nous n'avons pas besoin d'une variable faisant référence à l'objet. Au lieu de cela, le nom de la classe est utilisé, suivi de deux deux-points " ::".

    Imprimer l'exemple statique :: $ aNum; StaticExample :: sayBonjour ();

    Vous devriez déjà être familiarisé avec cette syntaxe à partir des bases de la POO en PHP. Nous avons utilisé la construction " ::" en combinaison avec le mot-clé parent afin d'accéder à la méthode surchargée de la classe parent.

    Maintenant, comme alors, nous nous référons à la classe, pas aux données contenues dans l'objet. Vous pouvez utiliser le mot-clé dans le code de la classe parent afin d'accéder à la superclasse sans utiliser le nom de la classe.

    Pour accéder à une méthode ou propriété statique de la même classe (et non d'une classe enfant), nous utiliserons le mot-clé soi.

    Mot-clé soi est utilisé pour faire référence à la classe courante, et la pseudo variable $ ceci- à l'objet courant. Par conséquent, de l'extérieur de la classe StatiqueExemple nous nous référons à la propriété $ unNum en utilisant le nom de sa classe.

    StaticExample :: $ aNum;

    Et à l'intérieur de la classe StatiqueExemple vous pouvez utiliser le mot-clé soi.

    Classe StaticExample (static public $ aNum = 0; static public function sayHello () (self :: $ aNum ++; print "Hello! (". Self :: $ aNum. ") \ N";))

    Noter: sauf lorsqu'il fait référence à une méthode surchargée de la classe parent, la construction " ::" doit toujours être utilisée uniquement pour accéder aux méthodes ou propriétés statiques.

    Par définition, les méthodes statiques ne sont pas appelées dans le contexte d'un objet. Pour cette raison, les méthodes et propriétés statiques sont souvent appelées variables et propriétés de classe. Par conséquent, vous ne pouvez pas utiliser la pseudo variable $ ceci dans une méthode statique.

    Pourquoi utiliser une méthode ou une propriété statique ?

    Nous arrivons ici à la question la plus importante. Le fait est que les éléments statiques ont un certain nombre de caractéristiques utiles.

    d'abord, ils sont accessibles de n'importe où dans le script (en supposant que vous ayez accès à la classe). Cela signifie que vous pouvez accéder aux fonctions sans passer une instance d'une classe d'un objet à un autre, ou pire, en stockant une instance de l'objet dans une variable globale.

    en deuxième, une propriété statique est disponible pour chaque instance d'un objet de cette classe. Par conséquent, vous pouvez définir des valeurs qui devraient être disponibles pour tous les objets d'un type donné.

    et enfin la troisième, le fait même que vous n'ayez pas besoin d'avoir une instance d'une classe pour accéder à sa propriété ou méthode statique évitera d'instancier des objets uniquement pour appeler une fonction simple.

    Pour démontrer cela, créons une méthode statique pour la classe BoutiqueProduit qui instanciera automatiquement les objets BoutiqueProduit... Définir une table avec SQLite des produits de la manière suivante :

    CREATE TABLE products (id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, firstname TEXT, mainname TEXT, title TEXT, price float, numpages int, playlength int, discount int)

    Créons maintenant une méthode obtenirInstance(), qui reçoit un identifiant de chaîne et un objet PDO. Ils permettront de récupérer une ligne d'une table de base de données, à partir de laquelle un objet de type BoutiqueProduit retourné au programme appelant.

    Nous pouvons ajouter ces méthodes à la classe BoutiqueProduit qui a été créé pour nous dans des matériaux antérieurs. Comme vous le savez probablement, PDO signifie PHP Data Object. La classe PDO fournit une interface générique pour diverses applications de base de données.

    // Classe ShopProduct private $ id = 0; fonction publique setID ($ id) ($ this-> id = $ id;) // ... fonction statique publique getInstance ($ id, PDO $ pdo) ($ stmt = $ pdo-> prepare ("select * from products où id =? "); $ result = $ stmt-> execute (array ($ id)); $ row = $ stmt-> fetch (); if (vide ($ row)) (return null;) if ($ row ["type"] == "book") ($ product = new BookProduct ($ row ["title"], $ row ["firstname"], $ row ["mainname"], $ row ["price"] , $ row ["numpages"]);) else if ($ row ["type"] == "cd") ($ product = new CdProduct ($ row ["title"], $ row ["firstname"], $ row ["mainname"], $ row ["price"], $ row ["playlength"]);) else ($ product = new ShopProduct ($ row ["title"], $ row ["firstname"], $ row ["mainname"], $ row ["price"]);) $ product-> setId ($ row ["id"]); $ product-> setDiscount ($ row ["discount"]); return $ produit;) // ...

    Comme vous pouvez le voir, la méthode obtenirInstance() renvoie un objet de type BoutiqueProduit, et il est assez "intelligent" pour, en fonction de la valeur du champ taper créer un objet avec les caractéristiques souhaitées.

    J'ai volontairement omis le code de gestion des erreurs pour que l'exemple soit aussi concis que possible. Par exemple, dans la version qui fonctionne réellement de ce code, nous ne pouvons pas être trop crédules et supposer que l'objet PDO transféré a été correctement initialisé et connecté à la base de données requise.

    En fait, nous devrions probablement envelopper l'objet PDO dans une classe qui garantit ce comportement. Nous reviendrons sur cette question dans un prochain article.

    Méthode obtenirInstance() plus utile dans le contexte d'une classe que dans le contexte d'un objet. Il vous permet de convertir facilement les données qui se trouvent dans la base de données en un objet, et pour cela nous n'avons pas besoin d'avoir une instance distincte d'un objet de type BoutiqueProduit.

    Cette méthode n'utilise aucune méthode ou propriété qui nécessite une instance distincte de l'objet, il n'y a donc aucune raison de ne pas le déclarer statique. Ensuite, ayant le bon objet PDO, nous pouvons appeler cette méthode de n'importe où dans l'application.

    $ dsn = "sqlite : //home/bob/projects/products.db" ; $ pdo = nouveau PDO ($ dsn, null, null); $ pdo-> setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION); $ obj = ShopProduct :: getInstance (1, $ pdo);

    Des méthodes comme celles-ci fonctionnent comme des "usines" en ce sens qu'elles prennent des matières "brutes" (telles que des données récupérées à partir d'une chaîne de base de données ou d'un fichier de configuration) et les utilisent pour créer des objets.

    Le terme "usine" fait référence au code d'instanciation d'objets. Nous vous rencontrerons plus loin avec des exemples de telles "usines".


    Propriétés permanentes

    Certaines propriétés ne doivent pas être modifiées. Par exemple, les éléments tels que les codes d'erreur ou les codes d'état du programme sont généralement définis manuellement dans les classes. Alors qu'ils doivent être publics et statiques, le code client ne doit pas pouvoir les modifier.

    Pour ce faire, vous pouvez définir des propriétés persistantes au sein de la classe. Comme les constantes globales, les constantes de classe ne peuvent pas être modifiées après avoir été définies. Une propriété persistante est déclarée à l'aide du mot-clé const.

    Contrairement aux propriétés normales, il n'y a pas de signe dollar devant le nom de la propriété persistante. Par convention, on ne leur attribue souvent que des noms en majuscules, comme dans l'exemple suivant :

    Classe ShopProduct (const DISPONIBLE = 0; const OUT_OF_STOCK = 1; // ...

    Les propriétés constantes ne peuvent contenir que des valeurs de type élémentaire. Vous ne pouvez pas affecter un objet à une constante.

    Comme pour les propriétés statiques, les propriétés persistantes sont accessibles via la classe, et non via une instance d'objet. Tout comme une constante est définie sans signe dollar, elle ne nécessite pas non plus d'accéder à un caractère de début.

    ImprimerieProduit :: DISPONIBLE;

    Tenter d'attribuer une valeur à une constante après qu'elle a été déclarée entraînera une erreur lors de l'étape d'analyse.

    Les constantes doivent être utilisées lorsque la propriété doit être accessible à toutes les instances de la classe et lorsque la valeur de la propriété doit être fixe et inchangée.

    Ceci conclut cet article, et le prochain se concentrera sur.

    Vous avez aimé le matériel et vous voulez vous remercier ?
    Partagez simplement avec vos amis et collègues!




    Vous avez aimé l'article ? Partagez-le