Unde este cel mai bun loc pentru a utiliza add_filter

12 ian. 2013, 07:23:45
Vizualizări: 30.3K
Voturi: 15

Ar trebui să folosesc funcția add_filter în hook-ul de acțiune init al plugin-ului meu sau direct în scriptul principal al plugin-ului?

Uneori observ că dezvoltatorii folosesc filtre peste tot, iar dacă le pun în hook-ul init, ar putea fi prea târziu pentru unele cazuri.

Există sfaturi generale privind precedența hook-urilor de tip action și filter astfel încât să putem avea un stil de cod mai consistent?

0
Toate răspunsurile la întrebare 1
1
18

add_filter() și add_action() sunt disponibile înainte ca orice plugin să fie încărcat. Astfel, le puteți utiliza în prima linie a pluginului sau temei dumneavoastră.

Pentru o mai bună lizibilitate, recomand gruparea înregistrărilor de acțiuni și filtre la începutul fișierului principal:

  • într-un plugin, fișierul cu antetul pluginului
  • într-o temă, fișierul functions.php

Există excepții de la această regulă:

  • Callback-uri înlănțuite. În acest exemplu înregistrez o acțiune pentru shutdown doar atunci când primul filtru pentru wp_nav_menu_objects a fost apelat. Astfel, al doilea callback nu poate fi înregistrat în același timp cu primul.
  • Stil OOP. Uneori trebuie să configurați membrii clasei înainte de a putea înregistra callback-urile. Folosind un exemplu foarte asemănător

    add_action(
        'plugins_loaded',
        array ( T5_Plugin_Class_Demo::get_instance(), 'plugin_setup' )
    );
    class T5_Plugin_Class_Demo
    {
        public function plugin_setup()
        {
            $this->plugin_url    = plugins_url( '/', __FILE__ );
            $this->plugin_path   = plugin_dir_path( __FILE__ );
            $this->load_language( 'plugin_unique_name' );
    
            // mai multe operații: înregistrare acțiuni și filtre
        }
    }
    

    … vedem că instanțierea clasei poate fi oprită de un alt plugin, iar o clasă copil ar putea înregistra mai multe sau diferite filtre și acțiuni.

Pe lângă grupare, puteți merge un pas mai departe și oferi o acțiune personalizată pentru a facilita personalizările pentru alți dezvoltatori.
Iată un exemplu dintr-o temă la care lucrez:

add_action( 'activate_header',      't5_activate_screen' );
// wp_loaded este prea târziu, personalizatorul WP nu ar detecta caracteristicile atunci.
add_action( 'after_setup_theme',    't5_setup_custom_background' );
add_action( 'after_setup_theme',    't5_setup_custom_header' );
add_filter( 'body_class',           't5_enhance_body_class' );
add_action( 'comment_form_before',  't5_enqueue_comment_reply' );
add_action( 'content_before',       't5_frontpage_widget' );
add_action( 'footer_before',        't5_loop_navigation' );
add_action( 'get_the_excerpt',      't5_excerpt_clean_up', 1 );
add_action( 'header_before',        't5_skiplink', 0, 0 );
add_filter( 'the_title',            't5_fill_empty_title', 20, 1 );
add_action( 'wp_enqueue_scripts',   't5_enqueue_style' );
add_action( 'wp_enqueue_scripts',   't5_enqueue_script' );
add_action( 'wp_loaded',            't5_setup' );
add_action( 'wp_loaded',            't5_page_enhancements' );
add_action( 'wp_loaded',            't5_post_format_support' );
add_action( 'wp_loaded',            't5_load_theme_language' );
add_action( 'wp_loaded',            't5_setup_sidebars' );
add_filter( 'wp_nav_menu_items',    't5_customize_top_menu', 10, 2 );
add_filter( 'wp_nav_menu_args',     't5_nav_menu_args', 10, 1 );
add_filter( 'wp_title',             't5_wp_title_filter', 20, 2 );

add_shortcode( 'gallery',    't5_shortcode_gallery' );
add_shortcode( 'wp_caption', 't5_shortcode_img_caption' );
add_shortcode( 'caption',    't5_shortcode_img_caption' );

// Utilizați această acțiune pentru a dezînregistra acțiunile și filtrele temei.
do_action( 't5_theme_hooks_registered' );

Ultima linie este importantă: O temă copil sau un plugin se poate conecta acum la acțiunea t5_theme_hooks_registered și poate dezînregistra orice hook anterior. Acest lucru va evita lupta cu prioritățile, iar eu sunt liber să modific prioritățile callback-urilor mele oricând.

Dar nu vă bazați doar pe ordinea codului sursă. Documentați hook-urile pe care le utilizați în blocul de documentare. Folosesc o etichetă personalizată wp-hook pentru asta. Iată un exemplu cu hook-uri înlănțuite din aceeași temă:

/**
 * Înregistrează handler pentru excerpt generat automat.
 *
 * @wp-hook get_the_excerpt
 * @param   string $excerpt
 * @return  string
 */
function t5_excerpt_clean_up( $excerpt )
{
    if ( ! empty ( $excerpt ) )
        return $excerpt;

    add_filter( 'the_content', 't5_excerpt_content' );

    return $excerpt;
}
/**
 * Elimină părți din excerpt generat automat.
 *
 * @wp-hook the_content
 * @param   string $content
 * @return  string
 */
function t5_excerpt_content( $content )
{
    remove_filter( current_filter(), __FUNCTION__ );

    return preg_replace( '~<(pre|table).*</\1>~ms', '', $content );
}

Nu trebuie să derulați în sus pentru a vedea unde sunt apelate aceste funcții, o privire la blocul de documentare este suficientă. Acest lucru necesită ceva efort, deoarece trebuie să mențineți sincronizate atât înregistrarea, cât și comentariul, dar pe termen lung economisește timp valoros.

12 ian. 2013 08:08:49
Comentarii

+1. Pentru "stilul OOP", preferința mea este să deleg controlul către clasa/obiectul care apoi înregistrează acțiuni/filtre în constructorul său (sau mai târziu dacă este cazul). Acest lucru oferă o mai bună încapsulare (în stil OOP!) și amână înregistrarea hook-urilor până când clasa este utilizată/instanțiată.

webaware webaware
12 ian. 2013 08:25:18