Thèmes et
Planning Familial.

Pensez vos thèmes child-ready

- meilleures pratiques.

English version here

Paulina Hetman aka @PeHaa

Paulina Hetman aka @PeHaa

Thème Enfant - Child Theme

Ne fonctionne pas sans un autre thème, appelé parent

Hérite des fonctionnalités et des modèles du parent

Sans toucher au parent, un child thème permet :

  • d'apporter des modifications
  • d'ajouter des fonctionnalités et des modèles

Une MAJ du thème parent n'efface pas les modifications.

themes.php view
themes.php Theme details view

Thème WP

  • un dossier
  • dans "theme directory" (wp-content/themes)
  • contient obligatoirement style.css
  • modèle (template) est défini
  • wp-content
    • themes
      • theme-1
      • theme-1-child
      • theme-2
  • wp-content
    • themes
      • theme-1
      • theme-1-child
      • theme-2
stylesheet : ? ...
template : ? ...
  • wp-content
    • themes
      • theme-1
        • functions.php
        • index.php
        • style.css
        • footer.php
        • header.php
      • theme-1-child
      • theme-2
stylesheet : ? ...
template : ? ...
  • wp-content
    • themes
      • theme-1
        • functions.php
        • index.php
        • style.css
        • footer.php
        • header.php
      • theme-1-child
      • theme-2
stylesheet : ? ...
template : ? ...
  • wp-content
    • themes
      • theme-1
        • functions.php
        • index.php
        • style.css
          css checking for Template in style.css header
        • footer.php
        • header.php
      • theme-1-child
      • theme-2
stylesheet :theme-1
template : ? ...
  • wp-content
    • themes
      • theme-1
        • functions.php
        • index.php
        • style.css
        • footer.php
        • header.php
      • theme-1-child
      • theme-2
stylesheet :theme-1
template : ? ...
  • wp-content
    • themes
      • theme-1
        • functions.php
        • index.php
        • style.css
        • footer.php
        • header.php
      • theme-1-child
      • theme-2
stylesheet :theme-1
template : theme-1
  • wp-content
    • themes
      • theme-1
      • theme-1-child
      • theme-2
stylesheet : ? ...
template : ? ...
  • wp-content
    • themes
      • theme-1
      • theme-1-child
        • style.css
      • theme-2
stylesheet :theme-1-child
template : ? ...
  • wp-content
    • themes
      • theme-1
      • theme-1-child
        • style.css
          css checking for Template in style.css header
      • theme-2
stylesheet :theme-1-child
template : theme-1
Précision :

Si un dossier dans wp-content/themes ne contient pas de style.css dans sa racine, tous ses sous-dossiers de premier niveau sont scannés en tant que thèmes potentiels.

  • wp-content
    • themes
      • pehaa-package
        • pehaa-theme
        • pehaa-theme-child
Précision :

Si un dossier dans wp-content/themes ne contient pas de style.css dans sa racine, tous ses sous-dossiers de premier niveau sont scannés en tant que thèmes potentiels.

  • wp-content
    • themes
      • pehaa-package
        • themes
          • pehaa-theme
          • pehaa-theme-child

thèmes

template

vs

stylesheet

TEMPLATEPATH STYLESHEETPATH
get_template(); get_stylesheet();
get_template_directory(); get_stylesheet_directory();
... ...
dossier du template dossier du stylesheet
dossier du parentdossier du thème (child)

Thème Parent

template

vs

stylesheet

TEMPLATEPATH = STYLESHEETPATH
get_template(); = get_stylesheet();
get_template_directory(); = get_stylesheet_directory();
... = ...
dossier du template = dossier du stylesheet
dossier du parentdossier du thème (child)

Thème Enfant

template

vs

stylesheet

TEMPLATEPATHSTYLESHEETPATH
get_template();get_stylesheet();
get_template_directory();get_stylesheet_directory();
......
dossier du templatedossier du stylesheet
dossier du parentdossier du thème (child)

Important pour un thème child-ready:

Attention aux utilisations de : get_stylesheet_directory() et get_template_directory(). Ces fonctions ne sont pas interchangeables.

Ils ne seront plus équivalents si un child thème est activé.

Templates (Modèles)

Un fichier modèle dans le thème enfant (STYLESHEETPATH) écrase fichier modèle dans le thème parent (TEMPLATEPATH).

Un nouveau modèle peut être créé dans le thème enfant.


/* wp-includes/template.php */
if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
  $located = STYLESHEETPATH . '/' . $template_name;
  break;
} else if ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
  $located = TEMPLATEPATH . '/' . $template_name;
  break;
}
						

Functions.php

Les fichiers functions.php sont tous les deux chargés (s'ils existent).
Celui du child avant celui du parent.

/* wp-settings.php */
if ( TEMPLATEPATH !== STYLESHEETPATH && file_exists( STYLESHEETPATH . '/functions.php' ) )
  include( STYLESHEETPATH . '/functions.php' );
if ( file_exists( TEMPLATEPATH . '/functions.php' ) )
  include( TEMPLATEPATH . '/functions.php' );
						

Functions.php

Nouvelles fonctions

Le fichier functions.php créé dans le thème enfant permet d'ajouter facilement de nouvelles fonctions


/* pehaa-theme-child/functions.php */
function my_child_function() {
  ...
}

						

Functions.php

Modifications


/* pehaa-theme/functions.php */
function my_function() {
  ...
}

						

Comment modifier my_function ?


/* pehaa-theme-child/functions.php */
function my_function() {
  ...
}
						

Fatal error: Cannot redeclare my_function()


/* pehaa-theme-child/functions.php */
function my_function() {
  ...							
}
						

/* pehaa-theme/functions.php */
if ( !function_exists( 'my_function' ) ) :
  function my_function() {
    ...
  }
endif;
						

OK: my_function est déclaré dans le thème enfant.

Important pour un thème child-ready:
Déclarer les fonctions utilisateur de manière conditionnelle.

Style.css

Vu souvent


/* child style.css */
@import url('../parent-theme/style.css');
/* Theme customization starts here */
						

/* parent : functions.php */
add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );
function my_enqueue_styles() {
	wp_enqueue_style( 'style', get_stylesheet_uri() );
}
						

La méthode @import est une mauvaise pratique car le chargement de la page est ralenti.

Style.css

Vu souvent


/* child style.css */
@import url('../parent-theme/style.css');
/* Theme customization starts here */
						

/* parent : functions.php */
add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );
function my_enqueue_styles() {
	wp_enqueue_style( 'style', get_stylesheet_uri() );
}
						

Codex : Note that the previous method was to import the parent theme stylesheet using @import: this is no longer best practice.

Style.css

Codex


/* child : functions.php */
add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
  wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
						

/* twentyfifteen-child : functions.php */
add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
  wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
}
						

/* twentyfifteen : functions.php */
add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' );
function twentyfifteen_scripts() {
  ...
  // Load our main stylesheet.
  wp_enqueue_style( 'twentyfifteen-style', get_stylesheet_uri() );
  ...
}
						
Web Inspector

3 situations

1 (défault) :
child apporte des modifications
2 :
le style est défini de zéro dans le child
3 :
le style du parent n'est pas modifié
T
S
-
S
T
-

T - style.css du dossier de TEMPLATEPATH (parent)
S - style.css du dossier de STYLESHEETPATH (child)
					
/* parent : functions.php */
add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );
function my_enqueue_styles() {
  $deps = array();
  if ( apply_filters( 'load_template_css', is_child_theme() ) ) {
    wp_enqueue_style( 'T-style', get_template_directory_uri().'/style.css', $deps );
    $deps[] = 'T-style';
  }
  if ( apply_filters( 'load_stylesheet_css', true ) ) {
    wp_enqueue_style( 'S-style', get_stylesheet_uri(), $deps );
  }
}
						

Parent est activé : S-style est chargé

3e paramètre du 'wp_enqueue_style' (dépendances) garantit que 'T-style' (parent) sera chargé avant 'S-style' (child).

					
/* parent : functions.php */
add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );
function my_enqueue_styles() {
  $deps = array();
  if ( apply_filters( 'load_template_css', is_child_theme() ) ) {
    wp_enqueue_style( 'T-style', get_template_directory_uri().'/style.css', $deps );
    $deps[] = 'T-style';
  }
  if ( apply_filters( 'load_stylesheet_css', true ) ) {
    wp_enqueue_style( 'S-style', get_stylesheet_uri(), $deps );
  }
}
						

Child est activé : T est S sont chargés (dans cet ordre)

3e paramètre du 'wp_enqueue_style' (dépendances) garantit que 'T-style' (parent) sera chargé avant 'S-style' (child).

Situation 2 :

le style est défini de zéro dans le child

					
/* child situation 2 : functions.php */
add_filter( 'load_template_css', 'do_not_load' );
function do_not_load() {
  return false;
}
						
					
/* parent : functions.php */
add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );
function my_enqueue_styles() {
  $deps = array();
  if ( apply_filters( 'load_template_css', is_child_theme() ) ) {
    wp_enqueue_style( 'T-style', get_template_directory_uri().'/style.css', $deps );
    $deps[] = 'T-style';
  }
  if ( apply_filters( 'load_stylesheet_css', true ) ) {
    wp_enqueue_style( 'S-style', get_stylesheet_uri(), $deps );
  }
}
						

Situation 3 :

le style n'est pas modifié

	
/* child situation 3 : functions.php */
add_filter( 'load_stylesheet_css', 'do_not_load' );
function do_not_load() {
  return false;
}
						
					
/* parent : functions.php */
add_action( 'wp_enqueue_scripts', 'my_enqueue_styles' );
function my_enqueue_styles() {
  $deps = array();
  if ( apply_filters( 'load_template_css', is_child_theme() ) ) {
    wp_enqueue_style( 'T-style', get_template_directory_uri().'/style.css', $deps );
    $deps[] = 'T-style';
  }
  if ( apply_filters( 'load_stylesheet_css', true ) ) {
    wp_enqueue_style( 'S-style', get_stylesheet_uri(), $deps );
  }
}
						

Hooks : Actions & Filters


apply_filters( $tag, $value, $var, ... );
						

Retourne $value après avoir appelé toutes les fonctions attachées au $tag (dans un ordre précis)



do_action( $tag, $args );
						

Exécute toutes les fonctions attachées au $tag (dans un ordre précis)



add_filter( $tag, $function, $priority, $acccepted_args );
add_action( $tag, $function, $priority, $acccepted_args );
						

Attache une fonction au $tag dans l'ordre défini par $priority

Exemple 1

footer footer
	
/* twentyfifteen-child : functions.php */
add_action( 'twentyfifteen_credits', 'pehaa_credits' );
function pehaa_credits() {
  echo 'Customized by PeHaa.';
}
						
	
/* twentyfifteen : footer.php */
do_action( 'twentyfifteen_credits' );
						
footer

Exemple 2

au lieu de :
					
/* parent : functions.php */
require get_template_directory() . 'my_file.php';
						
on utilise :
					
/* parent : functions.php */
require apply_filters( 'my_file_directory', get_template_directory() ) . 'my_file.php';
						
ce qui permet d'ajouter et modifier 'my_file.php' dans le child :
					
/* child : functions.php */
add_filter( 'my_file_directory', 'my_stylesheet_dir' );
function my_stylesheet_dir() {
	return get_stylesheet_directory();
}
						

Récap

À ne pas oublier au cours de développement du thème:

  • différence entre 'template' et 'stylesheet'
  • l'ordre de chargement des fichiers functions.php
  • déclarer les fonctions de manière conditionnelle
  • utiliser le plus souvent possible "apply_filters" et "do_action"

Twitter: @PeHaa

Merci à tous et bon développement en 2015 !