web-dev-qa-db-fra.com

Tous les plugins doivent-ils être encapsulés dans une classe?

Lors du développement d'un plugin, les fonctions doivent-elles être regroupées dans une classe pour éviter les conflits d'espaces de noms?

L'utilisation de classes crée-t-elle des frais généraux de performance pour PHP?

En cas de baisse des performances, les noms de fonction doivent-ils simplement être pré-fixés à la place?

29
Jamie

Lors du développement d'un plugin, les fonctions doivent-elles être regroupées dans une classe pour éviter les conflits d'espaces de noms?

Oui, mais ce n'est qu'un des arguments mineurs. En fait, ce n'est pas la "vraie" nature d'une classe dans OOAD .

L'utilisation de classes crée-t-elle des frais généraux de performance pour PHP?

Non, pas notamment. Une mauvaise conception et/ou un code mal écrit ou une optimisation prématurée créent beaucoup plus de problèmes de performances que les fonctionnalités de langage réelles.

En cas de baisse des performances, les noms de fonction doivent-ils simplement être pré-fixés à la place?

Tel qu'écrit, il n'y a aucun impact sur les performances. Un mauvais code écrit aura plus de succès qu'un bon code écrit qui contient plus de lignes de code mais ne vous oblige pas à faire de mauvaises choses.


Résultat final:

Vous pouvez utiliser différemment les classes pour les plugins. Vous pouvez simplement les utiliser pour avoir un certain espace de noms et les utiliser "juste" pour des fonctions globales. La forme la plus directe est celle des fonctions de classe statiques. L'exemple de code suivant montre les deux fonctions, d'abord globale, puis globale, statique:

/* global function */
function myplug_hook()
{
}

add_filter('the_hook', 'myplug_hook');


/* global static function */
class myplug
{
    public static function hook()
    {
    }
}

add_filter('the_hook', 'myplug::hook');

Ceci est juste un petit exemple montrant que vous devez taper plus pour le crochet simple. En outre, il montre le fonctionnement de l'espacement de nom: Vous pouvez plus facilement remplacer le nom de classe unique pour renommer toutes les fonctions statiques, puis rechercher et remplacer myplug::, ce qui pourrait être plus difficile avec myplug_ en raison de faux positifs. Mais au final il n'y a pas beaucoup de différence.

Le point clé est: fonctions de classe statiques Docs ne sont pas vraiment grand chose d'autre que fonctions globalesDocs .

Et cet exemple montre également ceci: le namespacing est correct, mais avec worpdress, il cesse avec l'utilisation de hooks: la fonction de rappel est codée, d'où l'intérêt de l'espacement en utilisant la classe (une place pour le nom de base, le nom de classe) ne l'est pas. aider lorsque vous intervenez votre code avec wordpress pour les noms de hook.

L'avantage réel commence par l'utilisation d'instances de classe réelles et de fonctions non statiques. Cela présente l’avantage de pouvoir commencer à utiliser les principes OO et de rationaliser votre code. Les fonctions de classe statiques sont plus un problème qu'une solution en fait.

Ensuite, il ne s'agit pas que du sucre syntaxique.

Le point clé est: Faites quelque chose qui vous aide à écrire le code que vous pouvez facilement gérer et maintenir. Ne surestimez pas les performances, c'est une erreur courante. Le plus important est que vous écriviez un code facile à lire et à comprendre, qui ne fait que ce dont vous avez besoin. Peut-être que cette question et cette réponse sont utiles pour une image plus grande dans ce contexte: Aide Multiple Custom Metabox .

Une approche commune que j'ai même avec de plus petits plugins utilise une fonction d'assistance statique pour instancier le plugin et le reste réside dans l'instance du plugin. Cela aide à encapsuler la logique du plugin principal et à tirer profit de l'espacement des noms avec les hooks, ainsi que du fait que les membres privés peuvent être réutilisés entre les hooks, ce qui n'est pas possible avec les fonctions globales standard. L'exemple de code suivant montre le motif:

<?php
/** Plugin Headers ... */

return MyPlugin::bootstrap(); 

class MyPlugin
{
    /** @var MyPlugin */
    static $instance;
    static public function bootstrap() {
        if (NULL === self::$instance) {
            self::$instance = new __CLASS__;
        }
        return self::$instance;
    }
    # ...
}

C'est un motif commun que j'utilise pour le fichier de plugin de base. La classe plugin, d’une part, représente le plugin de wordpress et, d’autre part, elle permet de commencer à utiliser des paradigmes orientés objet pour le propre code, qui peut même être totalement orienté objet (mais ne doit pas nécessairement l'être). C'est une sorte de contrôleur, s'interfaçant avec la totalité de l'API wordpress en tant que requête (s).

Comme le montre l'exemple, une instance du plugin sera créée. Cela vous permet d’utiliser des ressources communes connues comme un constructeur Docs (__construct) pour initialiser le plugin actuel:

# ...
class MyPlugin
{
    # ...
    public function __construct()
    {
        add_filter('the_hook', array($this, 'hook'));
    }

    public function hook()
    {
    }
    # ...
}

Au moment où le hook est enregistré, cet objet plugin bénéficie déjà de sa conception: vous avez cessé de coder en dur la fonction de hook réelle contre le plugin concret nom de classe _. C'est possible en raison de la liaison de la classe à l'instance d'objet pour le rappel. Cela semble compliqué, il suffit de dire: $thisest le plugin. Peut être utilisé dans les rappels au crochet, comparez Enregistrement de méthodes de classe en tant que rappels au crochet .

Ce modèle permet une interface plus facile avec wordpress: l'injection est réduite aux noms des crochets et aux données qu'ils fournissent. Vous pouvez ensuite commencer à mettre en œuvre directement dans cette classe de plug-in ou à refactoriser votre implémentation en conséquence, de manière à ne placer dans la classe de plug-in que le minimum nécessaire pour définir votre interface de plug-in contre wordpress, tout en maintenant la logique générale à côté de worpdress. C’est là que commence le plaisir et très probablement ce que chaque auteur de plugin veut réaliser à long terme.

Donc, ne programmez pas avec Wormpdress mais contre. Comme WORpdress est assez flexible, il n’existe pas d’interface commune ou facile à décrire. Une classe de plug-in de base peut assumer ce rôle, vous permettant une plus grande flexibilité pour votre propre code, ce qui facilitera le code et améliorera les performances.

Il y a donc plus qu'un avantage à espacer les noms. La meilleure suggestion que je puisse vous donner est: essayez vous-même. Il n'y a pas grand chose à perdre, seulement de nouvelles choses à découvrir.

Vous remarquerez probablement des différences après avoir passé des mises à jour plus importantes de Wordpress tout en maintenant votre plugin compatible.

Caveat: Si votre plugin s'intègre directement à wordpress pour faire le travail, utiliser une ou deux fonctions publiques pourrait vous convenir mieux. Prenez le bon outil pour le travail.

25
hakre

Classes VS ensemble de fonctions


Performance

Général: Bien, il n'y a pas de différence de "performance" entre les classes et les ensembles de fonctions.

Détail:

  • Il y a une grande différence si vous interrogez function_exists() par rapport à class_exists() car vous avez normalement beaucoup de fonctions (environ 1 800 (?) Dans le noyau wp) par rapport aux classes (~ 100 (?) Dans le noyau wp). Donc, faire des choses "connectables" et donc questionner l'existence estune différence de temps d'exécution.
  • Les classes offrent un grosavantage sur les ensembles de fonctions: vous pouvez beaucoup plus facilement éviter de l'appeler sur une requête où vous n'en avez pas besoin, puis avec des fonctions. Vous devez uniquement effectuer des contrôles conditionnels pour la classe et non pour chaque fonction. Ainsi, si vous n'en avez pas besoin à chaque chargement de page et que vous pouvez éviter d'appeler de nombreuses instructions if/else, une fonction "fonctionnera mieux".

Architecture - Comment ça marche:

ensemble de fonctions: En général, les fonctions sont exécutées à la ligne que vous appelez. Ainsi, chaque fois que vous appelez des éléments, vous devez les réécrire, si vous devez les appeler plusieurs fois.

Classe: Il existe différentes approches pour les classes. La classe qui se rapproche le plus d'un ensemble de fonctions est la classe "factory" ( wikipedia / google ). Imo, c'est presque la même chose qu'un ensemble de fonctions, mais encapsulé dans une classe. Mais il existe aussi d'autres "types" de classes. Vous pouvez par exemple écrire un abstractou une classe de classe parent, que vous étendez avec une classe enfant. Dans un exemple concret: supposons que vous ayez une classe qui génère des champs de texte statiques. Dans votre fonction __construct(), vous avez un ensemble de scénarios tels que "left_column", "right_column" & "footer_field". Ensuite, vous appelez quelque chose comme $text_field = new TextFieldClass(); pour instancier la classe. Et plus tard, vous appelez simplement $text_field->add( $case => 'left_column', 'case' => 'foo text' ); et $text_field->add( $case => 'footer_field', 'case' => 'bar text' );. Tous vos conditionnels et autres ont déjà été effectués lorsque vous avez instancié la classe et seulement les deux fonctions de classe auraient été appelées lors de la création des champs de texte, ce qui vous aurait permis de gagner du temps d’exécution.


Opinion personnelle

Si vous écrivez vos cours avec sagesse, vous aurez alors un mineuravantage en performance). Mais vous aurez une structure bien organisée sur laquelle travailler. Jusqu'à présent, rien de spectaculaire. Mais si vous envisagez l'utilisation suivante du "split" cas pour les classes et les fonctions dans un plugin, alors vous obtiendrez mon finalpoint: La classe est interne, les fonctions sont API . Tant que vous n'offrez l'API que via des fonctions utilisables publiquement ( classes d’appel ou fonctions de classe), vous serez sur le côté de la sauvegarde pour développer votre plugin. Vous avez acquis la liberté de changer la structure interne ou même les possibilités de votre plugin sans affecter les utilisateurs, à tout moment et partout.

Exemple:

// construction of object
if ( ! class_exists( 'WPSE_HelloWorld' ) )
{

class WPSE_HelloWorld
{
    function __construct( $args = array( 'text', 'html', 'echo' ) )
    {
        // call your object building procedures here
        $this->hello_world( 'text', 'html', 'echo' );
    }

    function hello_world( 'text', 'html', 'echo' )
    {
        $start_el = '<{$html}>';
        $end_el = '</{$html}>';
        if ( $echo )
        {
            return print "{$start_el}{$some}{$end_el}";
        }

        return "{$start_el}{$some}{$end_el}";
    }
} // END Class 

}

// API: public functions
function the_hello_world( $args( 'echo' => true ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

function get_hello_world( array( $args( 'echo' => false) ) )
{
    $new = new WPSE_HelloWorld();
    return $new->hello_world( $args );
}

// then you can call it like get_the_title() or the_title(), which you know from the WP API:
// 'echo' is set to false per default:
$some_var = get_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *returns* "<strong>hello reader</strong>"

// 'echo' is set to true per default:
the_hello_world( array( 'text' => 'hello reader', 'html' => 'strong' ) );
# *prints/echos* "<strong>hello reader</strong>"

Remarque: veuillez également lire le lien @ t310s affiché dans le commentaire du Q.

9
kaiser

C'est un choix purement stylistique de la part de l'auteur du plugin. Il n'y a pas de réelle différence en termes de rapidité.

4
Otto

Les classes n'offrent généralement pas d'avantages en termes de performances, mais elles ont très rarement des effets négatifs. Leur véritable avantage est de rendre le code plus clair et d'éviter les conflits d'espace de noms.

1
Bainternet

La plupart du temps, si vous utilisez des fonctions, vous inscrivez le nom du plug-in dans chaque nom de fonction. Vous devez donc dupliquer ce nom une douzaine de fois si le plug-in comporte une douzaine de fonctions, ce qui est un peu traînant. .

Avec les classes, vous n’auriez probablement le nom du plug-in qu’une seule fois.

De plus, vous pouvez utiliser l'héritage ou d'autres constructions oo pour implémenter les comportements de manière très propre. Voici un ex:

class animalplugin{
  //plugin functions...
  function talk(){print "animalnoise";}
}
class animalplugin_with_cat_mods extends abcplugin{
  //cat functions overrides
  function talk(){print "meow";}
}
if (iscat()){
  new animalplugin_with_cat_mods();
} else {
  new animalplugin();
}
0
zeedre