PHP verwendet eine private Methode als Callback

Lesezeit: 3 Minuten

Benutzer-Avatar
Silicomancer

Ich experimentiere zum ersten Mal mit PHP+WP. Ich beabsichtige, WP-Plugin-Hooks zu verwenden. Als C++-Programmierer beabsichtige ich auch, meinen gesamten Code in Klassen zu packen. Derzeit hänge ich mit dem folgenden Snippet fest, das einen WP-Plugin-Hook installieren sollte:

   class SettingsHandler
   {
      public function __construct()
      {
         add_filter('plugin_action_links', array($this, 'AddSettingsLink'), 10, 2);
      }

      private function AddSettingsLink($links, $file)
      {
         if ($file==plugin_basename(__FILE__))
         {
            $settings_link = '<a href="https://stackoverflow.com/questions/22426794/options-general.php?page=options_page">Settings</a>';
            array_unshift($links, $settings_link);
         }       
         return $links;
      }
   }

   $settingsHandler = new SettingsHandler();

Dies gibt mir eine Fehlermeldung: Warnung: call_user_func_array() erwartet, dass Parameter 1 ein gültiger Rückruf ist, kann nicht auf die private Methode SettingsHandler::AddSettingsLink() in E:\xampp\apps\wordpress\htdocs\wp-includes\plugin.php zugreifen auf Linie 199

Wenn ich den Callback auf public schalte, ist der Fehler weg. Es scheint, dass ich eine private Methode nicht als Callback in PHP/WP verwenden kann. Dies wäre sehr schlecht, da es viele Callback-Methoden offenbart, auf die niemand direkt zugreifen sollte. Kann ich solche Rückrufe privat machen?

Ich habe auch das folgende Snippet gefunden, das gut läuft:

   class a
   {
      public function __construct()
      {
         $str = " test test ";
         $result = preg_replace_callback('/test/', array($this, 'callback'), $str);
         echo $result;
      } 

      private function callback($m)
      {
         return 'replaced';
      }
   }

   $a = new a();

Warum funktioniert das zweite Snippet, während das erste fehlschlägt? Wo ist der Unterschied?

  • Ihr erster Callback wird nicht innerhalb Ihres Objektkontexts aufgerufen, sondern von einem externen Plugin-Handler. Warum besteht man dann darauf, die Callback-Methode privat zu halten?

    – mario

    15. März 2014 um 17:01 Uhr

  • Schreiben Sie Wrapper (öffentliche Methoden) für solche privaten Methoden und übergeben Sie diese Wrapper als Callback.

    – hinterste

    15. März 2014 um 17:17 Uhr

Benutzer-Avatar
Gordon

Die zweite Version funktioniert, weil preg_match_all wird innerhalb des Klassenbereichs aufgerufen und führt den Rückruf sofort aus.

Aber das add_filter Funktion fügt nur den Rückruf zur globalen hinzu $wp_filter Reihe. Die Callbacks in diesem Array werden dann zu einem späteren Zeitpunkt von aufgerufen außen die Klasse, in der Sie die Methode definiert haben. Folglich gelten Sichtbarkeitsregeln, die den Rückruf unzugänglich machen.

Sie können dies umgehen¹, indem Sie den Aufruf der Methode in eine umschließen Anonyme Funktionz.B

public function __construct()
{
    add_filter(
        'plugin_action_links',
        function($links, $file) {
            return $this->AddSettingsLink($links, $file);
        },
        10,
        2
    );
}

Allerdings setzt dies aufgrund von mindestens PHP 5.4 (siehe Changelog im Handbuch) voraus $this in der anonymen Funktion vor dieser Version nicht verfügbar.

Eine andere Möglichkeit wäre, die zu haben SettingsHandler implementieren __invoke um es in einen Functor umzuwandeln, zB Sie addieren

public function __invoke($links, $file)
{
    return $this->AddSettingsLink($links, $file);
}

und ändern Sie den Ctor-Code in

add_filter('plugin_action_links', $this, 10, 2);

Da die Klasse implementiert __invoke Als öffentlicher Einstiegspunkt kann die Instanz als Callback verwendet werden. Auf diese Weise können Sie die privaten Dinge privat halten.

Nebenbei bemerkt, ich würde den Code verschieben, der den Filter außerhalb der Klasse hinzufügt. Wenn Sie es im ctor haben, ist die Klasse weniger testbar (ja, ich weiß, niemand testet WP-Plugins, aber trotzdem). Fügen Sie es stattdessen in Ihre Plugin-Datei ein und fügen Sie dann alles andere Erforderliche von dort hinzu, z

// your-plugin.php
include 'SettingsHandler.php';
add_filter('plugin_action_links', new SettingsHandler, 10, 2);

Aber das liegt an Ihnen.

¹Notiz: Anscheinend funktioniert dies nicht in WordPress, da es versucht, den Abschluss irgendwo auf dem Weg zu serialisieren. Im Allgemeinen ist dies ein Arbeitsmuster, um private Methoden als Rückrufe bereitzustellen.

  • Ich habe die Problemumgehung für die anonyme Funktion ausprobiert … Fehler “Serialisierung von ‘Closure’ ist nicht zulässig”

    – Silicomancer

    15. März 2014 um 23:11 Uhr


  • @Silicomancer hmm, interessant. Leider bin ich mit dem Innenleben von WP nicht vertraut genug, um zu wissen, wo es versucht, die Closure/Anonymous-Funktion zu serialisieren. Ich habe ohne WP getestet und dann würde es funktionieren. Ich werde die Frage aktualisieren, um Ihr Ergebnis zu notieren.

    – Gordon

    16. März 2014 um 9:34 Uhr

  • Das kann ich nicht bestätigen, die Lösung mit der anonymen Funktion hat bei mir einwandfrei funktioniert; eigentlich ziemlich einfach; Dank dafür!

    – DevelJoe

    26. Dezember 2020 um 12:43 Uhr

1283620cookie-checkPHP verwendet eine private Methode als Callback

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy