Der beste Weg, um eine Klasse in einem WP-Plugin zu initiieren?
-
-
In Bezug auf die letzte Bearbeitung wirdesetwasnutzlos,wennesin derselben Plugin-Datei wie die Klasseenthaltenist.Sie können die Klasse auchgemäß der vonmirbeschriebenen Methodeinstanziieren.Auch wennesin einer separaten Dateiist,istesimmernochetwas sinnlos.Ich kannnur sehen,ob Sieeine Wrapper-Funktionerstellenmöchten,mit der Sieeine Klasse außerhalb Ihrer Plugin-Dateien,innerhalb von Designs usw.instanziieren können.Trotzdemmüssteichmichfragen,welche Logik dahinter steckt,da die ordnungsgemäße Verwendung von Bedingungen und Hookseine Feinsteuerung der Instanziierungermöglichen sollte,sodass Sie sich stattdessen auf die Verwendung des Plugins konzentrieren können.Regarding last edit, if that's contained in the same plugin file as the class, it becomes somewhat useless. You may as well instantiate the class as per the method I describe. Even if its in a separate file, its still somewhat pointless. Only use case I can see is if you want to create a wrapper function that enables you to instantiate a class outside of your plugin files, within themes and so on. Even so, I'd have to ask what logic lay behind that because proper use of conditionals and hooks should allow fine grain control over instantiation allowing you to focus on using the plugin instead.
- 1
- 2012-10-23
- Adam
-
Ich stimme demirgendwie zu,aberich dachte,es lohnt sich,eseinzufügen,daichesin einpaar WP-Pluginsgefunden habe.I kinda agree with this, but I thought it worth putting in as I found it in a couple of WP plugins.
- 0
- 2012-10-24
- kalpaitch
-
4 Antworten
- Stimmen
-
- 2012-10-22
Gute Frage,esgibt eine Reihe von Ansätzen undes hängt davon ab,was Sieerreichenmöchten.
macheich oft;
add_action( 'plugins_loaded', array( 'someClassy', 'init' )); class someClassy { public static function init() { $class = __CLASS__; new $class; } public function __construct() { //construct what you see fit here... } //etc... }
Ein ausführlicheres Beispiel,das sich auseinigen jüngsten Diskussionen zu diesem Themaim Chatraumergibt,finden Sie unter "noreferrer"> dieses Wesentliche von WPSE-Mitglied toscho .
Der Ansatzfür leere Konstruktoren.
Hieristein Auszug der Vor- und Nachteile aus dem obigen Kern,der den leeren Konstruktoransatz vollständig veranschaulicht.
-
Vorteile:
-
Unit-Tests könnenneue Instanzenerstellen,ohne Hooks zu aktivieren automatisch. Kein Singleton.
-
Keineglobale Variableerforderlich.
-
Wermit der Plugin-Instanz arbeitenmöchte,kanneinfach anrufen T5_Plugin_Class_Demo ::get_instance ().
-
Einfach zu deaktivieren.
-
Immernochechtes OOP: Keine Arbeitsmethoden sind statisch.
-
Nachteil:
- Vielleicht schwerer zu lesen?
Der Nachteilistmeiner Meinungnachein schwacher,weshalbesmein bevorzugter Ansatz seinmüsste,jedochnicht dereinzige,denich verwende. Tatsächlich werden sich zweifelloseinige andere Schwergewichtein Kürzemit diesem Themabefassen,daeseinige gute Meinungen zu diesem Themagibt,diegeäußert werden sollten.
Hinweis: Ichmuss das Hauptbeispiel von toscho finden,das 3 oder 4 durchlaufen hat Vergleiche,wieeine Klasseinnerhalbeines Pluginsinstanziiert werden kann,wobei die Vor- und Nachteile dereinzelnen Klassen untersucht wurden. Der obige Link war derbevorzugte Weg,dies zutun. Die anderen Beispielebieten jedocheinen guten Kontrast zu diesem Thema. Hoffentlich hat toscho dasnochin der Datei.Hinweis: Die WPSE Antwort auf dieses Themamit relevanten Beispielen und Vergleichen. Auch diebeste Lösung zum Beispieleine Klassein WordPress.
add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) ); class My_Plugin { private $var = 'foo'; protected static $instance = NULL; public static function get_instance() { // create an object NULL === self::$instance and self::$instance = new self; return self::$instance; // return the object } public function foo() { return $this->var; // never echo or print in a shortcode! } }
Good question, there are a number of approaches and it depends on what you want to achieve.
I often do;
add_action( 'plugins_loaded', array( 'someClassy', 'init' )); class someClassy { public static function init() { $class = __CLASS__; new $class; } public function __construct() { //construct what you see fit here... } //etc... }
A more thorough an indepth example which came about as a result of some recent discussions on this very topic within the chat room can be seen in this gist by WPSE member toscho.
The empty constructor approach.
Here is an excerpt of advantages/disadvantages taken from the above gist which exemplifies the empty constructor approach in full.
Advantages:
Unit tests can create new instances without activating any hooks automatically. No Singleton.
No global variable needed.
Whoever wants to work with the plugin instance can just call T5_Plugin_Class_Demo::get_instance().
Easy to deactivate.
Still real OOP: no working methods are static.
Disadvantage:
- Maybe harder to read?
The disadvantage in my opinion is a weak one at that which is why it would have to be my favored approach, however not the only one I use. In fact several other heavy weights will no doubt chime in on this topic with their take on the subject shortly because there are some good opinions surrounding this topic that should be voiced.
note: I need to find the gist example from toscho that ran through 3 or 4 comparisons of how to instantiate a class within a plugin that looked at the pros and cons of each, which the above link was the favored way to do it, but the other examples provide a good contrast to this topic. Hopefully toscho still has that on file.Note: The WPSE Answer to this topic with relevant examples and comparisons. Also the best solution for instance a class in WordPress.
add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) ); class My_Plugin { private $var = 'foo'; protected static $instance = NULL; public static function get_instance() { // create an object NULL === self::$instance and self::$instance = new self; return self::$instance; // return the object } public function foo() { return $this->var; // never echo or print in a shortcode! } }
-
Was wäre der Unterschied zwischen add_action ('plugins_loaded',...);und add_action ('load-plugins.php',...);In dem Beispiel,dasichgenommen habe,wurde letzteres verwendetwhat would be the difference between add_action('plugins_loaded',...); and add_action('load-plugins.php',...); The example I took used the latter
- 0
- 2012-10-22
- kalpaitch
-
Ichbin mirnicht sicher,aber angesichts der Namen würdeich sagen,dass der Hook "plugins_loaded"eine Warteschlangeist,die ausgeführt wird,nachdem die Pluginsgeladen wurden,wobei der Hook "load-plugins.php" dieeigentliche Warteschlange zum Laden von Pluginseinbinden würde.Praktischmachtes keinengroßen Unterschied,abertheoretisch kannes zu Problemen kommen,wenn Sie Methoden aufrufen,wennnicht alle Pluginsgeladen sind.Deshalb würdeich "plugins_loaded"bevorzugen.Wiederinterpretiereichnurihre Namen.I'm not sure, but considering the names I would say that the `plugins_loaded` hook is a queue that is run after the plugins are loaded where as the `load-plugins.php` hook would hook the actual plugin loading queue. Practically it doesn't make much of a difference, but theoretically it could cause issues if you are calling methods when not all plugins are loaded. That's why I would prefer `plugins_loaded`. Again, I am just interpreting their names.
- 0
- 2012-10-22
- Tim S.
-
Soweitich weiß,ist load-plugins.php,obwohlesfunktioniert,mit der Kerndatei `update.php` verknüpft undnicht Teil der üblichen Standardaktionen,auf dieman sich verlassen sollte,wennes um die Abfolge von Ereignissengeht,die während der Initialisierung und ausgelöst werdenAus diesem Grundbevorzugeich die zutreffenden Hooks,in diesem Fall `plugins_loaded`.Diesist das,wasich oft als kurze Momentaufnahme dessenbezeichne,waspassiert,wenn [Aktionsreferenz] (http://codex.wordpress.org/Plugin_API/Action_Reference).Meine Erklärungistnicht vollständig.From what I understand load-plugins.php, although it works, is associated with the core `update.php` file and is not part of the usual default actions that should be relied upon when concerning the sequence of events that fire during initialization and for that reason I prefer to use those hooks that do apply, in this case `plugins_loaded`. This is what I often refer to as a quick snapshot of what happens when [Action Reference](http://codex.wordpress.org/Plugin_API/Action_Reference). My explanation is not complete in its entirety.
- 1
- 2012-10-22
- Adam
-
Sie suchennach [dieser Antwort] (http://wordpress.stackexchange.com/questions/61437/php-error-with-shortcode-handler-from-a-class/61440#61440)?You are looking for [this answer](http://wordpress.stackexchange.com/questions/61437/php-error-with-shortcode-handler-from-a-class/61440#61440)?
- 0
- 2012-10-22
- fuxia
-
@toscho Ja,das war's.Icherinneremich,dass wir uns dasim Chat angesehen haben,aber auchin Formeines Gists.Abereinsim selben.Dank dafür!@toscho Yep, that's it. I remember we were looking at that in chat but in the form of a Gist also. But one in the same. Thanks for that!
- 0
- 2012-10-22
- Adam
-
Sehr hilfreich,und der add_shortcode () scheinteine vieleinfachere Möglichkeit zu sein,die Ausgabeeinesbestimmten Teils dieser Klasseeinzuschließen,alseine Instanzper say abzurufen.Istesmöglich,einen Shortcode sowohlin den Vorlagendateien als auchim WordPress-Editor zu verwenden?Very helpful, and the add_shortcode() seems to be a much simpler way to include the output of a particular part of that class, rather than fetching an instance per say. Is it possible to use a shortcode in the template files as well as in the WordPress Editor?
- 0
- 2012-10-22
- kalpaitch
-
@kalpaitch Wennein Shotcode zu Ihrem Anwendungsfallpasst,dannja,`echo do_shortcode ('[mein-Shortcode]');`in seinergrundlegendsten Form,wenn Sieeinen Shortcode außerhalb des herkömmlichen Post-Editor-Bildschirms aufrufenmöchten,wird dies ausgeführtTrick.@kalpaitch If a shotcode fits your use case, then yes, `echo do_shortcode('[my-shortcode]');` in its most basic form, for when wanting to call a shortcode outside of the traditional post editor screen will do the trick.
- 0
- 2012-10-22
- Adam
-
Ichmag diesen singletonartigen Ansatz.Ichfragemichjedoch,ob Sieplugins_loaded als Initialisierungs-Aktions-Hook verwenden.Dieser Hook soll ausgeführt werden,nachdem alle Pluginsgeladen wurden.Wenn Sie sich danacheinbinden,entführen Sie diesen Hook und können sich über Konflikte oder Problememit der Startsequenzmit anderen Plugins oder Themes lustigmachen,die sichin plugins_loadedeinbinden.Ich würde keine Aktion ausführen,um Ihre Initialisierungsmethode auszuführen.Die Plugin-Architektur wurde so konzipiert,dass sieinline undnichtfüreine Aktion ausgeführt wird.I like this singleton-like approach. However, I question using plugins_loaded as your initializing action hook. This hook is meant to be run __after__ all plugins have loaded. By hooking in after it, you are kind of hijacking that hook, and may fun into conflicts or startup-sequence issues with other plugins or themes that hook into plugins_loaded. I wouldn't hook into any action to run your initialization method. The plugin architecture was designed to run inline, not on an action.
- 4
- 2012-10-23
- Tom Auger
-
Ichbin diemeiste Zeitmit "init" verbunden,aberich verstehe Ihren Standpunktmit "plugins_loaded",was absolut sinnvollist.Esist auch sinnvoll,wenn Siebeabsichtigten,diesen Haken zu diesem Zweck zuentführen.Ich sehe die Verwendung von Hooksfür Pluginsnicht so wie Sie,aberich würdegernemehr über Ihre Position zu diesem Themaerfahren,wenn Sieeine empfohlene Lektüre haben.Links?Weitere Beispielefür welche Arten von Sequenzproblemen können auftreten?Danke Kumpel ..I hook onto `init` the majority of the time, but I get your point with `plugins_loaded`, makes perfect sense. It also makes sense if your intention was to hijack that hook for that purpose. I don't view using hooks the same way for plugins as you do but I'd be interested to learn more about your position on the topic if you have some recommended reading? Links? Further examples of what kinds of sequence issues we might encounter? Thanks mate..
- 0
- 2012-10-23
- Adam
-
@ Tom Auger,ich verstehe Ihren Standpunkt zum Ladenmit dem Hookplugins_loaded vollständig.Wäreesbesser,dieerste Methodein der Frage zum Initiiereneiner Klasse zu verwenden,oder wenn Sieeine alternative Methode vorschlagen,könnten Sie diesbitte ineine Antwort aufnehmen?@Tom Auger, I completely see your point about loading using the hook plugins_loaded. Would it be better to use the first method in the question for initiating a class, or if you propose an alternative method, could you please include in an answer?
- 0
- 2012-10-24
- kalpaitch
-
Wenn Sie [`register_activation_hook ()`] (http://codex.wordpress.org/Function_Reference/register_activation_hook) verwenden,müssen Sie diese Funktion aufrufen,bevor die Aktion `plugins_loaded` ausgelöst wurde.Note that if you use [`register_activation_hook()`](http://codex.wordpress.org/Function_Reference/register_activation_hook) you need to call that function before the `plugins_loaded` action has been triggered.
- 2
- 2012-10-31
- Geert
-
@Geert,stimmte zu,ichfand,dass diese Aktivierungs-Hooksnochin __constructgehenmussten@Geert, agreed, I found that these activation hooks still had to go in __contruct
- 0
- 2012-11-02
- kalpaitch
-
Weitere Informationenfinden Siein diesem Beitrag von @mikeschinkel undim Dicussin den Kommentaren.http://hardcorewp.com/2012/using-classes-as-code-wrappers-for-wordpress-plugins/#comment-149As additional information, see this post from @mikeschinkel and the dicuss in the comments. http://hardcorewp.com/2012/using-classes-as-code-wrappers-for-wordpress-plugins/#comment-149
- 1
- 2013-01-03
- bueltge
-
@bueltge Dankefür den Link,soll lesen.Siehtnacheinerguten Diskussion aus!@bueltge Thanks for the link, shall read. Looks like a good discussion!
- 0
- 2013-01-03
- Adam
-
- 2012-10-22
Ich verwendefolgende Struktur:
Prefix_Example_Plugin::on_load(); /** * Example of initial class-based plugin load. */ class Prefix_Example_Plugin { /** * Hooks init (nothing else) and calls things that need to run right away. */ static function on_load() { // if needed kill switch goes here (if disable constant defined then return) add_action( 'init', array( __CLASS__, 'init' ) ); } /** * Further hooks setup, loading files, etc. * * Note that for hooked methods name equals hook (when possible). */ static function init( ) { } }
Hinweise:
- hat Platzfür Dinge definiert,die sofort ausgeführt werdenmüssen
- Das Deaktivieren/Überschreibenfür Optimierungenisteinfach (eine
init
-Methode aushängen) - Ichglaubenicht,dassichjemalsein Objekt der Plugin-Klasse verwendet/gebraucht habe -eserfordert,den Überblick zubehalten usw.; Diesist wirklichein gefälschter Namespace,nicht OOP (meistens)
Haftungsausschluss Ich verwendenoch keine Komponententests ( so viele Dinge aufmyplate ) und höre,dass statische Aufladungfür sie weniger vorzuziehenist. Machen Sie Ihre Recherchen dazu,wenn Sieeseinem Unit-Test unterziehenmüssen.
I use following structure:
Prefix_Example_Plugin::on_load(); /** * Example of initial class-based plugin load. */ class Prefix_Example_Plugin { /** * Hooks init (nothing else) and calls things that need to run right away. */ static function on_load() { // if needed kill switch goes here (if disable constant defined then return) add_action( 'init', array( __CLASS__, 'init' ) ); } /** * Further hooks setup, loading files, etc. * * Note that for hooked methods name equals hook (when possible). */ static function init( ) { } }
Notes:
- has defined place for things that need to run right away
- disable/override for tweaks is easy (unhook one
init
method) - I don't think I ever used/needed object of plugin class - requires keeping track of it, etc; this is really fake namespacing by purpose, not OOP (most of the time)
Disclaimer I don't use unit tests yet (so many things on myplate) and I hear that static can be less preferable for them. Do your research on this if you need to unit test it.
-
Ich weiß,dass Leute,die sichmit Unit-Testsbeschäftigen,statische/Singleton-Lösungen wirklichnichtmögen.Ich denke,wenn Sie vollständig verstehen,was Siemit statischer Aufladungerreichen wollen,und sich zumindest der Auswirkungenbewusst sind,istes vollkommenin Ordnung,solche Methoden zuimplementieren.Gute Themen dazubei [SO]I know people big on unit testing really don't like static / singleton solutions. I think if you fully understand what you are attempting to achieve by using static and are at least aware of the ramifications of doing so then its perfectly fine to implement such methods. Good topics surrounding this over at [SO]
- 3
- 2012-10-22
- Adam
-
Das hatmich wirklich zum Nachdenkengebracht.Warum alsoeine Klasse verwenden undnichteinfach zueinfachen Präfixfunktionen zurückkehren?Tun wir diesnur,um sauberere Funktions-/Methodennamen zu haben?Ichmeine,siemit einem "statischen"b4 verschachtelt zu haben,istes so vielbesser lesbar?Die Wahrscheinlichkeiteines Namenskonfliktsist ungefährgleich wiebei einemeinzelnen Klassennamen,wenn Sie korrekte Präfixe verwenden oderfehltmiretwas?This made me really think. So why use a Classes then and not just go back to simple prefixed functions. Do we do this just to have cleaner function/method names? I mean having them nested with a "static" b4 them is it that much more readable? The chance of having a name conflict is about the same as for a single class name if you use propper prefixes or am I missing something?
- 0
- 2013-05-28
- James Mitch
-
@JamesMitch Ja,all-statische Methoden sindmeistnur Funktionenmit gefälschtem Namespace,wie siein WP verwendet werden.Klassen habenjedoch auchin diesem Falleinige Vorteilegegenüber reinen Funktionen,wie z. B. Autoload und Vererbung.In letzter Zeitbin ich von statischen Methoden zu realinstanziierten Objekten übergegangen,die durch Abhängigkeitsinjektionscontainer organisiert sind.@JamesMitch yes, all-static methods is mostly just functions with fake namespace as used in WP. However classes do have some advantages over pure functions even in this case, such as autoload and inheritance. Lately I have been moving from static methods and towards real instantiated objects organized by dependency injection container.
- 1
- 2013-05-28
- Rarst
-
- 2012-10-22
Alles hängt von der Funktionalität ab.
Ich habeeinmalein Pluginerstellt,das Skripte registriert,als der Konstruktor aufgerufen wurde,alsomussteiches am Hook
wp_enqueue_scripts
einbinden.Wenn Sieesbeim Laden Ihrer Datei
functions.php
aufrufenmöchten,können Sie auch selbsteine Instanzerstellen.$class_instance = new ClassName();
wie Sieerwähnt.Möglicherweisemöchten Sie die Geschwindigkeit und die Speichernutzungberücksichtigen.Mir sind keinebekannt,aberich kannmir vorstellen,dassesin einigen Fällen unaufgeforderte Hakengibt.Wenn Sie Ihre Instanz an diesem Hookerstellen,können Siemöglicherweiseeinige Serverressourcen sparen.
It all depends on functionality.
I once made a plugin that registered scripts when the constructor was called so I had to hook it at the
wp_enqueue_scripts
hook.If you want to call it when your
functions.php
file is loaded, you might as well create an instance yourself$class_instance = new ClassName();
as you mentioned.You might want to consider speed and memory usage. I'm not aware of any, but I can imagine there are uncalled hooks in some cases. By creating your instance at that hook you might save some server resources.
-
Cool,danke dafür,ichnehme an,esgibt auch zwei Punkte zu der obigen Frage.Die andereist,ob __constructgeeignet ist oder obinit ()eine bessere Möglichkeitist,die Klasse zuinitialisieren.Cool thanks for that, I suppose there are two points to the above question as well. The other being whether __construct is suitable or whether init() is a better way to initialize the class.
- 0
- 2012-10-22
- kalpaitch
-
Nun,ich würdemichfüreine statische `init ()` -Methodeentscheiden,damit die Klasseninstanzim Klassenbereich anstelleeines anderen Bereichs aufgerufen wird,in dem Siemöglicherweise vorhandene Variablen überschreiben könnten.Well I'd go for an static `init()` method so the class instance is called in the class' scope instead of another scope where you could possibly overwrite existing variables.
- 1
- 2012-10-22
- Tim S.
-
- 2017-09-25
Ich weiß,dass diesein paar Jahre altist,abermittlerweile unterstützt PHP 5.3 anonyme Methoden ,also habeichmir Folgendes ausgedacht:
add_action( 'plugins_loaded', function() { new My_Plugin(); } );
undirgendwiegefälltesmir ambesten.Ich kann reguläre Konstruktoren verwenden undmuss keine "init" - oder "on_load" -Methoden definieren,diemeine OOP-Strukturen durcheinanderbringen.
I know this is a couple years old, but meanwhile php 5.3 supports anonymous methods, so I came up with this:
add_action( 'plugins_loaded', function() { new My_Plugin(); } );
and somehow I like it the most. I can use regular constructors and don't need to define any "init" or "on_load" methods that mess up my OOP structures.
Ich habeein Pluginerstellt undnatürlich wollteich alsicheinen netten OO-Ansatz wählen. Jetzt habeich diese Klasseerstellt und anschließendeine Instanz dieser Klasseerstellt:
Ichgehe davon aus,dasseseine WP-Möglichkeitgibt,diese Klasse zuinitiieren,und dannbin ich auf Leutegestoßen,die sagten,dass sie liebereine
init()
-Funktion alseine__construct()
eins. Undin ähnlicher Weisefandicheinige Leute,diefolgenden Haken verwendeten:Wasistim Allgemeinen derbeste Weg,umeine WP-Klasseninstanzbeim Laden zuerstellen und diese alsglobal zugängliche Variable zu verwenden?
HINWEIS: Alsinteressanter Nebenpunkt habeichfestgestellt,dass
register_activation_hook()
zwar aus dem__construct
heraus aufgerufen werden kann kannim zweiten Beispielnichtinnerhalb voninit()
aufgerufen werden. Vielleicht könntemichjemandin diesem Punkt aufklären.Bearbeiten: Vielen Dankfür alle Antworten. Esgibt eindeutigeinige Debatten darüber,wiemit der Initialisierunginnerhalb der Klasse selbst umgegangen werden soll,aberich denke,dassesim Allgemeineneinen ziemlichguten Konsensgibt,dass
add_action( 'plugins_loaded', ...);
ist derbeste Weg,umestatsächlich zu starten ...Bearbeiten: Nur um die Sache zu verwirren,habeich auchgesehen,dass dies verwendet wird (obwohlich diese Methode selbstnicht verwenden würde,weil das Verwandelneiner schönen OO-Klassein eine Funktion den Sinn zu verlieren scheint ):