Sviluppare plugin per WordPress: Best Practice e Silver Bullet
1. Sviluppare plugin per
WordPress
di LUCA BARTOLI
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013
@WORDCAMPBOLOGNA # WPCAMPBO13
2. CHI SONO
Luca Bartoli
Web: www.orbitalwaves.it
Twitter: @lucabartoli
LinkedIn: lucabartoli00
BIO
Sviluppatore e ed esperto SEO, si occupa di web da oltre 10 anni e sviluppa
in PHP dal 2004. Attivo soprattutto in ambito B2B, collabora con diverse
società per la realizzazione di progetti web che spaziano dai portali
istituzionali ai backend aziendali e CRM.
E’ fondatore della neonata Orbital Waves, società che si occupa di strategie
e tecnologie per il web.
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
5. OOP NELLO SVILUPPO DEI PLUGINS
Moltissimi plugin non implementano un
modello di programmazione ad oggetti.
1. <?
2. class Mio_Plugin {
3. ...
4. }
Principali problemi della programmazione procedurale:
1. Confusione
2. Alto impatto delle modifiche sul codice
WordPress sta gradualmente riorganizzando
tutto il proprio codice in classi.
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
6. STRUTTURA TIPO DI UN PLUGIN (1/2)
1. <?php
2.
3. class Mio_Plugin {
4.
5. function __construct() {
6. add_action( 'plugins_loaded', array( $this, 'init' ));
7. }
8.
9. function init() {
10. ...
11. }
12.
13. function my_function_1(...) {
14. ...
15. }
16.
17. function my_function_2(...) {
18. ...
19. }
20. }
21.
22. $mio_plugin = new MioPlugin;
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
7. STRUTTURA TIPO DI UN PLUGIN (2/2)
L’organizzazione tipica delle cartelle di un plugin ben
strutturato divide i files per scopo.
mio-plugin.php contiene solamente il
bootstrap del plugin, ed instanzia la
classe principale contenuta in
core/classes/
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
8. STRUTTURA TIPO DI UN PLUGIN: 2 SIMPLE TIPS
Evitare le chiamate dirette al plugin, se non ci si trova in
ambiente WP:
1. if (!function_exists ('add_action')) {
2. header('Status: 403 Forbidden');
3. header('HTTP/1.1 403 Forbidden');
4. exit();
5. }
Evitare conflitti
1. if ( !class_exists( 'MioPlugin' ) ) {
2.
3. class MioPlugin {
4. ...
5. }
6. }
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
12. Utilizzate le funzioni di
WordPress!!
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
13. UTILIZZARE LE FUNZIONI E GLI OGGETTI DI WORDPRESS
Qualche esempio:
Retrieve di contenuti esterni senza curl:
1. wp_remote_request(…) oppure 1. WP_Http::request(…)
Include di script e css:
1. wp_enqueque_style(…) 1. wp_enqueque_script(…)
Query sul database:
1. global $wpdb;
2. $myrows = $wpdb->get_results( "SELECT id, name FROM mytable" );
Alcune funzioni utili per i files:
1. unzip_file( $file, $to );
1. wp_handle_upload( $file, $overrides, $time );
2. wp_handle_sideload( $file, $overrides, $time );
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
14. UTILIZZARE LE FUNZIONI E GLI OGGETTI DI WORDPRESS
Una nuova classe per gestire le immagini:
1. $image = wp_get_image_editor( 'cool_image.jpg' );
2.
3. if ( ! is_wp_error( $image ) ) {
4. $image->rotate( 90 );
5. $image->resize( 300, 300, true );
6. $image->save( 'new_image.jpg' );
7. }
http://codex.wordpress.org/Class_Reference/WP_Image_Editor
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
15. UTILIZZARE LE FUNZIONI E GLI OGGETTI DI WORDPRESS
Argomenti delle funzioni:
1. function mia_funzione( $args = array() ) {
2. $defaults = array(
3. 'first_arg' => true,
4. 'second_arg' => 'bar'
5. $args = wp_parse_args($args, $defaults);
6. ...
7. }
1. mia_funzione( array( 'first_arg' => 'foo' ) );
2. mia_funzione('first_arg=false');
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
16. INTERNAZIONALIZZARE I PROPRI PLUGIN
Quando internazionalizzare un plugin?
1. __( $text, $domain );
2. _e( $text, $domain );
3. _n( $single, $plural, $number, $domain );
1. printf( _n( 'We deleted %d spam message.', 'We deleted %d spam
messages.', $count ), $count );
http://codex.wordpress.org/I18n_for_WordPress_Developers
È una buona abitudine, e non comporta lavoro aggiuntivo. È consigliabile
anche se non si ha la necessità di avere altre lingue:
Potrebbe servire successivamente o essere implementato da altri
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
18. ACTIONS E FILTERS
Può essere interessante poter aggiungere o alterare alcuni
dati prima dell’output:
1. $myvar = apply_filters( $tag, $value, $param, $otherparam );
Ed eseguire particolari azioni ogni volta che si verifica un
evento:
1. …
2. do_action( 'my_action', $arg );
3. …
1. $myEmailClass = new emailer();
2. add_action('my_action', array($myEmailClass, 'send'));
http://codex.wordpress.org/Plugin_API
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
19. DEBUG
È fondamentale mantenere attivo il debug durante tutto lo
sviluppo e accertarsi che non vengano generati errori:
1. define('WP_DEBUG', true);
In produzione disattiviamo il debug e attiviamo il log:
1. define('WP_DEBUG', false);
2. define('WP_DEBUG_LOG', true);
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
20. GESTIONE DEGLI ERRORI
Possiamo gestire gli errori attraverso la classe WP_Error:
1. $error = new WP_Error( 'Error Code', __( 'My error description',
TEXTDOMAIN ) );
1. if ( isset( $error ) && is_wp_error( $error ))
2. wp_die( $error );
http://codex.wordpress.org/Class_Reference/WP_Error
Utilizzare wp_die permette anche di ottenere un feedback
corretto dai test automatici PHPUnit
http://codex.wordpress.org/User Hakre/WP_Unit-Tests
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
21. COMPOSIZIONE DELLE URL
Mai comporre url hardcoded:
1. get_bloginfo('url').'wp-content/plugins/nomeplugin/a.php'
1. plugins_url( 'a.php',__FILE__);
1. site_url(); 1. home_url();
Spesso è utile salvare la directory del plugin durante il bootstrap
1. define( 'MY_PLUGIN_DIR', dirname(__FILE__) );
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
22. SICUREZZA DEI PLUGINS
1. Filter input, escape output
2. Verificare le capabilities dell’utente
1. current_user_can( $capability, $args );
3. Usare i nonces per evitare i CSRF
1. <form method="post">
2. <!-- some inputs here ... -->
3. <?php wp_nonce_field('name_of_my_action','name_of_nonce_field'); ?>
4. </form>
1. if ( empty($_POST) ||
!wp_verify_nonce($_POST['name_of_nonce_field'],'name_of_my_action') )
4. Usare wpdb::prepare per evitare SQL Injection
1. $sql = $wpdb->prepare( 'query' , value_parameter[, ... ] );
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
24. DISATTIVAZIONE E RIMOZIONE PLUGIN
Attivazione del plugin
1. register_activation_hook( __FILE__, 'my_activation_hook' );
Impostare e modificare rewrite rules Init del plugin
Impostare ruoli e capabilities add_option, custom posts,
taxonomies…
Disattivazione del plugin
1. register_deactivation_hook( __FILE__, 'my_deactivation_hook' );
Restore e flush rewrite rules
Non rimuovere i dati
Restore ruoli e capabilities
Rimozione del plugin
1. //uninstall.php Eliminiamo i dati,
2. if ( ! defined ( 'WP_UNINSTALL_PLUGIN' ) )
possibilmente informando
3. die();
4. delete_option ( 'my_plugin_option' ); l’utente, o chiedendo il
consenso
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
25. SFRUTTARE LE NOVITÀ DI PHP
5.3
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
26. CLOSURES
Sicuramente le avrete già viste ed utilizzate in javascript, in
particolare in framework tipo jQuery
1. $("#target").click(function() {
2. alert("Yeeee.");
3. });
Dalla versione 5.3 è possibile anche in PHP
1. add_filter( 'excerpt_length', function() {
2. return 50;
3. } );
Problemi di prestazioni e …
1. remove_filter( $tag, $function_to_remove, $priority, $accepted_args );
???
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
27. NAMESPACES
Esistono molte tecniche per evitare i conflitti di naming.
1. Prefixing
1. function myprefix_slider_render( $foo, $bar );
2. function myprefix_slider_add_slide ( $slide );
2. Class wrapping
1. class myprefix_slider {
2. function render( $foo, $bar );
Dalla versione 5.3 è possibile anche in PHP
3. function add_slide( $slide );
4. }
Da PHP 5.3 possiamo utilizzare i namespaces:
1. //1.php 1. //2.php
2. namespace MyPrefixSlider; 2. require_once('1.php');
3. function render() { ... } 3. use MyPrefixSlider as Slider;
4. function add_slide( $slide ) { ... } 4. Sliderrender();
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
28. CLOSURES E NAMESPACES: QUANDO USARLI
È importante valutare quando utilizzare funzioni e funzionalità
che richiedono PHP 5.3:
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
29. GRAZIE PER L’ATTENZIONE,
CI SONO DOMANDE?
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13
30. LUCA BARTOLI
Luca Bartoli
Web: www.orbitalwaves.it
Twitter: @lucabartoli
LinkedIn: lucabartoli00
BIO
Sviluppatore e ed esperto SEO, si occupa di web da oltre 10 anni e sviluppa
in PHP dal 2004. Attivo soprattutto in ambito B2B, collabora con diverse
società per la realizzazione di progetti web che spaziano dai portali
istituzionali ai backend aziendali e CRM.
E’ fondatore della neonata Orbital Waves, società che si occupa di strategie
e tecnologie per il web.
WORDCAMP BOLOGNA - 9 FEBBRAIO 2013 @WORDCAMPBOLOGNA # WPCAMPBO13