Spuštění wiki komunity pro sběrobjektivníosvědčené postupy pro vývoj pluginů. Tato otázka byla inspirována @ EAMann komentáře na wp-hackery .
Záměrem je spolupracovat na tom, jaké objektivní osvědčené postupy by mohly být, abychom je mohli potenciálně využít v procesu hodnocení spolupráce v rámci komunity.
UPDATE: Po shlédnutí prvních několika odpovědí je jasné, že musíme mít pouze jednu myšlenku/návrh/nejlepší praxi na odpověď a lidé by měli seznam zkontrolovat, aby se před odesláním neobjevili žádné duplikáty.
Pokud si myslíte, že by lidé chtěli přidat nebo změnit některá data: poskytnout apply_filters () před návratem .
P.S. Jedna věc, kterou jsem našel trochu zklamáním a že vaše otázky adresy je procento pluginy, které jsou určeny pouze pro koncové uživatele, tj., Které nemají vlastní háčky. Představte si, že WordPress byly navrženy jako většina pluginů? Bylo by to nepružné a velmi úzce specializované řešení.
Možná by se věci lišily, kdyby WordPress měl možnost automaticky instalovat pluginy, na kterých závisely další pluginy? Jak to je, já obvykle musím napsat mnoho funkcí, které potřebuji od nuly, protože klienti chtějí věci určitým způsobem a dostupné pluginy, zatímco 90% tam, nedovolte mi flexibilitu aktualizovat zbývajících 10%.
Opravdu si přeji, aby ti, kteří vedou komunitu WordPress, identifikovali způsob, jak zajistit, aby byly pluginy odměňovány za dodržování nejlepších postupů (například přidávání háčků pro jiné vývojáře), stejně jako dobré odpovědi jsou odměňovány na webu StackExchange.
Vezměme si příklad z další otázky :
Příklad: Chci něco udělat ve svém pluginu, když někdo retweets článek. Pokud tam byl vlastní hák v jakékoliv populární retweet plugin je to, že jsem mohl připojit do a oheň z, to by bylo skvělé. Neexistuje, takže můžu upravit jejich plugin tak, aby to zahrnoval, ale to funguje pouze pro mou kopii, a nechci se snažit tuto distribuci šířit.
wp_enqueue_script
a wp_enqueue_style
Pluginy by neměly načítat/pokoušet se načíst duplicitní verze souborů JS/CSS, zejména jQuery a další JS soubory obsažené v WP Core.
Pluginy by měly vždy používat wp_enqueue_script
a wp_enqueue_style
při propojování JS a CSS souborů a nikdy přímo přes <script>
tagy.
Všechny výstupní řetězce by měly být propojeny s příslušnou textovou doménou, aby umožnily internacionalizaci zainteresovanými stranami, i když developer nemá zájem o překlad vlastního pluginu.
Všimněte si, že je velmi důležité načíst jazykové soubory během akce init
, aby se uživatel mohl zapojit do akce.
Viz Kodex: I18n pro vývojáře WordPress
A také tento článek: Loading WP jazykové soubory správně .
WP 4.6 změnilo pořadí načtení a zkontrolovaná místa, což usnadnilo vývojářům a uživatelům.
S ohledem na plugin s textdomain 'my-plugin', WordPress bude nyní hledat překladový soubor v:
/wp-content/languages/plugins/my-plugin-en_US.mo
Pokud se tam nepodaří najít, bude hledat ten, kde jej plugin prozradí, aby se díval (obvykle ve složce „jazyk“, pokud se řídí kódem):
/wp-content/plugins/my-plugin/languages/my-plugin-en_US.mo
Pokud nebude nalezen žádný jazykový soubor, zkontroluje výchozí umístění:
/wp-content/languages/my-plugin-en_US.mo
První kontrola byla přidána v 4.6 a dává uživatelům definované místo pro přidání jazykového souboru, jako dříve, než by potřebovali vědět, kam vývojář přidal jazykový soubor, nyní uživatel potřebuje znát pouze textovou doménu pluginu:/wp -content/jazyky/pluginy/TEXTDOMAIN-LOCAL.mo
[...]
Na závěr bych rád zdůraznil, že je důležité načíst vlastní soubory uživatelských jazyků z WP_LANG_DIR před načtením jazykových souborů dodávaných s pluginem . Pokud je načteno více mo-souborů pro stejnou doménu, použije se první nalezený překlad. Tímto způsobem budou jazykové soubory poskytované zásuvným modulem sloužit jako nouzové řešení pro řetězce, které uživatel nepřeloží.
public function load_plugin_textdomain()
{
$domain = 'my-plugin';
// The "plugin_locale" filter is also used in load_plugin_textdomain()
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
load_textdomain(
$domain,
WP_LANG_DIR . '/my-plugin/' . $domain . '-' . $locale . '.mo'
);
load_plugin_textdomain(
$domain,
FALSE,
dirname( plugin_basename(__FILE__) ) . '/languages/'
);
}
Vždy otestujte své pluginy s WP_DEBUG
zapnutým a v ideálním případě jej zapněte během celého procesu vývoje. Plugin by neměl házet žádné chyby s WP_DEBUG
. To zahrnuje zastaralé oznámení a nezaškrtnuté indexy.
Chcete-li ladění zapnout, upravte soubor wp-config.php
tak, aby WP_DEBUG
konstanta byla nastavena na true
. Více informací naleznete v Codex on Debug .
Pokud můžete: použít existující funkce obsažené ve WordPress jádru místo psaní vlastního. Vlastní funkce PHP vyvíjejte pouze tehdy, když v jádru WordPressu neexistuje vhodná pre-existující funkce.
Jednou z výhod je, že můžete použít "log deprecated notification" pro snadné sledování funkcí, které mají být nahrazeny. Další výhodou je, že uživatelé si mohou prohlédnout dokumentaci funkce v Kodexu a lépe porozumět tomu, co plugin dělá, i když nejsou zkušeným vývojářem PHP.
plugin, který byl odstraněn z instalace WordPressu, by měl odstranit všechny soubory, složky, položky databáze a tabulky které vytvořil, stejně jako hodnoty option to created.
Pluginy mohou nabídnout možnost exportu/importu nastavení, takže nastavení lze uložit před WordPress před smazáním.
Zásuvný modul should dezinfikuje všechny uživatelské vstupy načtené přímo nebo nepřímo (např. Přes $_POST
nebo $_GET
) před použitím vstupních hodnot k dotazování databáze MySQL.
Viz: Formátování příkazů SQL .
Není důvod psát čistý, objektově orientovaný kód PHP5. Podpora PHP4 bude postupně ukončena po příštím vydání (WP 3.1). Samozřejmě můžete předponovat všechny vaše názvy funkcí, abyste skončili s endlessly_long_function_names_with_lots_of_underscores, ale je mnohem jednodušší napsat jednoduchou třídu a všechno v ní spojit. Také umístěte svou třídu do samostatného souboru a pojmenujte ji odpovídajícím způsobem, abyste ji mohli snadno rozšířit a udržovat:
// in functions.php
require 'inc/class-my-cool-plugin.php';
new MyCoolPlugin();
// in inc/class-my-cool-plugin.php
class MyCoolPlugin {
function __construct() {
// add filter hooks, wp_enqueue_script, etc.
// To assign a method from your class to a WP
// function do something like this
add_action('admin_menu', array($this, "admin"));
}
public function admin() {
// public methods, for use outside of the class
// Note that methods used in other WP functions
// (such as add_action) should be public
}
private function somethingelse() {
// methods you only use inside this class
}
}
Zásuvka by měla správně předponovat VŠECHNY položky globálního jmenného prostoru (konstanty, funkce, třídy, proměnné, dokonce i věci jako vlastní taxonomie, typy příspěvků, widgety atd.). Například nevytvářejte funkci nazvanou init()
; místo toho jej pojmenujte jako jpb_init()
.
Jeho společný název by měl obsahovat předponu se třemi nebo čtyřmi písmeny před jmény nebo použít funkci PHP Jmenný prostor . Porovnání: Jednopísmenová předpona pro PHP třídní konstanty?
Zásuvný modul by neměl smazat všechna data po deaktivaci.
Zahrnujte pouze soubory, které potřebujete ...
Pokud jste na frontě, nezahrnujte kód, který se týká oblasti admin.
Po odinstalaci a plugin should Vyzve uživatele, aby vymazal data a obdržel potvrzení, že uživatel je v pořádku s vymazáním dat, než tak učiní a plugin should také umožní uživateli možnost uchovávat data při odinstalaci. (Tento nápad z @ EAMann.)
Nepoužívejte pouze return;
, pokud byl nějaký vstup uživatele nesprávný. Dodejte jim nějaké informace o tom, že bylo provedeno špatně.
function some_example_fn( $args = array() )
{
// If value was not set, build an error message
if ( ! isset( $args['some_value'] ) )
$error = new WP_Error( 'some_value', sprintf( __( 'You have forgotten to specify the %1$s for your function. %2$s Error triggered inside %3$s on line %4$s.', TEXTDOMAIN ), '$args[\'some_value\']', "\n", __FILE__, __LINE__ ) );
// die & print error message & code - for admins only!
if ( isset( $error ) && is_wp_error( $error ) && current_user_can( 'manage_options' ) )
wp_die( $error->get_error_code(), 'Theme Error: Missing Argument' );
// Elseif no error was triggered continue...
}
Během bootstrapu můžete nastavit globální objekt chyby pro motiv nebo plugin:
function bootstrap_the_theme()
{
global $prefix_error, $prefix_theme_name;
// Take the theme name as error ID:
$theme_data = wp_get_theme();
$prefix_theme_name = $theme_data->Name;
$prefix_error = new WP_Error( $theme_data->Name );
include // whatever, etc...
}
add_action( 'after_setup_theme', 'bootstrap_the_theme' );
Později můžete na požádání přidat neomezené chyby:
function some_theme_fn( $args )
{
global $prefix_error, $prefix_theme_name;
$theme_data = wp_get_theme();
if ( ! $args['whatever'] && current_user_can( 'manage_options' ) ) // some required value not set
$prefix_error->add( $prefix_theme_name, sprintf( 'The function %1$s needs the argument %2$s set.', __FUNCTION__, '$args[\'whatever\']' ) );
// continue function...
}
Pak je můžete načíst na konci tématu. Tímto způsobem nepřerušujete vykreslování stránky a stále můžete vydávat všechny chyby pro vývoj
function dump_theme_errors()
{
global $prefix_error, $prefix_theme_name;
// Not an admin? OR: No error(s)?
if ( ! current_user_can( 'manage_options' ) ! is_wp_error( $prefix_error ) )
return;
$theme_errors = $prefix_error->get_error_messages( $prefix_theme_name );
echo '<h3>Theme Errors</h3>';
foreach ( $theme_errors as $error )
echo "{$error}\n";
}
add_action( 'shutdown', 'dump_theme_errors' );
Další informace naleznete na toto Q . Odtud je spojena příslušná jízdenka, která opravuje "společnou práci" WP_Error
a wp_die()
a následuje další lístek. Komentáře, kritici a takoví jsou oceňováni.
/ plugins/pluginname/{různé}
"Název_souboru" použitý pro složku by měl být vždy měnitelný.
Toto je obvykle zpracované definováním konstant a konzistentně používat je v celém pluginu.
Netřeba dodávat, že mnoho populárních pluginů jsou hříšníci.
plugins_url()
pro snadné propojení se zdroji, včetně pluginu.Zásuvný modul should omezuje jeho dopad co nejvíce pomocí minimalizuje počet jmen, které přidává do globálního jmenného prostoru .
To lze provést zapouzdřením funkcí pluginu do třídy nebo pomocí funkce PHP namespaces . Předpona všeho může také pomoci, ale není tak flexibilní.
Vedle funkcí a tříd zavádí plugin should not_ globální proměnné. Použití tříd je normálně zastarává a zjednodušuje údržbu pluginu.
Nejlepší praxe je blízko stylu PhpDoc. Pokud nepoužíváte IDE jako "Eclipse", stačí se podívat v příručce PhpDoc .
Nemusíte přesně vědět, jak to funguje. Profesionální vývojáři mohou kód číst stejně a potřebují jej pouze jako shrnutí. Hobby kodéři a uživatelé mohou ocenit způsob, jakým to vysvětlíte na stejné úrovni znalostí.
Namísto přidávání možností do databáze pomocí funkce add_option byste je měli ukládat jako pole pomocí Nastavení API , které se o vše postará.
API úprav je poměrně jednoduchá konstrukce a bezpečný způsob, který umožňuje přidávání a načítání možností. Vše se uloží jako serializovaná hodnota do vaší databáze. Snadné, bezpečné a jednoduché.
(Dříve: Anonymous API Communication)
Pokud modul plug-in komunikuje s externím systémem nebo rozhraním API (např. S některou službou Webservice), měl by tak učinit anonymně nebo poskytnout uživateli anonymní možnost, která zajistí, že žádná data týkající se uživatele pluginu neuniknou nekontrolované druhé straně.
V mnoha případech nemusí uživatelé chtít, aby všichni měli přístup k oblastem vytvořeným vaším pluginem, zejména s pluginy, které provádějí více složitých operací.
Přinejmenším, mít odpovídající schopnosti kontroly pro všechny různé druhy postupů, které lze použít plugin.
Použijte SVN repository uvedené na WordPress.org pro hostování pluginů. To umožňuje snadnější aktualizaci uživatelského prostředí a pokud jste nikdy předtím nepoužili SVN, dostane vás k tomu, abyste jej skutečně pochopili pomocí kontextu, který to odůvodňuje.
Je to vždy těžké číst kód, který není napsán v pořadí, v jakém je popraven. Nejprve zahrnout/vyžadovat, definovat, wp_enqueue_style & _script, atd., Pak funkce, které plugin/téma potřebuje a konečně stavitel (např. Admin obrazovka, věci, které jsou integrovány v tématu, atd.).
Pokuste se oddělit věci jako css a js ve svých vlastních složkách. Snažte se to také s funkcemi, které jsou pouze pomocníky, jako jsou pole flatteners a podobně. Udržet "hlavní" soubor jako čistý a snadno čitelný, jak je to možné, je způsob, který pomáhá uživatelům, vývojářům a vám, když se snažíte aktualizovat během jednoho roku a neviděli jste kód po delší dobu.
Je také dobré mít strukturu, kterou často opakujete, takže vždy najdete cestu. Vývoj ve známé struktuře na různých projektech vám dá čas, aby se to zlepšilo, ai když se váš klient přepne na jiného vývojáře, nikdy neslyšíte „nechal chaos“. To buduje vaši reputaci a mělo by být dlouhodobým cílem.
Není to tak běžné napříč pluginy, ale pokud váš plugin obsahuje (některá) nastavení, pak should poskytuje Import/Export dat jako je konfigurace a vstup uživatele .
Import/Export zlepšuje použitelnost pluginu.
Příklad-plugin, který má takovou funkci pro import a export (a také mechanismus zpět) je Breadcrumb NavXT (Wordpress Plugin) (úplné zveřejnění: nějaký malý kód, který jsem tam vytvořil, většina z nich byla provedena mtekkem) .
umřít slušným způsobem Všechny funkce pluginů (a dokonce i motivů) by měly používat wp_die()
v kritických místech, aby uživateli nabídly trochu informací o tom, co se stalo. Php chyby jsou nepříjemné a wp_die
může dát uživateli pěkně stylizovanou zprávu o tom, co plugin (nebo oni) udělali špatně. Navíc, pokud má uživatel debugování deaktivován, plugin se prostě zlomí.
Použití wp_die()
také pomáhá, aby vaše pluginy/motivy byly kompatibilní s wordpress testsuite .
Je hezčí říci RTFM (klikněte na tlačítko Nápověda) jako odpověď, než když budete muset znovu a znovu odpovídat na otázku.
/**
* Add contextual help for this screen
*
* @param $rtfm
* @uses get_current_screen
*/
function ContextualHelp( /*string*/ $rtfm)
{
$current_screen = get_current_screen();
if ($current_screen->id == $this->_pageid)
{
$rtfm .= '<h3>The WordPress Plugin - Screen A</h3>';
$rtfm .= '<p>Here are some tips: donate to me ' .
}
return $rtfm;
}
add_action('contextual_help', array($this,'ContextualHelp'),1,1);
update/note: (viz komentáře kaiser): výše uvedený příklad má být použit ve třídě
Pokud zásuvný modul nabízí možnost zadávání dat, měl by mít vždy konec na konci, přímo před tlačítkem "odeslat" a "reset", takže vývojáři mohou snadno rozšířit formulář nejen o pole, ale také tlačítka.
Viz: Nastavení API
funkce vždy přes Hook, ne přímo.
Příklad:
Nepoužívejte pro zahrnutí třídy pluginu přes nový bez háku
Použijte Hook plugins_loaded
// add the class to WP
function my_plugin_start() {
new my_plugin();
}
add_action( 'plugins_loaded', 'my_plugin_start' );
Update: malý živý příklad: Plugin-svn-trunk-page a pseudo příklad
//avoid direct calls to this file where wp core files not present
if (!function_exists ('add_action')) {
header('Status: 403 Forbidden');
header('HTTP/1.1 403 Forbidden');
exit();
}
if ( !class_exists( 'plugin_class' ) ) {
class plugin_class {
function __construct() {
}
} // end class
function plugin_start() {
new plugin_class();
}
add_action( 'plugins_loaded', 'plugin_start' );
} // end class_exists
Můžete také nahrát přes mu_plugins_loaded na vícenásobné instalaci, viz kodex pro odkaz na akci: http://codex.wordpress.org/Plugin_API/Action_Reference Také zde vidíte, jak se tento wP s tímto háčkem zobrazuje: http://adambrown.info/p/wp_hooks/hook/plugins_loaded?version=2.1&file=wp-settings.php Používám to velmi často a není to tak těžké a brzy, lépe jako nová třída ();
Popis pluginu by měl přesně popisovat funkce vašeho pluginu. K dispozici je 10 nabízených pluginů. Všechny z nich zobrazují doporučené příspěvky, ale mnoho z nich má různé funkce. Mělo by být snadné porovnat váš plugin s podobnými pluginy přečtením popisu.
Měli byste se vyvarovat chlubit se, jak jednoduchý je váš plugin, pokud to opravdu není velmi základní. V popisu byste měli uvést užitečné odkazy, jako je odkaz na nastavení.
Plug-iny a témata by měly být licencovány pod licencí kompatibilní s WordPress. To jim umožňuje být znovu distribuován s programem WordPress jako "program". Doporučená licence je GPL . Dbejte na to, aby všechny knihovny kódu obsažené v zásuvném modulu byly kompatibilní se stejnou licencí.
(Toto má byl problém a vážné bod rozpravy jak v minulosti, tak přítomno .)
Plugin by měl Webové služby mezipaměti/štítu a/nebo požadavky XMLRPC/SOAP přes vrstvu ukládání do mezipaměti/poskytovatele dat pokud je použijete k tomu, abyste nevyžadovali front-requesty na ( pomalá) webová služba.
To zahrnuje stažení RSS kanálu a dalších stránek. Navrhněte si pluginy, které požadují data v pozadí.
Jedním z možných KROKŮ je (Vezměte poslání do ping.fm jako příklad): Vytvořte tabulku vyrovnávací paměti, řekněme: ping_fm_buffer_post (datum, čas, zpráva, odeslaný čas, stav)
Měli bychom určitě mít nějaké testovací nástroje na našem vývojovém prostředí pluginů.
Na základě této odpovědi podle Ethan Seifert na testovací otázku, je to následující postup:
Jméno háčků a filtrů (třídy, funkce a vars), tak, že je lidé mohou identifikovat i v roce , když si už nepamatují, odkud tento kousek nebo kód pochází. Nezáleží na tom, zda se názvy háčků a filtrů prodlouží. Př. youruniquename_hook/filter_whatitdoes.
dbdbInit.class.php
".dbdbInit
-class funkci, která se registruje ex. custom_post_types, pak volání register_custom_post_types()
.$custom_post_type_names
.function array_handler( $array ) { // handle the array}
..Další věc: Pokud máte ladit věci pak, v 99% všech případů, dostanete všechny vaše zprávy nejen pro váš kód, ale také pro wordpress taky. Pokuste se tedy použít stejnou předponu ex. "dbdb
" pro vaše třídy, veřejné funkce a proměnné/objekty. Tímto způsobem je můžete snadno najít mezi stovkami souborů. (Wordpress načte 64 souborů před vaším motivem a asi 1.550 funkcemi, nemluvě o háčcích a filtrech.)
Poznámka: Po přečtení této rady, jsem nyní krok zpět z této praxe jako kontrola každé funkce pro existenci může zpomalit vaše stránky.
Zkontrolujte, zda jsou funkce zastaralé přímo ve vašem motivu.
To je příklad "může být takový".
if ( ! function_exists( 'wp_some_fn' ) )
{
$theme_data = wp_get_theme();
$error = new WP_Error( 'wp_some_fn', sprintf( __( 'The function %1$s is deprecated. Please inform the author', TEXTDOMAIN ), "Theme: {$theme_data->Name}: Version {$theme_data->Version}" );
// abort
if ( is_wp_error( $error ) )
return print $error->get_error_message();
}
// else if no error - the function works and exists
wp_some_fn();
Pro správné/nejlepší řešení chyb viz tato odpověď: link
Dalo by se i funkce $ zařadit do funkce. To vám a vašim uživatelům pomůže udržet si přehled o funkcích nebo třídách ve vašem tématu, které se mohou změnit.
Používání kódovacích standardů WordPress
http://codex.wordpress.org/WordPress_Coding_Standards
Víte, jak mnohem jednodušší je aktualizovat kód, na kterém jste pracovali, oproti kódu, který někdo dal dohromady? Normy kódování usnadňují vývojářům, kteří pracují na projektu, aby přišli a zjistili, co se děje.
Víme, že váš plugin nebo téma je vaše vlastní, a způsob, jakým si zlomíte linie a přidáte své složené závorky, je výrazem vaší individuality. Každá odrážka je pečlivě promyšlený výrok. Ale s vlastním kódem přispíváte do WordPressu, i když váš kód není v základní aplikaci. Kódovací standardy pomáhají vývojářům rychle se dostat do vašeho kódu.
Plugin should snížit dopad WordPress API na potřebné minimum tak oddělit plugin kód z WordPress kódu. To snižuje dopad změn v rámci WordPress codebase na plugin. Navíc to zlepšuje kompatibilitu mezi verzemi vašeho kódu pluginu.
To neznamená, že nepoužíváte WordPress funkce (použijte je, jako Re-Use existující funkce navrhuje), ale ne, aby váš kód kód s WordPress funguje příliš mnoho, ale oddělit vaše pluginy obchodní logiku z funkce WordPress.
Aby byl plugin snadno použitelný a přizpůsobitelný, měly by být všechny výstupní řetězce modifikovatelné. Nejlepším způsobem, jak to udělat, je použít wp-options pro uložení výstupních řetězců a poskytnutí backendu pro změnu výchozích hodnot. Plugin by neměl používat zobrazené řetězce, které nelze snadno měnit pomocí backendu pluginu.
Například: Sociable - dává vám možnost změnit větu, která se objeví před částmi ikony „sdílet a užívat si:“
Pro tento účel existují tři různé háčky:
register_uninstall_hook();
register_deactivation_hook();
register_activation_hook();