web-dev-qa-db-fra.com

Réduire l'utilisation de Global Post

Lors de la création de boîtes à méta, dans chaque fonction de boîte à méta, il semble qu'une référence au global $post soit passée en tant que paramètre ($event). Je préfère cela, car cela semble cohérent et moins susceptible de fausser le $post var en le déclarant explicitement comme je l'ai lu ailleurs.

add_action('admin_init', 'events_admin');
function events_admin() 
{
     add_meta_box('display_events_date_meta_box',
        'Dates',
        'display_events_date_meta_box',
        'events', 'normal', 'high'
    );

}

function display_events_date_meta_box($event) // Referenced
{
     //$event in this case is the $post global
}

J'ai créé un filtre et diverses autres fonctions qui n'utilisent actuellement que la variable global $post.

add_action( 'admin_head-post-new.php', 'test' );
add_action( 'admin_head-post.php', 'test' );
function test()
{
    global $post; // Declared explicitly
}

Existe-t-il un moyen standard/recommandé de transmettre la variable global $post en tant que paramètre à ces fonctions?

7
myol

Lorsque j'ai besoin de traiter la variable $post sous admin, j'utilise généralement une classe pour capturer et encapsuler la variable globale $post à un stade précoce, en obtenant un moyen d'accès universel sans recourir de manière répétée à la variable globale.

class MyAdminPost 
{

   private static $post;

   public static function init()
   {
     $p_get = filter_input(INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT);
     $p_post = filter_input(INPUT_POST, 'post', FILTER_SANITIZE_NUMBER_INT);
     if ($p_get > 0 || $p_post > 0) {
       self::$post = $p_get > 0 ? get_post($p_get) : get_post($p_post);
     } elseif ($GLOBALS['pagenow'] === 'post-new.php') {
       add_action('new_to_auto-draft', function(\WP_Post $post) {
         if (is_null(MyAdminPost::$post)) {
           MyAdminPost::$post = $post;
         }
       }, 0);
     }
   }

   public function get()
   {
     return self::$post;
   }
}

add_action('admin_init', array('MyAdminPost', 'init'));

Au début du chargement de l'administrateur, c'est-à-dire 'admin_init' hook, la classe 'MyAdminPost' recherche la variable post ID envoyée avec l'objet post associé à la demande et au magasin.

Cela fonctionne sur la page post.php, mais pas sur post-new.php, car sur cette page, l'ID de publication n'est pas envoyé avec la requête car il n'existe pas encore. Dans ce cas, j'ajoute un rappel à 'new_to_auto-draft' qui est l'un des crochets "{old_status}_to_{new_status}" pour stocker la publication immédiatement après sa création sur la page post-new.php.

De cette manière, dans les deux pages, l'objet post est stocké très tôt dans une propriété de classe.

Exemple d'utilisation (procédural)

function get_my_admin_post()
{
   static $post = null;
   if (is_null($post) && did_action('admin_init')) {
     $map = new MyAdminPost();
     $post = $map->get(); 
   }

   return $post;
}

add_action('admin_head-post.php', 'test');

function test()
{
    $post = get_my_admin_post();
}

Exemple d'utilisation (POO)

class ClassThatUsesPostObject
{

  private $post_provider;

  function __construct(MyAdminPost $map)
  {
     $this->post_provider = $map;
  }

  function doSomethingWithPost()
  {
    $post = $this->post_provider->get();
  }
}

Avantages

  • vous pouvez obtenir très tôt l'objet post d'une manière compatible avec les pages post.php et post-new.php, donc dans all les points d'ancrage activés dans ces pages, vous avez accès à l'objet post sans effort

  • vous supprimez toute référence de variable globale $post dans votre code

  • votre code devient testable isolément

8
gmazzap

admin_head-{$hook_suffix} est déclenché sur chaque page d'administrateur, donc passer quelque chose à cette fonction n'aurait probablement aucun sens. Vous pouvez voir dans la source qu'aucun argument n'est passé:

do_action( "admin_head-$hook_suffix" );

Dans de nombreux cas, vous n’avez pas d’autre alternative à global $post, et si vous parcourez à peu près n’importe quel fichier source principal, vous verrez partout une global litre, en raison de la construction essentiellement procédurale du noyau et de l’objectif principal de maintenir la compatibilité avec les versions antérieures. C'est désordonné mais surtout inoffensif si vous n'accédez qu'à sa valeur dans un contexte connu .

1
Milo

Vous ne pouvez pas facilement modifier les paramètres utilisés avec un filtre/une action existant car ils sont définis par le code "appelant", vous ne pouvez donc pas injecter de paramètres supplémentaires. Il serait peut-être possible de le faire en piratant le code principal derrière do_action/apply_filter, mais si vous y parvenez, vous risquez probablement de détruire tous les autres codes liés aux actions/filtres.

1
Mark Kaplun