WordPress CMS : les metaboxes

Publié par Gui dans Tutoriels, Wordpress

Avancée

Wordpress, PHP

Les metabox (ou boîtes à meta information) sont des données enregistrées pour un contenu spécifique (page ou article donné) et qui permettent par exemple de facilement modifier l’affichage du contenu selon les informations saisies.

En fait, vous les utilisez à chaque fois sans que vous le sachiez vraiment. Les catégories, tags, format etc… sont autant de metaboxes.

Création d’une métabox

Nous allons donc voir comment créer des metaboxes de manière générique et en utiliser une pour mettre en page notre contenu. Nous allons par exemple créer une metabox pour choisir la disposition d’une page.

Définition d’une metabox

Une metabox est définie selon plusieurs paramètres :

  1. Identifiant
  2. Titre
  3. Fonction de callback (d’affichage)
  4. Le type de contenu pour lequel elle sera applicable (‘post’, ‘page’, ‘link’, ou ‘custom_post_type’)
  5. L’emplacement (‘normal’, ‘advanced’, ou ‘side’)
  6. La priorité (l’ordre d’affichage dans la page)
  7. Les arguments à passer à la fonction de callback

Maintenant créez un fichier metabox_options.php et insérer le code suivant dedans :

<?php

$themename = "my_theme";
$metaboxes = array(
	'page_layout' => array(
		'title'			=> __('options', $themename),
		'applicableto'	=> 'page',
		'priority'		=> 'low',
		'location'		=> 'normal',
		'tabs'			=> array(
			'page_layout_options' => array(
				'title' 	=> __('layout', $themename),
				'fields' 	=> array(
					'layout_sidebar' => array(
						'title'			=> __('layout', $themename),
						'type' 			=> 'radio',
						'description'	=> __('choose page layout', $themename),
						'options'		=> array('full-width' => "<img src='".get_template_directory_uri().'/admin/img/full-width.png'."' alt='".__('full width', $themename)."' title='".__('full width', $themename)."' />", 'sidebar-content' => "<img src='".get_template_directory_uri().'/admin/img/sidebar-content.png'."' alt='".__('left sidebar', $themename)."' title='".__('left sidebar', $themename)."' />", 'content-sidebar' => "<img src='".get_template_directory_uri().'/admin/img/content-sidebar.png'."' alt='".__('right sidebar', $themename)."' title='".__('right sidebar', $themename)."' />")

					)
				)
			),
			'page_options' => array(
				'title' 	=> __('common options', $themename),
				'fields' 	=> array(
					'display_tagline' => array(
						'title'			=> __('hide page title', $themename),
						'type' 			=> 'checkbox',
						'description'	=> '',
						'size'			=> ''
					)
				)
			)
		)
	)
);

Explications

Les options ci-dessus correspondent aux paramètres des metaboxes :

$metaboxes = array(
	'metabox_ID' => array(
		'title' 	=> 'Titre',
		'applicableto'	=> 'Type de contenu applicable',
		'priority'		=> 'Priorité',
		'location'		=> 'Emplacement de la metabox',
		'tabs'			=> array(
			'identifiant Onglet' => array(
				'title'		=> 'Titre du premier onglet de la metabox',
				'fields'	=> array(
					'identifiant Champ' => array(
						'titre champ'	=> 'Titre du champ',
						'type' 			=> 'Type de champ',
						'description'	=> 'Description du champ',
						'options'		=> '(optionel) Valeur des options si type radio'
					)
				)
			)
		)
	)
);

Les libellés et descriptions utilisent gettext pour l’internationalisation.

Chargement des options

Dans un autre fichier metabox_framework.php, insérer le code suivant :

include_once("metaboxes_options.php");

add_action( 'admin_init', 'add_metaboxes' );

function add_metaboxes()
{
	if(!empty($metaboxes))
	{
		foreach($metaboxes as $id => $metabox)
		{
			add_meta_box($id, $metabox['title'], 'show_metaboxes', $metabox['applicableto'], $metabox['location'], $metabox['priority'], $id);
		}
	}
}

Après avoir inclus nos options, nous allons ajouter les métaboxes (informer WordPress de le faire pour nous via la fonction add_action).

Affichage des metaboxes

Maintenant que nos metaboxes sont créées, il nous faut les afficher dans la page d’administration du contenu adéquat.

Toujours dans ce dernier fichier, ajouter une fonction show_metaboxes() avec le code suivant :

<?php

function show_metaboxes($post, $args)
{
	global $themename, $metaboxes;

	$custom = get_post_custom($post->ID);
	$tabs = $metaboxes[$args['id']]['tabs'];

	/** Wrapper **/

	$output = "<div class='metabox-wrapper'>";

	/** Nonce **/
	$output .= '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';

	/** Menu **/
	$output .= '<div id="page_options_menu"><ul>';

	$i = 0;
	foreach($tabs as $id => $tab)
	{
		$output .= '<li';
		if($i == 0)
			$output .= ' class="active"';
		$output .= '><a href="#'.$id.'">'.__($tab['title'], $themename).'</a></li>';
		$i++;
	}

	$output .= '</ul></div>';

	/** Content **/
	$output .= '<div id="page_options_content"><div class="inner">';

	foreach($tabs as $id => $tab)
	{
		$fields = $tab['fields'];

		$output .= '<div class="option_content" id="'.$id.'">';

		$iter = 0;

		foreach($fields as $id => $field)
		{
			$output .= '<div class="row">
					<div class="label">
						<label for="'.$id.'">'.$field['title'].'</label>';
						if(!empty($field['description']))
							$output .= '<small>'.$field['description'].'</small>';
					$output .= '</div>
					<div class="value">';

			switch($field['type'])
			{
				case "text":
					$output .= '<input type="text" id="'.$id.'" name="'.$id.'" value="'.$custom[$id][0].'" size="'.$field['size'].'" />';
				break;

				case "checkbox":
					$output .= '<input type="checkbox" id="'.$id.'" name="'.$id.'" size="'.$field['size'].'"';
					if($custom[$id][0] == "on") $output .= " checked='checked'";
					$output .= '/>';
				break;

				case "radio":
					$output .= "<div class='green_block'>";

					$val = $custom[$id][0];
					$radio_id = $id;

					foreach($field['options'] as $id => $label) :
						if($val == $id) $checked = ' checked="checked"';
						else $checked = "";
						$output .= "<div class='radio-option'><label for='".$id."_$iter'>".$label."</label><input$checked type='radio' name='".$radio_id."' value='".$id."' id='".$id."_$iter' /></div>";
					endforeach;
					$output .= "</div>";
				break;
			}

			$output .= '</div></div>';

			$iter++;
		}
		$output .= '</div>';
	}

	$output .= '</div></div><div class="clear"></div></div>';

	echo $output;
}

Explications

Il y a plusieurs parties importantes dans ce code.

Nous allons dans un premier temps générer un nonce, une sécurité permettant de vérifier ensuite que notre code a bien l’autorisation d’enregistrer ces informations. Puis nous allons récupérer les données déjà associées à notre contenu :

$custom = get_post_custom($post->ID);
$tabs = $metaboxes[$args['id']]['tabs'];

/** Nonce **/
$output .= '<input type="hidden" name="custom_meta_box_nonce" value="'.wp_create_nonce(basename(__FILE__)).'" />';

$args[‘id’] est le dernier paramètre que l’on a passé à la fonction add_metabox et qui nous permet ici de récupérer les onglets de la bonne metabox.

Ensuite, nous allons parcourir deux fois (ceci pourrait être optimisé pour n’être fait qu’une seule fois) nos onglets pour d’une part construire le menu (les onglets) et ensuite le formulaire associé.

Nous faisons un switch pour afficher le contenu adéquat en fonction du type d’élément souhaité :

switch($field['type'])
{
	case "text":
		//
	break;

	case "checkbox":
		//
	break;

	...
}

Nous aurons donc quelque qui ressemble à cela :

Sauvegarde des metaboxes

Enfin, nous allons sauvegarder toutes nos informations en créant la fonction save_metaboxes.

add_action( 'save_post', 'save_metaboxes' );

function save_metaboxes($post_id)
{
	global $themename, $metaboxes;

	// verify nonce
	if (!wp_verify_nonce($_POST['custom_meta_box_nonce'], basename(__FILE__)))
		return $post_id;

	// check autosave
	if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
		return $post_id;

	// check permissions
	if ('page' == $_POST['post_type']) {
		if (!current_user_can('edit_page', $post_id))
			return $post_id;
		} elseif (!current_user_can('edit_post', $post_id)) {
			return $post_id;
	}

	$post_type = get_post_type();

	// loop through fields and save the data
	foreach($metaboxes as $id => $metabox)
	{
		// check if metabox is applicable for current post type
		if($metabox['applicableto'] == $post_type)
		{
			$tabs = $metaboxes[$id]['tabs'];

			foreach($tabs as $id => $tab)
			{
				$fields = $tab['fields'];
				foreach($fields as $id => $field)
				{
					$old = get_post_meta($post_id, $id, true);
					$new = $_POST[$id];

					if ($new && $new != $old)
					{
						update_post_meta($post_id, $id, $new);
					}
					elseif ('' == $new && $old || !isset($_POST[$id]))
					{
						delete_post_meta($post_id, $id, $old);
					}
				}
			}
		}
	}
}

Plusieurs étapes intéressantes dans ce code :

  1. On vérifie le nonce, afin de s’assurer que c’est bien notre script qui a commandé cette opération
  2. On vérifie que WordPress n’est pas en train d’autosaver le post, ce qui peut causer des pertes de données
  3. On s’assure que la personne connectée a les droits suffisants pour effectuer cette action
  4. Enfin, on boucle sur les metaboxes
  5. On vérifie qu’elles s’appliquent bien à ce type de contenu (get_post_type())
  6. Si le meta existe, on l’ajoute ou le modifie
  7. Sinon on le supprime (afin de ne pas polluer la base)

Utilisation des metaboxes dans les templates

Maintenant, nos metaboxes sont prêtes à être utilisées. Nous allons donc voir comment les exploiter au sein d’un template.

Pour cela, nous allons utiliser le template page.php pour modifier l’affichage du contenu.

Récupération des metas de la page courante :

$options = get_post_custom($post->ID);

Puis ajuster l’affichage (inclure la sidebar ou non) :

<?php

$options = get_post_custom($post->ID);
$layout = $options['layout_sidebar'][0];

if(empty($layout))
	$layout = "content-sidebar";

get_header();

switch($layout)
{
	case "full-width":
		the_content();
	break;

	case "content-sidebar":
		the_content();
		get_sidebar();
	break;

	case "sidebar-content":
		get_sidebar();
		the_content();
	break;
}

get_footer();

Ce qui nous donnera selon les cas les affichages suivants :

Conclusion

Voilà un exemple concret et générique d’utilisation des metaboxes pour améliorer l’affichage du contenu. Vous pouvez ensuite ajouter autant de metaboxes que vous le souhaitez, simplement en rajoutant des options dans le fichier d’options, et les utiliser dans vos fichiers de template.

6 commentaires

  1. Le Shmurtz

    Merci pour ce tutorial très intéressant !

  2. id meneo

    Très malin! C’est souvent le casse-tête pour implémenter des options en backoffice pour le client. Ca c’est hyper pratique!

  3. olive

    Bonjour,
    Je viens de tester votre tuto, chez moi rien ne s’affiche, pas de meta box dans la création d’une nouvelle page, les pages n’affichent plus rien en front end.

    questions :
    – $themename = « my_theme »; –> le nom de mon theme wp ?
    – fonction show_metaboxes() –> a mettre dans metabox_framework.php ou dans metabox_options.php ?
    – même question avec : fonction save_metaboxes ?
    – Récupération des metas de la page courante –> le code remplace tout dans notre page.php ou il est à ajouter dans la boucle (twentyeleven) ?
    – ne manque t’il pas des balises php pour : include_once(« metaboxes_options.php »); car le code est grisé dans mon metabox_framework.php (voir question 2)
    – les fichiers ne doivent ils pas communiquer avec notre functions.php ? (include)
    merci

    • Gui
  4. プラダ 靴 アウトレット,プラダバック 人気,ニナリッチ 香水 レベルドゥリ

    http://horselovermagazine.com/brstring/prada2f469-82953-54.htmlプラ&#12480; バッグ ナイロン,プラダ アウトレット 店舗,ニナリッチ 財布 店舗
    [url=http://dar-nsp.com.ua/brstring/prada31b79-92953-63.html]プラダ 靴 アウトレット,プラダバック 人気,ニナリッチ 香水 レベルドゥリッチ2[/url]

Laisser une réponse


Post shadow