add_action referenziert eine Klasse
7 Antworten
- Stimmen
-
- 2012-04-05
Nein,Sie können die Klassenicht direkt übereinen Hook 'initialisieren' oderinstanziieren. Esistimmerein zusätzlicher Codeerforderlich (undesistnicht wünschenswert,dies zutun,da Sieeine Dose Würmerfür sich selbst öffnen.
Hieristeine bessere Möglichkeit:
class MyClass { function __construct() { add_action( 'admin_init', [ $this, 'getStuffDone' ] ); } function getStuffDone() { // .. This is where stuff gets done .. } } $var = new MyClass();
Natürlich könntemaneine Schnittstellenklasseerstellen,um siefür den allgemeinen Fallnoch weiter zu vereinfachen:
class IGetStuffDone { function IGetStuffDone(){ add_action( 'admin_init', [ $this, 'getStuffDone' ] ); } public abstract function getStuffDone(); }
Beachten Sie,dass Sie als Schnittstelle kein Objekt dieses Typs direkterstellen können,sonderneine Unterklasse,in der Sie Folgendes sagen können:
class CDoingThings extends IGetStuffDone { function getStuffDone(){ // doing things } } $var = new CDoingThings();
Damit werden dann automatisch alle Hooks hinzugefügt. Siemüssen lediglich definieren,wasgenauin einer Unterklasse ausgeführt wird,undes dannerstellen!
Auf Konstruktoren
Ich würde keinen Konstruktor als Hook-Funktion hinzufügen,dasisteine schlechte Praxis und kann zu vielen ungewöhnlichen Ereignissenführen. In denmeisten Sprachengibt ein Konstruktor das Objekt zurück,dasinstanziiert wird. Wenn Ihr Hook alsoetwas wiein einem Filter zurückgebenmuss,gibt er diegefilterte Variablenicht wiegewünscht zurück,sondern das Klassenobjekt.
Das direkte Aufrufeneines Konstruktors oder Destruktorsisteine sehr,sehr,sehr schlechte Programmierpraxis,unabhängig davon,in welcher Sprache Sie sichbefinden,und sollte niemals durchgeführt werden.
Konstruktoren sollten auch Objekteerstellen,um siegebrauchsfertig zuinitialisieren,nichtfür dieeigentliche Arbeit. Die vom Objekt auszuführenden Arbeiten solltenin einer separaten Funktion ausgeführt werden.
Statische Klassenmethoden,die überhauptnichtinstanziiert/initialisiert werdenmüssen
Wenn Ihre Klassenmethodeeine statische Klassenmethodeist,können Sie den Namen der Klassein Anführungszeichen anstatt
$this
wie untengezeigt übergeben:class MyClass { public static function getStuffDone() { // .. This is where stuff gets done .. } } add_action( 'admin_init', [ __NAMESPACE__ . '\MyClass','getStuffDone' ] );
Beachten Sie die Verwendung von
__NAMESPACE__
,dieerforderlichist,wenn sich Ihre Klassein einem Namespacebefindet.Schließungen
Leider können Sienicht vermeiden,dass die Zeile dieneue Klasseerstellt. Dieeinzige andere Lösung zum Überspringen wäre der Kesselplattencode,dernoch diese Zeileenthält,z. B.:
add_action( 'admin_init', function() { $var = new MyClass(); $var->getStuffDone(); } );
An diesem Punkt können Sie die Klasse auch überspringen undeinfacheine Funktion verwenden:
add_action( 'admin_init', function() { // do stuff } );
Aber denken Sie daran,dass Siejetzt das Gespenst anonymer Funktioneneingeführt haben. Esgibt keine Möglichkeit,die obengenannte Aktionmit
remove_action
zuentfernen. Dies kann und kann Entwicklern,diemit dem Code anderer Benutzer arbeitenmüssen,große Schmerzenbereiten.Auf kaufmännischem Und
Möglicherweise werdenfolgende Aktionen angezeigt:
array( &$this, 'getStuffDone' )
Dasist schlecht .
&
wurdein PHP 4 wieder hinzugefügt,als Objekte als Werte undnicht als Referenzen übergeben wurden. PHP 4istmehr alsein Jahrzehnt alt und wurde seit langer Zeitnichtmehr von WordPress unterstützt.Esgibt keinen Grund ,
&this
zu verwenden,wenn Hooks und Filter hinzugefügt werden. Das Entfernen der Referenz verursacht keine Probleme und kann sogar die Kompatibilitätmit zukünftigen Versionen von verbessern PHPVerwenden Sie stattdessen Folgendes:
[ $this, 'getStuffDone' ]
No, you cannot 'initialise' or instantiate the class through a hook, not directly. Some additional code is always required ( and it is not a desirable thing to be able to do that, as you're opening a can of worms for yourself.
Here is a better way of doing it:
class MyClass { function __construct() { add_action( 'admin_init', [ $this, 'getStuffDone' ] ); } function getStuffDone() { // .. This is where stuff gets done .. } } $var = new MyClass();
Of course one could create an interface class to simplify it for the general case even further:
class IGetStuffDone { function IGetStuffDone(){ add_action( 'admin_init', [ $this, 'getStuffDone' ] ); } public abstract function getStuffDone(); }
Note that as an interface, you can't create an object of this type directly, but you could create a sub-class, letting you say:
class CDoingThings extends IGetStuffDone { function getStuffDone(){ // doing things } } $var = new CDoingThings();
Which would then automatically add all the hooks, you just need to define what exactly is being done in a subclass and then create it!
On Constructors
I wouldn't add a constructor as a hook function, it's bad practice, and can lead ot a lot of unusual events. Also in most languages a constructor returns the object that is being instantiated, so if your hook needs to return something like in a filter, it will not return the filtered variable as you want, but instead it will return the class object.
Directly calling a constructor or a destructor is very, very, very bad programming practice, no matter which language you're in, and should never be done.
Constructors should also construct objects, to initialise them ready for use, not for actual work. Work to be done by the object should be in a separate function.
Static class methods, and not needing to instantiate/initialise at all
If your class method is a static class method, you can pass the name of the class in quotes rather than
$this
as shown below:class MyClass { public static function getStuffDone() { // .. This is where stuff gets done .. } } add_action( 'admin_init', [ __NAMESPACE__ . '\MyClass','getStuffDone' ] );
Note the use of
__NAMESPACE__
which is required if your class is inside a namespace.Closures
Sadly you cannot avoid the line creating the new class. The only other solution to skipping it would involve boiler plate code that still has that line e.g.:
add_action( 'admin_init', function() { $var = new MyClass(); $var->getStuffDone(); } );
At which point you may as well skip the class, and just use a function:
add_action( 'admin_init', function() { // do stuff } );
But keep in mind you have now introduced the spectre of anonymous functions. There is no way to remove the above action using
remove_action
, and this can and does cause great pain for developers who have to work with other peoples code.On Ampersands
You may see actions used like this:
array( &$this, 'getStuffDone' )
This is bad.
&
was added back in PHP 4 when objects were passed as values, not as references. PHP 4 is more than a decade old, and hasn't been supported by WordPress in a very long time.There is no reason to use
&this
when adding hooks and filters, and removing the reference will cause no issues, and may even improve compatibility with future versions of PHPUse this instead:
[ $this, 'getStuffDone' ]
-
In Ordnung.Vielen Dank von all dem;habe wirklicheinigesgelernt.Ichfühlemichjetzt wirklichnurin klassenbasiertem PHP wohl.Diesist,wasichgetan habe undesfunktioniert,aber können Siemir sagen,obes schlechte Praxis/in irgendeiner Weisefalschist?Ich habe die Klasseinnerhalbeiner statischen Funktioninnerhalb der Klasse selbstinitiiert.Dann wird auf die statische Funktionin der add_action verwiesen.Siehe diesen Link: http://pastebin.com/0idyPwwYOk. Thank you from all of that; really learnt quite a bit. I'm really only getting comfortable in class based PHP now. This is what I have done, and it works, but could you tell me if it is bad practice/incorrect in any way? I've initiated the class inside a static function, within the class itself. Then referenced the static function in the add_action. See this link: http://pastebin.com/0idyPwwY
- 0
- 2012-04-05
- Matthew Ruddy
-
Ja,Sie könntenes somachen,obwohlich vermeiden könnte,"$ class" als Variablennamen zu verwenden,sind diese Wörtereher reserviert.Ich denke,Sietun alles,um zu vermeiden,dass Sieim globalen Bereichetwas Ähnliches wie "$ x=new Y ();" sagen,und Siefügen Komplexität hinzu,wenn keineerforderlichist.Ihr Versuch,die Menge desgeschriebenen Codes zu reduzieren,hat dazugeführt,dass Siemehr Codegeschrieben haben!yes you could do it that way, though I could avoid using `$class` as your variable name, those words tend to be reserved. I think you're going way out of your way to avoid saying something similar to `$x = new Y();` in the global scope, and you're adding complexity where none is necessary. Your attempt to reduce the amount of code written has involved writing more code!
- 0
- 2012-04-05
- Tom J Nowell
-
Ichmöchtein allen obengenannten Fällen darauf hinweisen,dass Siebessereine Funktion alseine Klasse verwenden sollten,da diese Klasse ohnehin verworfen wird und denselben Zweckerfüllt.Esisteine Verschwendung von Ressourcen.Denken Sie daran,dass das Erstellen und Zerstöreneines Objektsmit Kosten verbundenist. Siemöchtennur wenige Objekte undmöchten,dass sie langlebig sindI'd point out in all of the above cases, you would be better off using a function rather than a class, as that class will be discarded anyway and serves the same purpose. It's a waste of resources. Remember, there is a cost to creating and destroying an object, you want few objects, and you want them to be long lived
- 0
- 2012-04-05
- Tom J Nowell
-
Guter Punkt.Die Art und Weise,wieichesgesehen habe,hat sichgeändert.Ich denke,ich werdees stattdessenim globalen Bereich aufrufen und den zusätzlichen Code vermeiden.Good point. Changed the way I've been looking at it. I think I'll call it in the global scope instead, avoiding the extra code.
- 0
- 2012-04-05
- Matthew Ruddy
-
Ichmöchte hinzufügen,dass,wenn Sie Ihre Klasse zufälligin einen Namespacegestellt haben,Sie diesebenfalls hinzufügenmüssen,oder add_action ()/add_filter ()esnichtfindet - wiefolgt: `` `add_action ('admin_init'),array ('MyNamespace \ MyClass','getStuffDone')); `` `I would like to add that if you happen to have put your class in a namespace, you will have to add that too or add_action()/add_filter() won't find it - like this: ```add_action( 'admin_init', array('MyNamespace\MyClass','getStuffDone' ) );```
- 1
- 2018-04-27
- jschrab
-
- 2012-04-05
Beispielklasse
Hinweise:
- Initiiere die Klassenureinmal
- Rufen Sie Priorität 0 auf,damit Sie später denselben Hookmit der Standardpriorität verwenden können
- Wickeln Sieesin einen
! class_exists
,umein zweimaliges Aufrufen zu vermeiden,undplatzieren Sie deninit-Aufruferin
- Machen Sie die Funktion
init
und die Klasse varstatic
- Rufen Sie den Konstruktorin Ihrem Init auf,wenn Sie die Klasse
new self
aufrufen.Hieristein Beispiel
if ( ! class_exists( 'WPSESampleClass' ) ) { // Init the class on priority 0 to avoid adding priority inside the class as default = 10 add_action( 'init', array ( 'WPSESampleClass', 'init' ), 0 ); class WPSESampleClass { /** * The Class Object */ static private $class = null; public static function init() { if ( null === self::$class ) self :: $class = new self; return self :: $class; } public function __construct() { // do stuff like add action calls: add_action( 'init', array( $this, 'cb_fn_name' ) ); } public function cb_fn_name() { // do stuff } } // END Class WPSESampleClass } // endif;
Php 5+
Bitte ,lassen Sie den
&
weg. Wir sind schonjenseits von PHP4. :)Example class
Notes:
- Init the class only once
- Call on priority 0, so you can use the same hook with the default priority later
- Wrap it up in a
! class_exists
to avoid calling it twice and place the init caller inside
- Make the
init
function and the class varstatic
- Call the constructor from inside your init, when you call the class
new self
.
Here's an example
if ( ! class_exists( 'WPSESampleClass' ) ) { // Init the class on priority 0 to avoid adding priority inside the class as default = 10 add_action( 'init', array ( 'WPSESampleClass', 'init' ), 0 ); class WPSESampleClass { /** * The Class Object */ static private $class = null; public static function init() { if ( null === self::$class ) self :: $class = new self; return self :: $class; } public function __construct() { // do stuff like add action calls: add_action( 'init', array( $this, 'cb_fn_name' ) ); } public function cb_fn_name() { // do stuff } } // END Class WPSESampleClass } // endif;
Php 5+
Please, leave the
&
out. We're already beyond php4. :) -
- 2018-03-04
if (!class_exists("AllInOneWoo")){ class AllInOneWoo { function __construct(){ add_action('admin_menu', array($this, 'all_in_one_woo') ); } function all_in_one_woo(){ $page_title = 'All In One Woo'; $menu_title = 'All In One Woo'; $capability = 'manage_options'; $menu_slug = 'all-in-one-woo-menu'; $function = array($this, 'all_in_one_woo_menu'); $icon_url = 'dashicons-media-code'; $position = 59; add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position); } function all_in_one_woo_menu(){?> <div class="wrap"> <h1><?php _e('All In One Woo', 'all_in_one_woo'); ?></h1> </div> <?php } }// end class }// end if if (class_exists("AllInOneWoo")){ $all_in_one_woo = new AllInOneWoo(); }
if (!class_exists("AllInOneWoo")){ class AllInOneWoo { function __construct(){ add_action('admin_menu', array($this, 'all_in_one_woo') ); } function all_in_one_woo(){ $page_title = 'All In One Woo'; $menu_title = 'All In One Woo'; $capability = 'manage_options'; $menu_slug = 'all-in-one-woo-menu'; $function = array($this, 'all_in_one_woo_menu'); $icon_url = 'dashicons-media-code'; $position = 59; add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position); } function all_in_one_woo_menu(){?> <div class="wrap"> <h1><?php _e('All In One Woo', 'all_in_one_woo'); ?></h1> </div> <?php } }// end class }// end if if (class_exists("AllInOneWoo")){ $all_in_one_woo = new AllInOneWoo(); }
-
Bitte ** [bearbeiten] Sie Ihre Antwort ** undfügen Sieeine Erklärung hinzu: ** Warum ** könnte das das Problem lösen?Please **[edit] your answer**, and add an explanation: **why** could that solve the problem?
- 0
- 2018-03-04
- fuxia
-
-
- 2012-04-05
Im Allgemeinen würden Sieeinem Hooknichteine ganze Klasse hinzufügen.Die Hooks
add_action()
/add_filter()
erwarten Rückruffunktionen ,auf die von innerhalb von verwiesen werden kanneine Klasse .Nehmen wir an,Sie habeneine
init()
-Funktionin Ihrer Klasse,die Siein den WordPress-Codeinit
einbindenmöchten.Setzen Sie Ihren
add_action()
-Aufruf in Ihre Klasseein undidentifizieren Sie den Rückruf wiefolgt:add_action( 'init', array( $this, 'init' ) );
(Hinweis: Ichgehe davon aus,dass Ihre Klasseeinen korrekten Namespace hat. Andernfallsmüssen Sie Ihre Rückruffunktionenmit einem Namespace versehen.)
Generally speaking, you wouldn't add an entire class to a hook. The
add_action()
/add_filter()
hooks expect callback functions, which can be referenced from within a class.Let's say that you have an
init()
function inside your class, that you want to hook into the WordPressinit
hook.Put your
add_action()
call inside your class, and then identify the callback like so:add_action( 'init', array( $this, 'init' ) );
(Note: I'm assuming your class is properly namespaced; otherwise, be sure to namespace your callback functions.)
-
Wasist,wenn die aktuelle Klassenochnichtinitiiert wurde?Ich habe versucht,add_action zu verwenden,umtatsächlich zuinitiieren,dahermussichnicht $ var=new MyClass () hinzufügen.vorher woanders.What about if the current class hasn't already been initiated? I was trying to use add_action to actually initiate, so I don't have to add $var = new MyClass(); beforehand elsewhere.
- 0
- 2012-04-05
- Matthew Ruddy
-
Können Sienichteinfacheinen Rückruf schreiben,um Ihre Klassebei "init" zuinstanziieren (oder woimmer Sieihnbrauchen)?Can you not just write a callback to instantiate your class at `init` (or wherever you need it)?
- 0
- 2012-04-05
- Chip Bennett
-
- 2012-04-05
Sie sollten diestun können,indem Sie den Klassennamen anstelle desinstanziierten Objekts übergeben:
add_action( 'init', array( 'MyClass', '__construct' ) );
(Theoretisch sollte Ihre andere Lösung auchfunktionieren
$var = new MyClass(); add_action( 'admin_init', array( $var, '__construct' ) );
Ichbin mirnicht sicher,warum dasnicht soist.Vielleicht,wenn Sienichtper Referenz anrufen?)
You should be able to do it by passing the class name instead of the instantiated object:
add_action( 'init', array( 'MyClass', '__construct' ) );
(In theory, your other solution should work too
$var = new MyClass(); add_action( 'admin_init', array( $var, '__construct' ) );
Not sure off the head why it doesn't. Maybe if you don't call by reference?)
-
Zuerstfunktioniertmannicht.Lässt die Seiteeinfach leer werden.Die zweitefunktioniert,abernur,weil die Klassein derersten Zeileinitiiert wurde.Der Zweck des Hinzufügens der Aktion wird dadurch zunichtegemacht,da die Klassebereitsinitiiert wurde.Aberesmachtnicht das,wasich versuche,nämlich die Klasse durch die Aktion zuinitiieren.Imeigentlichen Code,an demich arbeite,ist die Aktionnicht 'admin_init',sonderneine benutzerdefinierte Aktioninnerhalbeiner anderen Klasse.Ichmöchtenicht,dass die Funktion 'MyClass'initiiert wird,wenn die Aktionin der anderen Klassenicht vorhandenist.Entschuldigung,wennmiretwasfehlt;lernen wieichgeheFirst one doesn't work. Just makes the page go blank. The second works, but only because the class has been initiated in the first line. It sort of defeats the purpose of adding the action, because the class has already been initiated. But it doesn't do what I'm trying to do, which is initiate the class through the action. In the actual code I'm working on, the action isn't 'admin_init' but a custom action within another class. I don't want the function 'MyClass' to be initiated if the action in the other class isn't there. Sorry if I'm missing something; learning as I go
- 0
- 2012-04-05
- Matthew Ruddy
-
Ja,ich habemichgeirrt.Dasfunktioniertnur,wenn Sieeine statische `init` -Methode aufrufen.Siehe http://wordpress.stackexchange.com/a/48093/14052Yeah, I was wrong. That only works if you're calling a static `init` method. See http://wordpress.stackexchange.com/a/48093/14052
- 0
- 2012-04-05
- Boone Gorges
-
- 2014-12-22
Sie können Ereignissein Ihrer Klasse auslösen,ohne sie zunächst laden zumüssen.Diesistpraktisch,wenn Sienicht diegesamte Klasseim Voraus ladenmöchten,sondern auf die WordPress-Filter und -Aktionen zugreifenmüssen.
Hieristein sehreinfaches Beispiel
<?php class MyClass { public static function init() { add_filter( 'the_content', array('MyClass', 'myMethod') ); } public static function myMethod($content) { $content = $content . 'Working without loading the object'; } } MyClass::init();
Diesisteine sehr vereinfachte Version von Kaisers Antwort,zeigt aberin einfachen Worten das Verhalten.Könntefür diejenigennützlich sein,die sich diesen Stil zumersten Mal ansehen.
Andere Methoden können das Objektbei Bedarf weiterhininitiieren.Ichpersönlich verwende diese Methode,um optionalen Teilenmeines Plugins das Einreihen von Skripten zuermöglichen,aber das Objektnurbei einer AJAX-Anforderung auszulösen.
You can trigger events in your class without the need to load it initially. This is handy if you don't want to load the full class up front, but need to access the WordPress filters and actions.
Here's a very simple example
<?php class MyClass { public static function init() { add_filter( 'the_content', array('MyClass', 'myMethod') ); } public static function myMethod($content) { $content = $content . 'Working without loading the object'; } } MyClass::init();
This is a very simplified version of Kaiser's answer but shows in simple terms the behaviour. Might be handy for those looking at this style for the first time.
Other methods can still initiate the object if required. I'm personally using this method to allow optional parts of my plugin to enqueue scripts, but only triggering the object on an AJAX request.
Istesmöglich,in 'add_action' aufeine Klasse anstelleeiner Funktion zu verweisen?Ich kannesnicht herausfinden.Hieristnurein grundlegendes Beispielfür diebetreffende Funktion.
Alsoja,dasfunktioniertnicht.Ich habe auch versucht:
Und:
Und auch:
Kannich dastrotzdemtun,ohneeine separate Funktionerstellen zumüssen,die die Klasse lädt?Ichmöchtein der Lage sein,den Klassenkonstruktoreinfach über die add_action auszuführen.Dasist alles,wasgeladen werdenmuss,um den Ballins Rollen zubringen.