Aktualisieren Sie ein Plugin unter Beibehaltung der Back-Kompatibilität: general
-
-
Da Sieeinen Beitrag über das Instanziieren ohne Globalerwähnt haben,finden Sie hiereinen solchen Beitragmit Links zumehreren anderen verwandten Beiträgen: http://hardcorewp.com/2013/using-singleton-classes-for-wordpress-plugins/Since you mentioned a post about instantiating without a global here's such a post about with links to several other related posts: http://hardcorewp.com/2013/using-singleton-classes-for-wordpress-plugins/
- 0
- 2013-04-11
- MikeSchinkel
-
1 Antworten
- Stimmen
-
- 2013-03-02
Klassennamen unterscheidenin PHPnicht zwischen Groß- und Kleinschreibung (mit einer Ausnahme ),damit das kein Problemist.
Der Zugriff auf Ihre Haupt-Plugin-Instanzfüreine Klasseistmit einer statischen Methodemöglich.
get_instance()
( Beispiel ). Siemüssen dafür keinen Singletonbauen. Undes solltenicht die Abwärtskompatibilitätbeeinträchtigen.Wenn Siein Ihrem alten Code öffentliche Methoden hatten und diese Methoden von Code von Drittanbietern verwendet wurden,müssen Sie diegenaue Signaturbehalten. Behalten Sie alsoentweder die Methodebei und leiten Sie den Aufruf an die Instanz derneuen Klasse weiter,oder verwenden Sie - wennes viele solcher Methodengibt -
__call()
,um alle diese Methodenin einer zuerfassen.(Update) Anhand Ihres Beispielsfür
remove_action()
…ist dies schwierig. Wenn Sie diesen Rückrufjetzt voneiner anderen Klasse hinzufügen,gibt es keine sichere Möglichkeit,abwärtskompatibel zubleiben,da Sieremove_action()
-Aufrufenicht „beobachten" können.
Sie können den alten Rückruf registrieren undeinen Observer implementieren,derbemerkt wird,wennerentfernt wurde .Eine Idee,mit derichfür zukünftige Projektegespielt habe: Trenne die öffentliche API von derinneren Logik.
Beispiel: Erstellen Sieeine Klasse
Plugin_API
und übergeben Sie alle Objekte aus Ihrem Working -Code an diese Klasse,wenn sieeingerichtet werden. Wenneine Methode von dieser API aufgerufen wird,übergeben Sie diesen Aufruf an das verantwortliche Objekt intern ,ohne Ihre Plugin-Struktur der Öffentlichkeit zugänglich zumachen.Beispielcode
add_action( 'wp_loaded', array ( Plugin_Controller::get_instance(), 'plugin_setup' ) ); class Plugin_Controller { protected static $instance = NULL; public static function get_instance() { NULL === self::$instance and self::$instance = new self; return self::$instance; } public function plugin_setup() { $api = Plugin_API::get_instance(); $api->add_object( 'post_type', new Plugin_Custom_Post_Type ); $api->add_object( 'taxonomy', new Plugin_Custom_Taxonomy ); $api->add_object( 'options_page', new Plugin_Options_Page ); add_action( 'wp_head', array ( $api, 'wp_head' ) ); } } class Plugin_Custom_Post_Type {} class Plugin_Custom_Taxonomy {} class Plugin_Options_Page {} class Plugin_API { protected static $instance = NULL; protected $objects; public static function get_instance() { NULL === self::$instance and self::$instance = new self; return self::$instance; } public function add_object( $name, $object ) { $this->objects[ $name ] = $object; } public function wp_head() { $this->objects['post_type']->wp_head_callback(); $this->objects['taxonomy']->wp_head_callback(); } }
Jetzt kannein anderes Plugin diese Aktionmit ...
entfernenremove_action( 'wp_head', array ( Plugin_API::get_instance(), 'wp_head' ) );
… und Sie können Ihre Plugin-Strukturjederzeit ändern.
Diesistnureine Idee,ich habe sienicht verwendet. Aberes könnteeinen Versuch wert seinfürein komplexes Pluginmit vielen Klassen. Ichbin mirnicht sicher,wieesmit Filternfunktionieren wird,aber diese sindtrotzdemeinfacher zu verschieben.
Das Aktualisiereneiner unbekannten Anzahl von Post-Meta-Feldern kannteuer sein. Ich würde dasnicht anfassen.
Class names are case insensitive in PHP (with one exception), so that should not be a problem.
Accessing your main plugin instance for a class is possible with a static method
get_instance()
(example). You don’t have to build a Singleton for that. And it should not break backwards-compatibility.If you had public methods in your old code and these methods have been used by third party code, you have to keep the exact signature. So either keep the method and pass the call through to the instance of the new class, or – if there are many such methods – use
__call()
to catch all these methods in one.(Update) Given your example of
remove_action()
… this is tricky. If you add this callback from another class now, there is no safe way to stay backwards compatible, because you cannot “watch”remove_action()
calls.
You could register the old callback and implement an Observer to be noticed if it has been removed.One idea I have been playing with for future projects: separate the public API from the inner logic.
Example: Create a class
Plugin_API
and pass all objects from your working code into that class when they are set up. When a method from that API is called, pass that call to the responsible object internally, without exposing your plugin structure to the public.Sample code
add_action( 'wp_loaded', array ( Plugin_Controller::get_instance(), 'plugin_setup' ) ); class Plugin_Controller { protected static $instance = NULL; public static function get_instance() { NULL === self::$instance and self::$instance = new self; return self::$instance; } public function plugin_setup() { $api = Plugin_API::get_instance(); $api->add_object( 'post_type', new Plugin_Custom_Post_Type ); $api->add_object( 'taxonomy', new Plugin_Custom_Taxonomy ); $api->add_object( 'options_page', new Plugin_Options_Page ); add_action( 'wp_head', array ( $api, 'wp_head' ) ); } } class Plugin_Custom_Post_Type {} class Plugin_Custom_Taxonomy {} class Plugin_Options_Page {} class Plugin_API { protected static $instance = NULL; protected $objects; public static function get_instance() { NULL === self::$instance and self::$instance = new self; return self::$instance; } public function add_object( $name, $object ) { $this->objects[ $name ] = $object; } public function wp_head() { $this->objects['post_type']->wp_head_callback(); $this->objects['taxonomy']->wp_head_callback(); } }
Now another plugin can remove that action with …
remove_action( 'wp_head', array ( Plugin_API::get_instance(), 'wp_head' ) );
… and you are still free to change your plugin structure whenever you want.
This is just an idea, I haven’t used it. But it could be worth a try for a complex plugin with lots of classes. Not sure how it will work with filters, but these are easier to move anyway.
Updating an unknown number of post meta fields can be expensive. I would not touch that.
-
Ich hattegehofft,Sie könnten darauf antworten!Vielen Dank!Könnteich Siebeunruhigen,sich den Beispielcodeeines Drittanbieters anzusehen,denich hinzugefügt habe?Könnteich Ihre Demo-Klassenstrukturtrotzdemimplementieren und/oder `some_templates ()`in eine separate Klasse verschieben,ohne dies zubeschädigen?Was hoping you might respond to this! Thanks! Could I trouble you to take a look at the example third-party code I've added? Could I still implement your demo class structure, and/or move `some_templates()` to a separate class without breaking that?
- 0
- 2013-03-03
- helgatheviking
-
@helgatheviking Siehemein Update.@helgatheviking See my update.
- 0
- 2013-03-03
- fuxia
-
Vielen Dank!Ich weißnicht,obiches wegen der Rückkompatibilitätmit diesem speziellen Pluginimplementieren kann,aber das wirdfür dasnächste sehrpraktisch sein!Thanks so much! I don't know if I'll be able to implement it with this particular plugin because of all the back-compatibility, but this will be super handy for the next one!
- 0
- 2013-03-03
- helgatheviking
Wie kannich Updates zueinem meiner öffentlichen Pluginsmachen,ohne das Pluginfür alle vorhandenen Benutzer zubeschädigen?
Erstens möchteich die Klasse/den Namespace des Haupt-Plugins ändern,daichmöchte,dasses anderen Klassenim Plugin ähnelt,daseserweitert.
Alsomöchteich
ändernbis
Zweitens wird diegesamte Klasseinstanziiert undin einerglobalen Variablengespeichert.
Irgendwo hier habeichein gutes Beispiel dafürgesehen,wiemaneine Klasse ohne Globalinstanziiert (kann siejetztnatürlichnichtfinden,#doh). Das Global kann von Benutzern verwendet werden,umeinige Vorlagen hinzuzufügen/zuentfernen. Gibteseine Möglichkeit,das Globale loszuwerden,ohne die Themen der Personen,dieesmöglicherweise zur Manipulation der Vorlagen verwenden,vollständig zu zerstören?
Drittens ,im Zusammenhangmit dem obengenannten,istmeine Haupt-Plugin-Datei sehrgroßgeworden,undichmöchte sie aus Gründenmeinereigenen Gesundheitin Teile aufteilen. Wenn sich die Methode
some_templates()
in dersome_class()
befindet,istesjedochmöglich,siein diefront_end_class()
zu verschieben,ohne die Dinge zubeschädigen Benutzer?Zum Beispiel
Zum Aushakeneiner Aktionin meinem Plugin
Kann die Klassenstruktur und dasglobale Variablen-Setup angepasst werden,ohne dies zubeschädigen? Wie kannich Menschen darauf aufmerksammachen,dass sich diesgeändert hat?
_doing_it_wrong()
?Schließlich habeicheinige Post-Meta als "Ja" oder "Nein" anstelleeines Booleschen Wertsgespeichert. Istes sinnvoll,dies zu ändern?