web-dev-qa-db-fra.com

Utilisation de register_activation_hook dans les classes

J'essaie de développer un plugin à des fins de référencement de base, car beaucoup de personnes que je connais n'aiment pas utiliser Yoast. Je viens littéralement de commencer le plugin et je construis le message d'activation affiché à l'utilisateur lorsqu'il active le plugin. J'ai des problèmes avec un mélange entre OOP et les fonctions Wordpress intégrées, et je ne sais pas trop où je me trompe.

La seule façon pour que cela fonctionne est de créer une nouvelle instance du SEO_Plugin_Activation class dans le constructeur de mon fichier principal, puis d’appeler la méthode activatePlugin dans cette classe. Je pense que c'est inutile. Je pense aussi que la manière dont j'exécute mes fonctions dans le fichier de classe d'activation n'a pas vraiment de sens non plus. Mais c'est la seule façon pour moi de le faire fonctionner pour le moment.

Je ne sais pas si ce que je fais est parce que je ne saisis pas OOP techniques à 100%, ou si je n'utilise pas correctement l'API Wordpress. J'ai inclus trois exemples de code dans l'ordre suivant:

  1. Fichier du plugin principal
  2. Fichier de classe qui gère mes exigences d'activation
  3. Ce que j'espérais vraiment pouvoir être fait.

seo.php (fichier du plugin principal)

<?php
/*
... generic plugin info
*/

require_once(dirname(__FILE__) . '/admin/class-plugin-activation.php');

class SEO {
  function __construct() {
    $activate = new SEO_Plugin_Activation();
    $activate->activatePlugin();
  }

}

new SEO();
?>

class-plugin-activation.php

<?php
class SEO_Plugin_Activation {

  function __construct() {
    register_activation_hook(__FILE__ . '../seo.php', array($this, 'activatePlugin'));
    add_action('admin_notices', array($this, 'showSitemapInfo'));
  }

  function activatePlugin() {
    set_transient('show_sitemap_info', true, 5);
  }

  function showSitemapInfo() {
    if(get_transient('show_sitemap_info')) {
      echo '<div class="updated notice is-dismissible">' .
              'Your sitemap files can be found at these following links: ' .
            '</div>';
      delete_transient('show_sitemap_info');
    }
  }

}
?>

seo.php (Ce que j'espérais)

<?php
/*
 ... blah blah blah
*/

require_once(dirname(__FILE__) . '/admin/class-plugin-activation.php');

class SEO {
  function __construct() {
    register_activation_hook(__FILE__, array($this, 'wp_install'));
  }

  function wp_install() {
    $activate = new SEO_Plugin_Activation();
    // Execute some method(s) here that would take care 
    // of all of my plugin activation bootstrapping
  }

}

new SEO();
?>

J'ai essayé de le faire comme je l'ai décrit dans le troisième script, mais je n'ai pas réussi. À l'heure actuelle, le message s'affiche correctement, sans message d'erreur.

3
Dan Zuzevich

Après avoir relu votre question, je pense comprendre le problème, et cela découle d'un malentendu sur le fonctionnement de register_activation_hook, associé à une certaine confusion quant à la manière dont vous démarrez votre code et ce que cela signifie pour bootstrap

Partie 1: register_activation_hook

Cette fonction prend 2 paramètres:

register_activation_hook (chaîne $ fichier, fonction appelable $)

Le premier paramètre, $file, est le fichier de plugin principal, pas le fichier contenant ce que vous voulez exécuter. Il est utilisé de la même manière que plugins_url, vous avez donc besoin de la valeur __FILE__, plus précisément de sa valeur dans le fichier de plug-in racine contenant l'en-tête de votre plugin.

Le second paramètre est appelable et fonctionne comme vous le souhaitez, mais il utilise vraiment add_action en interne

Lorsqu’un plug-in est activé, l’action hook "activate_PLUGINNAME" est appelée. Dans le nom de ce hook, PLUGINNAME est remplacé par le nom du plugin, y compris le sous-répertoire optionnel. Par exemple, lorsque le plug-in se trouve dans wp-content/plugins/sampleplugin/sample.php, le nom de ce hook devient alors "activate_sampleplugin/sample.php".

Partie 2: amorçage et __FILE__

Un problème fondamental ici est que __FILE__ aura différentes valeurs en différents endroits et que vous avez besoin d’une valeur spécifique.

Vous avez également un problème, le démarrage devrait assembler le graphe d'objets, mais vous ne le faites pas. Tous vos objets sont créés dès qu’ils sont définis ou créés l’un dans l’autre, ce qui rend difficile voire impossible la transmission de valeurs.

Par exemple, je pourrais écrire un plugin comme ceci:

plugin.php:

<?php
/**
 * Plugin Name: My Plugin
 * Version: 0.1
 */

// loading step
require_once( 'php/app.php' );

// bootstrapping step
$app = new App( __FILE__ );

// execution step
$app->run();

J'ai défini toutes mes classes dans le sous-dossier php et les ai toutes chargées au même endroit. PHP sait maintenant quelles sont mes classes, leurs noms, etc., mais rien n'est encore arrivé.

Je crée ensuite tous mes objets en leur transmettant ce dont ils ont besoin. Dans ce cas, App a besoin de la valeur __FILE__ et je le transmets. Notez que cela crée les objets en mémoire, mais ne fait aucun travail. L'application de plugins est prête à fonctionner, mais elle est en phase de préparation.

La prochaine étape consiste peut-être à canaliser ces objets vers un ensemble de tests unitaires, mais je vais maintenant les exécuter. Mon processus d'amorçage est terminé et l'application est prête à être exécutée. Je déclenche donc la méthode run. Je ne devrais pas avoir besoin de passer quoi que ce soit à run car tout le nécessaire a été passé aux constructeurs. Au cours de la méthode run, j'ajoute tous mes filtres et crochets. C'est pendant ces hooks que toutes les autres parties du plugin sont exécutées.

Ce qui est important, c’est que j’ai une structure définie et que je transmette ce qui est nécessaire pendant la phase de construction/démarrage, avec un cycle de vie défini.

7
Tom J Nowell

Tom McFarlin a créé un très vaste plugin boilerplate (maintenant géré par Devin Vinson), tous écrits en POO, que vous pouvez utiliser pour créer votre nouveau plugin ou simplement étudier le flux de l’application pour répondre à votre question. Je l'ai utilisé pour plusieurs plugins personnalisés, et je dois dire que cela m'a vraiment ouvert les yeux sur certains des mystères de la programmation orientée objet.

1
Gary D

Vous devez vraiment enregistrer vos crochets d'activation/désactivation/désinstallation en dehors de votre classe de plug-in, comme indiqué par la réponse de kaiser ici , qui fournit un bien meilleur aperçu que ce que je pourrais écrire à ce sujet.

Cela devrait vous couvrir si vous souhaitez écrire ce plugin comme exercice d'apprentissage. Si tout ce que vous cherchez, c'est un plugin SEO qui fonctionne bien et qui n'est pas recouvert de publicités gluantes comme Yoast, je peux fortement recommander The SEO Framework.

1
Chris Cox