1. Introduction
Implémenter des types d'objets obligatoires en PHP peut parfois être très important. S'il manque, soit en raison d'un manque de connaissances - basé sur des hypothèses de programmation incorrectes, soit simplement par paresse - alors vous verrez dans votre application Web particulière des résultats auxquels vous ne vous attendez pas. Surtout lors de la programmation en PHP 4, il est très simple d'utiliser la fonction "is_a()" (bien qu'il existe d'autres méthodes) pour vérifier le type de l'objet avec lequel vous travaillez. Bien entendu, forcer les types d'objets peut également être utilisé pour filtrer les objets d'entrée qui doivent être transmis en tant que paramètres à d'autres classes PHP dans la même application.
Cependant, PHP 4 n'expose pas certaines faiblesses de son modèle objet - il peut occasionnellement nécessiter l'écriture de code supplémentaire afin d'implémenter certaines fonctionnalités trouvées dans les langages orientés objet matures. Ce fait est connu de la communauté PHP depuis longtemps. Cependant, avec la sortie de PHP 5, bon nombre de ces fonctionnalités extrêmement précieuses ont été ajoutées dans le cadre du modèle objet amélioré. Ils aideront à implémenter plus étroitement le développement de code basé sur les objets, vous permettant d'utiliser des caractéristiques d'objet spécifiques.
Dans le cas ci-dessus, une attention particulière doit être portée à la coercition de type objet. En fait, PHP 5 offre aux développeurs au moins deux façons de vérifier les types d'objets lors de l'exécution d'une application Web : il s'agit de l'opérateur "instanceof" et de la fonctionnalité "indice de type". Passons maintenant au sujet principal de cet article, je vais vous présenter l'utilisation de l'opérateur "instanceof" dans PHP 5, vous découvrirez bientôt qu'il peut être très pratique pour déterminer si l'objet avec lequel vous travaillez appartient à un type spécifique ;
Cet article vous aidera à comprendre comment implémenter les types d'objet obligatoires dans PHP 5 à travers quelques exemples orientés objet.
2. Ce que vous ne devriez pas faire
Pour montrer comment implémenter la coercition de type d'objet dans PHP 5, j'utiliserai la classe de widget (X)HTML et une simple classe de création de pages, avec des modifications simples pour s'adapter à l'environnement de développement PHP 5.
Mon premier exemple répertorie certaines classes de widgets (X)HTML qui dérivent d'une classe de base abstraite "HTMLElement", qui ignore la vérification du type de leurs objets d'entrée. Veuillez d'abord regarder la classe suivante :
//Définissez la classe abstraite 'HTMLElement'
classe abstraite HTMLElement{
attributs $ protégés ;
fonction protégée __construct($attributs){
si(!is_array($attributes)){
throw new Exception('Type d'attribut invalide');
}
$this->attributs=$attributs ;
}
// Méthode abstraite 'getHTML()' fonction abstraite protégée getHTML();
}
//Définit la classe spécifique 'Div'-extend HTMLElement
la classe Div étend HTMLElement{
private $output='<div';
données $ privées ;
fonction publique __construct($attributes=array(),$data){
parent::__construct($attributs);
$this->data=$data;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</div>';
renvoie $this->output ;
}
}
//Définit la classe concrète 'Header1' - étend HTMLElement
la classe Header1 étend HTMLElement{
privé $output='<h1 ';
données $ privées ;
fonction publique __construct($attributes=array(),$data){
parent::__construct($attributs);
$this->data=$data;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</h1>';
renvoie $this->output ;
}
}
//Définit la classe concrète 'Paragraph' - étend HTMLElement
Le paragraphe de classe étend HTMLElement{
privé $output='<p ';
données $ privées ;
fonction publique __construct($attributes=array(),$data){
parent::__construct($attributs);
$this->data=$data;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=$this->data.'</p>';
renvoie $this->output ;
}
}
//Définit la classe concrète 'UnorderedList' - étend HTMLElement
la classe UnorderedList étend HTMLElement{
private $output='<ul';
private $items=array();
fonction publique __construct($attributes=array(), $items=array()){
parent::__construct($attributs);
si(!is_array($items)){
throw new Exception('Paramètre non valide pour les éléments de la liste');
}
$this->items=$items;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->items as $item){
$this->output.='<li>'.$item.'</li>';
}
$this->output.='</ul>';
renvoie $this->output ;
}
}
Comme vous pouvez le voir, les classes de widgets (X)HTML ci-dessus sont très utiles pour générer des éléments spécifiques dans un site Web, mais j'ai intentionnellement écrit le code de chaque classe afin qu'elles ne puissent pas valider l'efficacité des paramètres d'entrée. Comme vous l'avez peut-être imaginé, les paramètres d'entrée sont transmis directement au constructeur de classe et attribués en tant que propriétés. La question se pose : y a-t-il quelque chose de mal à faire cela ? Oui, il y en a. Maintenant, je vais définir ma classe de création de page la plus simple et l'alimenter avec des widgets comme celui-ci afin que vous puissiez voir comment l'entrée de cette classe est mélangée avec des objets incorrects. Voici la signature de la classe générateur de page :
class PageGenerator{
privé $sortie='';
titre privé $ ;
fonction publique __construct($title='Page par défaut'){
$this->titre=$titre;
}
fonction publique doHeader(){
$this->output='<html><head><title>'.$this-
>titre.'</titre></tête><corps>';
}
fonction publique addHTMLElement($htmlElement){
$this->output.=$htmlElement->getHTML();
}
fonction publique doFooter(){
$this->output.='</body></html>';
}
fonction publique fetchHTML(){
renvoie $this->output ;
}
}
Maintenant, nous commençons à instancier certains objets widget (X)HTML et à les transmettre aux classes génératrices correspondantes, comme le montre l'exemple suivant :
try{
//Générer des éléments HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
l'élément va ici');
$div=new Div(array('name'=>'div1','class'=>'divclass'),'Contenu de l'élément Div
va ici');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'Contenu du paragraphe
l'élément va ici');
$ul=new UnorderedList(array ('name'=>'list1', 'class'=>'listclass'), array
('item1'=>'valeur1', 'item2'=>'valeur2', 'item3'=>'valeur3'));
//Instancier la classe du générateur de page $pageGen=new Page Generator();
$pageGen->doHeader();
//Ajouter un objet 'HTMLElement' $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
//Afficher la page Web echo $pageGen->fetchHTML();
}
attraper(Exception $e){
echo $e->getMessage();
sortie();
}
Après avoir exécuté le code PHP ci-dessus, le résultat que vous obtenez est une simple page Web - elle contient des objets (X)HTML créés précédemment. Dans ce cas, il est facile de comprendre ce qui se passera si, pour une raison quelconque, la classe de création de page reçoit un objet incorrect et appelle sa méthode "addHTML()". Ici, j'ai retravaillé la condition de conflit - en utilisant un objet widget (X)HTML inexistant. Veuillez réexaminer le code suivant :
essayez{
//Générer des éléments HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Content for H1
l'élément va ici');
$div=new Div(array('name'=>'div1','class'=>'divclass'),'Contenu de l'élément Div
va ici');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'Contenu du paragraphe
l'élément va ici');
$ul=new UnorderedList(array ('name'=>'list1', 'class'=>'listclass'), array
('item1'=>'valeur1', 'item2'=>'valeur2', 'item3'=>'valeur3'));
//Instancier la classe du générateur de page $pageGen=new Page Generator();
$pageGen->doHeader();
//Ajouter un objet 'HTMLElement' $pageGen->addHTMLElement($fakeobj) //Passer un objet inexistant à cette méthode $pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->addHTMLElement($ul);
$pageGen->doFooter();
// Affiche la page echo $pageGen->fetchHTML();
}
attraper(Exception $e){
echo $e->getMessage();
sortie();
}
Dans ce cas, comme indiqué dans la ligne suivante :
$pageGen->addHTMLElement($fakeobj)//Pass objet inexistant à cette méthode
Un objet widget (X)HTML inexistant est passé à la classe générateur de page, ceci entraînera une erreur fatale :
Erreur fatale : Appel à une fonction membre sur un non-objet dans
Qu'en est-il du
chemin/vers/fichier
?C'est une pénalité directe pour ne pas vérifier le type de l'objet passé à la classe générateur ! Assurez-vous donc de garder cela à l’esprit lors de la rédaction de vos scripts. Heureusement, il existe une solution simple à ces problèmes, et c’est là qu’intervient la puissance de l’opérateur « instanceof ». Si vous voulez voir comment cet opérateur est utilisé, lisez la suite.
3. Utilisez l'opérateur "instanceof".
Comme vous pouvez le constater, l'utilisation de l'opérateur "instanceof" est très simple. Il utilise deux paramètres pour remplir sa fonction. Le premier paramètre est l'objet que vous souhaitez vérifier et le deuxième paramètre est le nom de la classe (en fait un nom d'interface) utilisé pour déterminer si l'objet est une instance de la classe correspondante. Bien sûr, j'ai utilisé intentionnellement la terminologie ci-dessus afin que vous puissiez voir à quel point cet opérateur est intuitif à utiliser. Sa syntaxe de base est la suivante :
if (instance d'objet du nom de la classe){
//Faire quelque chose d'utile
}
Maintenant que vous comprenez comment cet opérateur est utilisé dans PHP 5, définissons la classe de constructeur de page Web correspondante afin de vérifier le type d'objet passé à sa méthode "addHTMLElement()". Voici la nouvelle signature de cette classe, dont j'ai parlé plus haut utilise l'opérateur "instanceof" :
class PageGenerator{
privé $sortie='';
titre privé $ ;
fonction publique __construct($title='Page par défaut'){
$this->titre=$titre;
}
fonction publique doHeader(){
$this->output='<html><head><title>'.$this->title.'</title></head><body>';
}
fonction publique addHTMLElement($htmlElement){
if(!$htmlElement instance de HTMLElement){
throw new Exception('Élément (X)HTML invalide');
}
$this->output.=$htmlElement->getHTML();
}
fonction publique doFooter(){
$this->output.='</body></html>';
}
fonction publique fetchHTML(){
renvoie $this->output ;
}
}
Notez, dans la classe ci-dessus, comment l'opérateur "instanceof" est inclus dans la méthode "addHTMLElement()" afin de garantir que tous les objets passés sont des instances de la classe "HTMLElement" définie précédemment. Désormais, il est possible de reconstruire la page Web que vous avez vue précédemment, auquel cas assurez-vous que tous les objets d'entrée transmis à la classe de création de page Web sont de véritables objets widget (X)HTML. Voici l'exemple correspondant :
try{
//Générer des éléments HTML $h1=new Header1(array('name'=>'header1', 'class'=>'headerclass'), 'Le contenu de l'élément H1 va ici');
$div=new Div(array('name'=>'div1', 'class'=>'divclass'), 'Le contenu de l'élément Div va ici');
$par=new Paragraph(array('name'=>'par1','class'=>'parclass'),'Le contenu de l'élément Paragraph va ici');
$teststr='Ceci n'est pas un élément HTML';
//Instancier la classe du générateur de page $pageGen=new Page Generator();
$pageGen->doHeader();
//Ajouter un objet 'HTMLElement' $pageGen->addHTMLElement($teststr) //Passez une simple chaîne à cette méthode $pageGen->addHTMLElement($h1);
$pageGen->addHTMLElement($div);
$pageGen->addHTMLElement($par);
$pageGen->doFooter();
//Afficher la page Web echo $pageGen->fetchHTML();
}
attraper(Exception $e){
echo $e->getMessage();
sortie();
}
Comme vous l'avez vu dans l'exemple ci-dessus, je transmets une simple chaîne de test (pas un objet "HTMLElement") dans la classe du générateur de pages, qui lancera une exception - interceptée par un bloc "catch" spécifique, comme indiqué ci-dessous :
Élément (X)HTML invalide
À ce stade, afin de déterminer la validité de l'objet d'entrée, j'ai utilisé l'opérateur "instanceof", afin que la page Web ci-dessus puisse être. J'espère que vous pourrez vraiment apprécier l'importance de filtrer l'entrée pour Les méthodes de votre classe pour éviter les erreurs superflues en utilisant cet opérateur. Saisie de données.
Après avoir montré l'implémentation correcte de l'opérateur "instanceof" dans la classe du générateur de pages Web, il y a plus à faire comme ce que j'ai écrit pour PHP 4 dans l'article précédent. (X). Pour les classes de widgets HTML, j'aimerais inclure cet opérateur dans leur méthode "getHTML()", permettant ainsi la création de pages Web qui génèrent des éléments (X)HTML imbriqués.
4. Étendre l'utilisation de l'opérateur "instanceof" : les widgets (X)HTML imbriqués
sont bons. Vous avez vu que l'opérateur "instanceof" fonctionne bien dans la vérification de type sur les objets d'entrée qui sont directement injectés dans la fonctionnalité de création de page. Maintenant, je vais aller plus loin et ajouter une routine de vérification au constructeur et à la méthode "getHTML()" de la classe de widget (X)HTML afin qu'ils puissent accepter d'autres widgets comme paramètres d'entrée. Veuillez vérifier les améliorations ci-dessous.
la classe Div étend HTMLElement{
private $output='<div';
données $ privées ;
fonction publique __construct($attributes=array(),$data){
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Type de paramètre invalide');
}
parent::__construct($attributs);
$this->data=$data;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->instance de données de HTMLElement) ?
$this->data->getHTML():$this->data;
$this->output.='</div>';
renvoie $this->output ;
}
}
la classe Header1 étend HTMLElement{
privé $output='<h1 ';
données $ privées ;
fonction publique __construct($attributes=array(),$data){
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Type de paramètre invalide');
}
parent::__construct($attributs);
$this->data=$data;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->instance de données de HTMLElement) ?
$this->data->getHTML():$this->data;
$this->output.='</h1>';
renvoie $this->output ;
}
}
Le paragraphe de classe étend HTMLElement{
privé $output='<p ';
données $ privées ;
fonction publique __construct($attributes=array(),$data){
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Type de paramètre invalide');
}
parent::__construct($attributs);
$this->data=$data;
}
//L'implémentation spécifique de la méthode 'getHTML()' public function getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
$this->output.=($this->instance de données de HTMLElement) ?
$this->data->getHTML():$this->data;
$this->output.='</p>';
renvoie $this->output ;
}
}
la classe UnorderedList étend HTMLElement{
private $output='<ul';
private $items=array();
fonction publique __construct($attributes=array(), $items=array()){
parent::__construct($attributs);
si(!is_array($items)){
throw new Exception('Paramètre non valide pour les éléments de la liste');
}
$this->items=$items;
}
//L'implémentation spécifique de la méthode 'getHTML()'
fonction publique getHTML(){
foreach($this->attributs comme $attribute=>$value){
$this->output.=$attribute.'="'.$value.'" ';
}
$this->output=substr_replace($this->output,'>',-1);
foreach($this->items as $item){
$this->output.=($item instanceof
HTMLElement)?'<li>'.$item->getHTML().'</li>':'<li>'.$item.'</li>';
}
$this->output.='</ul>';
renvoie $this->output ;
}
}
Comme indiqué dans les classes ci-dessus, afin de permettre l'implémentation d'éléments (X)HTML imbriqués lors de la génération des pages Web correspondantes, j'ai refactorisé respectivement leurs constructeurs et leurs méthodes "getHTML()". Notez que j'ai inclus le bloc conditionnel suivant dans le constructeur de chaque classe :
if(!$data instanceof HTMLElement&&!is_string($data)){
throw new Exception('Type de paramètre invalide');
}
À ce stade, ce que je fais en réalité, c'est m'assurer que seules les données de chaîne et les objets de type "HTMLElement" sont autorisés comme paramètres d'entrée pour chaque classe. Sinon, une exception sera levée par la méthode respective et pourra entraîner l’arrêt de l’exécution de l’application. C'est donc le processus de vérification des données d'entrée. Regardons maintenant la nouvelle signature de la méthode "getHTML()", qui utilise également l'opérateur "instanceof" :
$this->output.=($this->data instanceof HTMLElement)?$this->data-
>getHTML():$this->data;
Comme vous pouvez le voir, dans ce cas, l'opérateur this est très utile pour profiter des fonctionnalités polymorphes de la classe de widget (X)HTML. Si l'attribut $data est également un widget, alors sa méthode "getHTML()" sera appelée correctement, ce qui entraînera l'affichage de l'élément Web imbriqué. En revanche, s'il ne s'agit que d'une chaîne, alors elle est ajoutée directement à toutes les sorties de la classe actuelle.
À ce stade, vous avez peut-être compris l'utilisation de l'opérateur "instanceof" dans PHP 5 afin de garantir que certains objets appartiennent à un type spécifique. Comme vous pouvez le voir dans cet article, forcer les types d'objets dans PHP 5 est en fait une tâche assez simple. Pour l'instant, vous feriez mieux de développer un exemple d'utilisation de cette méthode pour filtrer des objets dans votre application PHP afin d'approfondir votre compréhension.
5. Résumé
Dans cet article, vous avez appris à utiliser l'opérateur "instanceof" dans PHP 5 pour vérifier le type de votre objet d'entrée, cependant, la méthode que je vous ai montrée n'est pas la seule ; Dans un article ultérieur, je vous expliquerai comment implémenter la fonctionnalité « indication de type » dans PHP 5, qui est une autre façon d'imposer le typage d'objets.
Auteur : Compilateur Zhu Xianzhong Source : Tianji Development