WordPress : Des custom post types vraiment custom

L’arrivée des custom post types dans WordPress 3 permet de gérer d’autres types que des articles et des pages. C’est une grande avancée : on peut définir de nouveaux types bien distincts, qui ont leur propre entrée dans le menu.

Cependant, ces custom post types sont un peu limités : en effet, on peut choisir quels champs on souhaite, mais seulement par rapport aux champs types d’un post (ou d’une page) : titre, extrait, champs personnalisés, vignette… En gros, on peut enlever des champs inutiles (ce qui est déjà pratique), mais on ne peut pas en ajouter.

Du coup j’ai développé un script pour ajouter des nouveaux champs. A noter que les fonctions citées ci-après vont se placer dans le fichier functions.php du thème, il n’y a donc aucune modification des entrailles de WordPress, et par conséquent pas de problème pour mettre ce dernier à jour.

Principe

  1. Nous créerons un custom post type, en gardant les champs qui nous intéressent.
  2. Nous créerons un tableau php dans lequel nous spécifierons les nouveaux champs souhaités ainsi que leurs types.
    Petite remarque : pour les champs pour lesquels on souhaite une liste de cases à cocher, je vous suggère fortement d’utiliser la fonction register_taxonomy, qui permet d’ajouter des catégories ou tags spécifiques à un custom post. En ajoutant des catégories à votre custom post type (càd en mettant hierarchical à true), vous aurez la même interface que pour choisir des catégories.
  3. Nous allons créér une fonction que nous placerons sur le hook ‘edit_form_advanced’. De cette façon, le texte affiché par notre fonction viendra se placer à la fin du formulaire d’édition d’un post. Nous n’oublierons pas de tester que nous sommes en train d’éditer notre custom type, sinon, nous allons affecter les formulaires de tous les posts !
    Cette fonction va prendre notre tableau de champs, et pour chaque élément, afficher dans le formulaire un input, un textarea, un select ou un checkbox selon le cas.
  4. A l’enregistrement du post (en s’attachant au hook ‘save_post’), nous prendrons tous les champs de notre tableau et l’on ajoutera/mettra à jour un champ personnalisé pour cet article.

Le code

Vous pouvez récupérer le code entier ici : code php pour des custom post types vraiment custom.

Explication de code

Préambule : Variables

global $myposttype;
global $myCustomTypeOptions;
$myposttype='moncustomposttype'; //id de mon custom post

N’ayant pas trouvé comment faire passer des paramètres à une fonction via add_action, je me suis rabattue sur la bonne ville méthode bien sale des variables globales (si qqn peut m’éclairer sur la question des paramètres via add_action, je suis preneuse).

Donc, on déclare deux variables globales, une pour le nom du custom post type, et une autre pour le tableau de champs de formulaires.

Etape 1 : Ajout de notre custom post type classique

On définit notre custom post type, on choisit les champs types qu’il supporte.
On ajoute éventuellement des catégories personnalisées.

add_action('init', 'moncustomposttype_init');
function moncustomposttype_init()
{
	global $myposttype;

	register_post_type($myposttype, array(
		'label' => 'Custom Posts',
		'singular_label' =>'Custom Post',
		'public' => true,
		'show_ui' => true,
		'capability_type' => 'post',
		'hierarchical' => false,
		'supports' => array('title', 'editor', 'thumbnail' )
	));

	/********** pour les checkbox à choix multiples : le plus simple est de déclarer une taxonomie hiérarchique (= catégorie)  ****************/
	register_taxonomy( 'couleurs', $myposttype, array( 'hierarchical' => true, 'label' => 'couleurs', 'query_var' => true, 'rewrite' => true ) );
}

Etape 2 : Le tableau de champs

Le tableau doit être rempli ainsi :
Pour chaque champs :
tableau(‘name’=> Label du champ,
‘desc’ => Petite description
‘id’=> l’attribut « name » du champ (c’est une bonne idée de préfixer par $myposttype_)
‘type’ => le type du champ (parmi « checkbox », « text », « select », « textarea »
‘options’ => pour le type select : tableau des valeurs d’options
‘std’=>; la valeur par défaut )

$myCustomTypeOptions = array (
	array(
		'name' => 'Mon champ text',
        'desc' => 'Description 1',
        'id' => $myposttype.'_champtexte',
        'type' => 'text',
        'std' => ''),
     array(
		'name' => 'Mon textarea',
        'desc' => 'Description 2',
        'id' => $myposttype.'_textarea',
        'type' => 'textarea',
        'std' => 'Youpi'),
    array(
		'name' => 'Mon select',
        'desc' => '',
        'id' => $myposttype.'_choix',
        'type' => 'select',
        'options' => array('choix 1','choix 2','choix 3'),
        'std' => 'choix 2'),
	array(
		'name' => 'Mon checkbox',
        'desc' => 'Case à cocher',
        'id' => $myposttype.'_case',
        'type' => 'checkbox',
        'std' => '1')
);

Etape 3 – La fonction qui ajoute les champs au formulaire

/************** à la fin du formulaire, ajout des champs définis dans $myCustomTypeOptions ***********/
add_action('edit_form_advanced', 'moncustomposttype_form');
add_action('save_post', 'moncustomposttype_save');
function moncustomposttype_form(){

	global $myposttype;
	global $myCustomTypeOptions;

	if((isset($_GET['post_type'])) and ($_GET['post_type']==$myposttype)) /* formulaire d'ajout */
	{
		echo '
'; /* formulaire vide (ou avec les valeurs par défaut) */ foreach ($myCustomTypeOptions as $o) { echo '
'; echo '

'.$o['name'].'

'; //fonction pour afficher le bon html en fonction du type, définie ci-après echo get_champ($o,$o['std']); if($o['desc']!='') echo ' '.$o['desc'].' '; echo '
'; } echo '
'; } else{ if(!isset($_GET['post_type'])) { if(isset($_GET['post'])) { if(get_post_type($_GET['post'])==$myposttype) /* formulaire de modification */ { $id=$_GET['post']; /* formulaire prérempli avec les valeurs pré-existantes */ echo '
'; foreach ($myCustomTypeOptions as $o) { echo '
'; echo '

'.$o['name'].'

'; echo get_champ($o,get_post_meta($id, $o['id'], true)); if($o['desc']!='') echo ' '.$o['desc'].' '; echo '
'; } echo '
'; } } } } } function get_champ($o,$val) { switch ($o['type']) { case 'textarea': echo ' '; break; case 'text': echo ' '; break; case 'checkbox': echo ' '.$o['name'].''; break; case 'select': echo ' '; break; } }

Etape 4 : Sauvegarder nos champs dans des champs personnalisés

/***************** Lors de la sauvegarde, ajout/modification d'un custom field par champs de $myCustomTypeOptions ***********/
function moncustomposttype_save(){

	global $myposttype;
	global $myCustomTypeOptions;

	if(isset($_POST['post_ID']))
	{
		$id=$_REQUEST['post_ID'];
		if(get_post_type($id)==$myposttype) /* si on édite bien un post du type $myposttype */
		{
			foreach ($myCustomTypeOptions as $o)
			{
if(isset($_POST[$o['id']])) {
					update_post_meta($id, $o['id'], $_POST[$o['id']]);
				}
				elseif($o['type']=='checkbox') {
					update_post_meta($id, $o['id'], 0);
				}
			}
		}
	}
}