• User Attivo

    child theme: errore fatale con funzioni

    Buonasera

    Sto personalizzando un child theme basato sul tema twentyten. Da quel che ho letto è possibile sovrascrivere anche le funzioni semplicemente creando nel child theme un documento **functions.php **ed inserendovi le nuove funzioni oppure quelle già presenti nel **functions.php **principale (in questo caso quello del tema twentyten) con le opportune modifiche. In questo modo le nuove funzioni da me inserite andranno a sovrascrivere o ad aggiungersi a quelle già esistenti.

    Nel fare questo finora non ho avuto alcun problema, poco fa però ho avuto la necessità di modificare la funzione **twentyten_continue_reading_link **e quindi, secondo quanto detto precedentemente, la ho copiata all'interno di **functions.php **del nuovo tema.

    Ecco cosa ho ottenuto:

    Fatal error: Cannot redeclare twentyten_continue_reading_link() (previously declared in /my-site/wp-content/themes/my-child-theme/functions.php:33) in /my-site/wp-content/themes/twentyten/functions.php on line 256

    quale mistero si nasconde dietro a tutto questo?

    Grazie.


  • User Attivo

    È possibile modificare alcune cose nel functions.php del tema child, utilizzando filtri, azioni, ecc ma pare che non si possano copiare e modificare se non a certe condizioni alcune funzioni del functions.php di TwentyTen, così almeno mi pare di aver capito nei link qui sotto.
    http://core.trac.wordpress.org/ticket/16500
    http://ottopress.com/2010/wordpress-protip-child-themes/


  • User Attivo

    Grazie mille ancora una volta.
    E' tutto spiegato più o meno qui:

    Overriding Functions

    One exception to the overriding mechanism of child themes has to do with the functions.php file. In a child theme situation, both functions.php files from both themes are loaded. This is necessary because elements of your parent theme might require pieces of the functions.php file to be loaded. This can make overriding functions in the parent theme tricky unless it?s written to allow you to do just that.
    The key to this is that the functions.php file of the child theme is loaded first. So if the parent theme is written in a manner WordPress calls ?pluggable?, then you can override those functions.
    In the twentyten theme?s functions.php file, several of the functions are defined like this:

    [TABLE]

    [TD="class: number"]1[/TD]
    [TD="class: content"]if ( ! function_exists( 'twentyten_admin_header_style' ) ) :[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]2[/TD]
    [TD="class: content"]function twentyten_admin_header_style() {[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]3[/TD]
    [TD="class: content"]...[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]4[/TD]
    [TD="class: content"]}[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]5[/TD]
    [TD="class: content"]endif;[/TD]
    [/TR]
    [/TABLE]

    That is a pluggable function. Basically, before it defines the function, it checks to see if the function is already defined. If the parent theme uses this mechanism, then a child theme can override this function by simply defining a function of the same name first. So all you have to do to change it is to copy the function into your child?s functions.php file and make your changes. When the parent theme loads, it will see that you already defined the function and continue on.
    Another way to override things is through the normal WordPress action and filter hook mechanisms. If a theme?s functions.php file uses those, then you can simply add your own hooked functions with different names. However, because the child?s functions.php file loads first, it can?t actually unhook things defined by the parent theme.
    The way to get around this is to use the after_setup_theme action hook. This action is called immediately after both functions.php files are loaded.
    For example, if I look at the twentyten theme, I?ll find this:

    [TABLE]

    [TD="class: number"]1[/TD]
    [TD="class: content"]function twentyten_excerpt_length( $length ) {[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]2[/TD]
    [TD="class: content"] return 40;[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]3[/TD]
    [TD="class: content"]}[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]4[/TD]
    [TD="class: content"]add_filter( 'excerpt_length', 'twentyten_excerpt_length' );[/TD]
    [/TR]
    [/TABLE]

    I don?t want that, I want my excerpts to be 55 words instead. So I add this to my functions.php file:

    [TABLE]

    [TD="class: number"]1[/TD]
    [TD="class: content"]function my_excerpt_length( $length ) {[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]2[/TD]
    [TD="class: content"] return 55;[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]3[/TD]
    [TD="class: content"]}[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]4[/TD]
    [TD="class: content"]add_filter( 'excerpt_length', 'my_excerpt_length' );[/TD]
    [/TR]
    [/TABLE]

    Whoops! It doesn?t work. Why not? Because I didn?t remove twentyten?s hook, and its filter is overriding mine. So I have to add this too:

    [TABLE]

    [TD="class: number"]1[/TD]
    [TD="class: content"]function my_undo_hooks( $length ) {[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]2[/TD]
    [TD="class: content"] remove_filter( 'excerpt_length', 'twentyten_excerpt_length' );[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]3[/TD]
    [TD="class: content"]}[/TD]
    [/TR]
    [/TABLE]

    [TABLE]

    [TD="class: number"]4[/TD]
    [TD="class: content"]add_action( 'after_setup_theme', 'my_undo_hooks' );[/TD]
    [/TR]
    [/TABLE]

    And then it works. I?ve added my filter, and removed the one in twentyten. Voila.

    In breve, il documento **functions.php **del *child theme *viene caricato prima di quello del main theme. Il codice prevede due tipi di funzioni, quelle "aggiornabili" (pluggable) e quelle no.
    Se una funzione è "pluggable" è reso evidente dalla presenza della verifica relativa all'esistenza stessa della funzione in questione **(if ( ! function_exists( 'nome_funzione' ) ) 🙂. In questo caso è possibile scrivere nel nostro functions.php la stessa funzione con le modifiche opportune e queste diverranno effettive.

    Diversamente la funzione non è modificabile attraverso il child theme. Per quel che ho dedotto si deve intervenire direttamente nel main theme modificando la funzione in questione oppure convertendola in "*pluggable" *per poi modificarla nel child theme.
    Insomma, in questo caso non si può fare a meno di intervenire direttamente nel tema principale.


  • User Attivo

    @Eugene said:

    Insomma, in questo caso non si può fare a meno di intervenire direttamente nel tema principale.
    Veramente io ho capito un' altra cosa, come in questo caso in cui la funzione non è pluggable nel file function di twentyten

    [PHP]function twentyten_excerpt_length( $length ) { return 40;}add_filter( 'excerpt_length', 'twentyten_excerpt_length' );[/PHP]

    Se voglio che la lunghezza dell' inizio post sia lunga 55 lettere invece di 40 non basta aggiungere questa mia funzione nel file function del child che non funzionerebbe

    [PHP]function my_excerpt_length( $length ) { return 55;}add_filter( 'excerpt_length', 'my_excerpt_length' );[/PHP]

    Ma devo aggiungere anche questa funzione al file function del child che serve a rimuovere quello di twenty ten in questo modo

    [PHP]function my_undo_hooks( $length ) { remove_filter( 'excerpt_length', 'twentyten_excerpt_length' );}add_action( 'after_setup_theme', 'my_undo_hooks' );[/PHP]


  • User Attivo

    In effetti questa faccenda degli hook l'avevo letta ma avevo capito fosse applicabile solo ad alcune funzioni. La mia proverbiale pigrizia e la voglia di fare tutto e subito hanno fatto si che non approfondissi l'argomento.
    Vediamo se ci ho capito qualcosa:
    non potendo modificare un funzione non "pluggabile" devo prima risciverla con un altro nome nel *child theme *e poi eliminare l'originale dal main theme, sempre tramite uno script nel child theme in modo da non apportare mai alcuna modifica al tema principale. Fin qui abbastanza chiaro, ma nell'esempio viene riportata una funzione che applica un filtro, mentre la funzione che devo modificare io è completamente differente:

    [PHP]function twentyten_continue_reading_link() {
    return ' <a href="'. get_permalink() . '">' . __( 'Continue reading <span class="meta-nav">→</span>', 'twentyten' ) . '</a>';
    }[/PHP]

    Come dovrei procedere?
    Inoltre questa funzione viene anche richiamata da altre funzioni e non so se eseguire la suddetta operazione (ovvero eliminarla e sostituirla) può compromettere il corretto funzionamento dell'intero sistema.


  • User Attivo

    Neanche io so se può compromettere qualcos'altro. Cercando ho trovato questo, ma non so se funziona.

    [PHP]function yoda_twentyten_continue_reading_link() {
    return ' <a href="'. get_permalink() . '">' . __( 'Continua a leggere <span class="meta-nav">→</span>', 'twentyten-child' ) . '</a>';
    }

    function yoda_twentyten_auto_excerpt_more( $more ) {
    return ' …' . yoda_twentyten_continue_reading_link();
    }

    function my_child_theme_setup() {
    remove_filter( 'excerpt_more', 'twentyten_auto_excerpt_more' );
    add_filter( 'excerpt_more', 'yoda_twentyten_auto_excerpt_more' );
    }

    add_action( 'after_setup_theme', 'my_child_theme_setup' );[/PHP]


  • User Attivo

    Purtroppo in questo momento non sono al mio PC e quindi non posso verificare l'efficacia del codice da te indicato, tuttavia vediamo se ho ben capito la logica di tutto questo:

    definisco la nuova funzione twentyten_continue_reading_link assegnandole un nuovo nome:
    [PHP]function yoda_twentyten_continue_reading_link() {
    return ' <a href="'. get_permalink() . '">' . __( 'Continua a leggere <span class="meta-nav">→</span>', 'twentyten-child' ) . '</a>';
    }[/PHP]

    per sicurezza (o correttezza) definisco anche le funzioni che richiamano quella da me precedentemente definita:
    [PHP]function yoda_twentyten_auto_excerpt_more( $more ) {
    return ' …' . yoda_twentyten_continue_reading_link();
    }[/PHP]

    "informo" il sistema del fatto che invece di richiamare la funzione twentyten_auto_excerpt_more deve adesso richiamare yoda_twentyten_auto_excerpt_more:
    [PHP]function my_child_theme_setup() {
    remove_filter( 'excerpt_more', 'twentyten_auto_excerpt_more' );
    add_filter( 'excerpt_more', 'yoda_twentyten_auto_excerpt_more' );
    }[/PHP]

    non ho capito la sintassi ma credo che serva per rendere effettivo quanto dichiarato dalla precedente funzione:
    [PHP]add_action( 'after_setup_theme', 'my_child_theme_setup' );[/PHP]

    In definitiva, se io modifico una funzione (alterandone il nome) devo far attenzione ad intervenire anche in tutte le altre funzioni che la richiamano.
    Attraverso remove_filter e add_filter "comunico" successivamente al sistema il nome della nuova funzione al posto di quella vecchia.

    Qualcosa l'ho azzeccata?


  • User Attivo

    In teoria si ma non garantisco nulla come sempre.


  • User Attivo

    Perfetto, non appena l'hosting torna attivo faccio dei test.

    Grazie ancora per l'aiuto e per i preziosi chiarimenti.


  • User Attivo

    Una piccola curiosità: che cappero sta ad indicare (o a cosa serve) il termine che si trova tra virgolette ('twentyten-child' o 'twentyten' o 'twentyeleven' o qualsiasi altra cosa) e che si trova ovunque nei temi?

    [PHP]function yoda_twentyten_continue_reading_link() {
    return ' <a href="'. get_permalink() . '">' . __( 'Continua a leggere <span class="meta-nav">→</span>', 'twentyten-child' ) . '</a>';
    } [/PHP]


  • User Attivo

    Sinceramente non lo so ma fa parte del codice di wordpress, se ti interessa ti rimando a questa lettura http://codex.wordpress.org/WordPress_Coding_Standards