Créer une nouvelle entité « Projets » avec les Custom Post Type

Pour rappel les Custom Post Types permettent de rajouter des entités supplémentaires à votre site wordpress. Par exemple je souhaite ajouter une entité « projets » afin de gérer et afficher mes projets en cours. J’aurai pu simplement créer une catégorie « projets » dans les articles mais mon entité projet est plus complexe qu’un simple billet de blog. Dans un précédent article j’ai fais une première approche des Custom Post Type grâce au plugin Easy Post Type. Ce tutoriel va vous permettre de créer vos propres custom post type sans plugin, ce qui vous permettra une meilleur souplesse dans vos projets WordPress. De bonnes notions de développement sont nécessaires afin de bien comprendre. Si vous êtes débutant je vous invite à regarder ce lien avant de vous attaquer à ce long tutoriel : plugin Easy Post Type.

function projet_module() {
$args = array(
'label' => __('Projets'),
'singular_label' => __('Projet'),
'public' => true,
'show_ui' => true,
'_builtin' => false, // It's a custom post type, not built in
'_edit_link' => 'post.php?post=%d',
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => array("slug" => "projects"),
'query_var' => "projets", // This goes to the WP_Query schema
'supports' => array('title', 'editor', 'thumbnail') //titre + zone de texte + champs personnalisés + miniature valeur possible : 'title','editor','author','thumbnail','excerpt'
);
register_post_type( 'projet' , $args ); // enregistrement de l'entité projet basé sur les arguments ci-dessus
register_taxonomy_for_object_type('post_tag', 'projet','show_tagcloud=1&hierarchical=true'); // ajout des mots clés pour notre custom post type
//add_action("admin_init", "admin_init"); function pour ajouter des champs personnalisés
//add_action('save_post', 'save_custom'); function pour la sauvegarde de nos champs personnalisés
}
add_action('init', 'projet_module');

Résultat : Depuis l’administration wordpress l’entité « Projets » doit apparaitre. Actuellement si on souhaite ajouter un projet, ce dernier aura quasiment la même structure qu’un billet libre. Le but maintenant est d’ajouter des champs personnalisés à notre entité.

function admin_init(){ //initialisation des champs spécifiques
add_meta_box("url_projet", "Url du projet", "url_projet", "projet", "normal", "low");  //il s'agit de notre champ personnalisé qui apelera la fonction url_projet()
}
function url_projet(){     //La fonction qui affiche notre champs personnalisé dans l'administration
global $post;
$custom = get_post_custom($post->ID); //fonction pour récupérer la valeur de notre champ
$url_projet = $custom["url_projet"][0];
?>
<input size="70" type="text" value="<?php echo $url_projet;?>" name="url_projet"/>
<?php
}
function save_custom(){ //sauvegarde des champs spécifiques
global $post;
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { // fonction pour éviter  le vidage des champs personnalisés lors de la sauvegarde automatique
return $postID;
}
update_post_meta($post->ID, "url_projet", $_POST["url_projet"]); //enregistrement dans la base de données
}
add_action("admin_init", "admin_init"); //function pour ajouter des champs personnalisés
add_action('save_post', 'save_custom'); //function pour la sauvegarde de nos champs personnalisés
$labelsCat1 = array(
'name' => _x( 'Clients', 'post type general name' ),
'singular_name' => _x( 'Client', 'post type singular name' ),
'add_new' => _x( 'Add New', 'client' ),
'add_new_item' => __( 'Ajouter un client' ),
'edit_item' => __( 'Modifier le client' ),
'new_item' => __( 'Nouveau client' ),
'view_item' => __( 'Voir le client' ),
'search_items' => __( 'Rechercher des clients' ),
'not_found' =>  __( 'Aucun client trouvé' ),
'not_found_in_trash' => __( 'Aucun client trouvé' ),
'parent_item_colon' => ''
);
register_taxonomy("clients", array("projet"), array("hierarchical" => true, "labels" => $labelsCat1, "rewrite" => true));

Résultat : L’entité projet possède maintenant une catégorie Clients (vous pouvez créer d’autres catégories si vous le souhaitez).

Depuis l’édition d’un article un bloc Client apparait.

Après avoir ajouté quelques projets depuis l’admin nous allons maintenant créer un modèle de page qui va accueillir tous nos projets.

Création d’un modèle de page.

  • Dupliquer le fichier page.php de votre template et renommer ce nouveau fichier par exemple : page-projets.php.
  • Editer page-projets.php avec un éditeur de texte et ajouter cette ligne de code :
/**
Template Name: Page des projets
*/
  • Uploader ce nouveau fichier via ftp dans le répertoire de votre template.
  • Depuis votre administration WordPress, créer une nouvelle page « projets ».
  • Changer le modèle de page « Modèle par défault » par « Page des projets » depuis la liste déroulante :

  • Voila votre modèle de page relié à votre page projets, maintenant il reste simplement à appeler la fonction d’affichage des projets.

Affichage des projets sur le site

Dans votre fichier page-projets.php repérer la ligne : &lt;?php the_content(); ?&gt;

Juste en dessous de cette ligne ajouter ce code :

<div id="projets">
<?php  $temp_query = $wp_query;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args=array(
'caller_get_posts'=>1,
'post_type' => 'projet',
'paged'=>$paged
);
$wp_query = new WP_Query($args);
while ($wp_query->have_posts()) : $wp_query->the_post();
$src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID));
?>
<a href="<?php the_permalink();?>"><img src="<?php echo $src[0];?>" /></a>
<h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
<?php
$terms = get_the_terms($post->ID, 'clients', '', ', ','');
if ( !empty( $terms ) ){
$numTerm = 0;
echo "<h3>CLIENT : </h3>";
echo "<p>";
foreach( $terms as $term ) {
$numTerm++;
if ($numTerm == 1){
echo " ".$term->name;
}
else{
echo ", ".$term->name;
}
}
echo "</p><br/>";
}
?>
<div>
<p><?php the_excerpt(); ?></p>
</div>
</div>

Résultat : Notre page devrait accueillir les projets, il ne reste plus qu’à faire la page intérieur.

Page intérieur (single-project.php)

Dupliquer le fichier single.php et renommer la copie single-project.php Tous les codes sont à coller à l’intérieur de la boucle WordPress :

1) Ajouter le champ personnalisé Url du projet :

<?php
$custom = get_post_custom($post->ID);
$url_projet = $custom["url_projet"][0];
?>
<a href="<?php echo $url_projet;?>">Voir ce lien</a>

2)Ajouter la catégorie client :

<?php
$terms = get_the_terms($post->ID, 'clients', '', ', ','');
if ( !empty( $terms ) ){
$numTerm = 0;
foreach( $terms as $term ) {
$numTerm++;
if ($numTerm == 1){
echo " ".$term->name;
}
else{
echo ", ".$term->name;
}
}
}
?>

Laisser un commentaire

39 Commentaires

  1. Bonjour Benjamin,
    Merci pour cet article, j’ai tourné à travers un tas de site et ce n’est pas évident de trouver quelque chose d’à peu près clair en terme de codes sur les post_type et les taxonomies.
    Je suis confronté à un problème depuis plusieurs jours, sans trouver de solution. J’ai une taxonomie hiérarchisée (France, Régions, Villes) et quand je veux afficher l’élément le plus bas (la ville) WordPress me retourne parfois ‘France’ et d’autre fois ma ville.
    Pourrais-tu me guider avec un code qui m’assure d’avoir ma ville à chaque coup ? Je suis sur que c’est une question d’ordre, mais je ne vois pas ou placer ce paramètre.

    Merci d’avance.

    1. Le code ci-dessous à mettre dans le fichier single- »ton-custom-post-type ».php fonctionne pour une taxonomy à 3 niveaux (Pays,Régions,Villes) :


      $taxonomy = "ta-taxonomy";
      $terms = get_the_terms(get_the_ID(), $taxonomy);
      $villesAndRegions = array();
      $villes = array();
      $pays = array();
      foreach ($terms as $term) {
      if ($term->parent){ $villesAndRegions[] = $term->term_id;}
      else{$pays[] = $term->term_id;} //on recupere les pays
      }
      foreach ($terms as $term) {
      if ($term->parent){
      if(in_array($term->parent,$pays)){
      // il s'agit des regions
      }
      else{
      //et la des villes !
      $villes[] = $term->name;
      }
      }
      }
      echo 'Ville: ' . implode(', ', $villes);?>

  2. Il fallait que je trouve une solution rapidement, alors j’ai finalement utilisé une autre méthode, mais je reviendrait sans doute sur ton code pour voir d’un peu plus près ce que tu m’a suggéré ^^ En tous cas merci d’avoir pris le temps de répondre.

  3. Bonjour,
    Je suis un peu embêté, je ne sais pas si j’ai bien tout compris.

    Je fais une partie encyclopédie sur mon site, j’ai donc utilisé ses custom post type pour avoir des fiches de types personnalités, de type personnages, de types consoles, de type sociétés, etc.

    Hors le soucis c’est que j’aimerai avoir un template différent pour chacun de ses fiches.
    Quand on créé un nouveau template, par exemple un template personnalité, le modèle est accessible depuis les attributs de la page (quand on créé une nouvelle page) mais pas depuis l’admin des personnalités. Il n’y a que l’ordre qu’on peut influencer.

    Avez vous une idée pour que le modèle soit accessible par là où qu’il soit directement sélectionné (peut être que vous l’avez expliquer mais je n’ai pas tout saisi)

    Merci d’avance

    1. Bonjour,

      Tu devrais créer un modele de page « page-fiche-personnages.php » par exemple comme expliqué dans cet article, tu repères cette portion de code :

      $args=array(
      'caller_get_posts'=>1,
      'post_type' => 'projet',
      'paged'=>$paged
      );

      et tu la remplace par :

      $args=array(
      'caller_get_posts'=>1,
      'post_type' => 'projet',
      'taxonomy' => 'prodcat', // le nom de ta taxonomy (fiche)
      'term' => 'term name', //le slug de ton terme (personnage)
      'paged'=>$paged
      );

      Le slug est en dessous du titre (minuscule sans espace).

      1. je ne t’avais jamais remercié, mais merci bien pour tes instructions, tuto clair et aides personnalisées, c’est plutôt rare.
        Un grand merci à toi.

        1. Merci pour ton commentaire ! J’essaye au mieux malgré mon manque de temps à fournir à tous le plus d’aides personnalisés. A bientôt !

  4. Bonjour,

    Bien qu’ayant respecter ce qui était écris (placer le code au dessus du premier, enlever les //), une erreur s’affiche quand je place le code « champ personnalisé ».

    Une idée d’où pourrait venir le problème ?

    Merci

    1. Peux tu m’indiquer cette erreur ?

  5. Lors de l’étape : Affichage des projets sur le site, j’ai un soucis apparemment il y aurai une erreur :)

    Apparemment une erreur de « syntaxe » que je ne trouve pas.

    Julie Franck.

    1. Bonsoir Julie pourrais tu m’indiquer cette erreur ?

      1. 1,
        'post_type' => 'projet',
        'paged'=>$paged
        );
        $wp_query = new WP_Query($args);
        while ($wp_query->have_posts()) : $wp_query->the_post();
        $src = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID)); */
        ?>

        Apparement on utilise plus : caller_get_posts mais ignore_sticky_posts

        De plus je pense que tu a une erreur ou niveau de ici :

        while ($wp_query->have_posts()) : $wp_query->the_post();

        J’en suis presque sur :)

        Tiens moi au courant, du coup je bloque sur ton tuto ^^

        1. Bonjour Julie,

          Je suis énormément occupé en ce moment beaucoup de boulot et pas de vacances donc je vais te demander plus d’infos :

          Je n’ai pas eu le temps de tester ce code sous WP 3.2 donc peux tu me confirmer que tu utilises bien cette version car j’ai utilisé ce code à de nombreuses reprises sans aucun soucis.
          As tu un problème au niveau du front office ou du back-office ?

          Si le problème est en front, pour l’affichage des projets, as tu un message d’erreur php ou rien ne s’affiche ?

  6. Bonjour, j’ai le même ‘soucis’ que Julie, ça m’affiche un Parse error: ‘syntax error, unexpected $end’ lorsque je souhaite utiliser le code de page-projets.php. Je suis bien sous 3.2

    Mais après avoir réfléchi 5 minutes, c’est juste que ta portion de code ne comprend pas le endwhile; de ta loop ().

    Bref, ça marche comme une rolex, merci bien ;)

    1. Tim

      Salut! Tu pourrai me dire où tu a mis le endwhile; dans le code stp parce que je trouve pas et ça me répète le même projet X fois…
      Merci!

  7. Bonjour,

    j’ai un petit soucis qui me reste encore. Tout le code fonctionne bien et j’arrive à créer catégories, nouvelle article…

    Mais lorsque je clic après l’avoir récupéré sur un des liens des articles créer avec ce dernier module et il ne me trouve pas la page.

    Pourtant j’ai bien crée la page single-apps.php (pour moi c’est pas projet mais apps).

    Qu’elle ligne défini le fichier qui affichera nos articles ? Rien à faire je ne trouve pas.

    D’avance merci de votre aide

  8. Désolé pour le double post.

    En fait mon fichier single-apps.php se charge bien mais à une condition. Mettre les permaliens par défaut exemple :

    http://localhost/?app=test-article

    Par contre si j’essaye avec des liens rewrite cela m’affiche une erreur 404.

    Après recherche sur google cela arrive souvent ce genre d’erreur.

    Auriez-vous une idée pour que la réécriture d’url (rewrite) fonctionne avec custom_post_type ?

    Encore merci

    1. Bonjour Alex,

      En effet il arrive souvent d’avoir des erreurs 404 avec les custom post type.

      As tu essayé la structure permalien sous cette forme : /%category%/%postname% ?

      As tu une page qui a pour slug(identifiant)le mot apps de la même forme que ton custom post type ? Cela peut provoquer des conflits ( voir ce post)

      Sinon le fait de travailler en local peut poser aussi des problèmes.

      Bon courage.

  9. Bonjour,

    je voudrais juste comprendre à quoi servent ces 2 lignes de codes dans page-projets.php : (pour le reste j’ai compris):

    $temp_query = $wp_query;
    $paged = (get_query_var(‘paged’)) ? get_query_var(‘paged’) : 1;

    Merci par avance !

    1. $temp_query = $wp_query; //on stock la requête dans une autre variable pour éviter les éventuelles conflits.

      $paged = (get_query_var(‘paged’)) ? get_query_var(‘paged’) : 1; //on récupère la valeur de la pagination (page 2-3-.. ?) si la variable est vide alors on attribut la valeur 1;

      1. Merci pour ta réponse.

        J’ai une autre question : dès que j’active le fichier functions.php avec ton bout de code pour les CPT, mon admin plante et j’ai le droit à une page blanche…
        Que faire ?

        1. on parle bien du fichier functions.php de ton thème ?

          Il faut que tu vérifies si tu possèdes bien une version wordpress 3 ou supérieur, que les balises PHP sont bien refermées à chaque ouverture, pour les accolades aussi.

          Si cela ne résous pas ton problème envoi moi tes coordonnées email par ma page contact afin de m’envoyer ton fichier functions.php de ton thème.

  10. Bonjour et merci pour ce super tuto.
    Il m’arrive un problème au niveau du fichier page-projet.

    J’affiche bien toute les projets que j’ai créés mais ils n’en finissent plus de ce dupliquer.(page de 3km de long)

    J’ai lu quelque commentaire plus haut que la boucle n’était pas terminé.
    Malheureusement pour moi, je ne vois pas ou la fermer.

    Merci d’avance pour ton aide.

  11. après qq galère de boucles avec dupli à l’infini, c nikel ! thx :) ))

  12. bonjour ,je lis cette tuto ,mais j’ai un question :
    Est ce que je peut ajouter deux projet avec bien sur noms different sur le menu wordpress.
    par ce que lorsque que j’ajoute les deux projet ,il y a un probléme pour la fonction « admin-init »
    merci de me donnez une solution pour cette probléme

  13. Salut !
    J’ai testé ton code et pour l’affichage de la liste des projets ça marche nickel !
    Mais je n’ai pas réussi à faire fonctionner le fichier single-project.php, lorsque je clique sur un projet, il charge le template de base single.php et non single-project.php

    Meci :)

  14. Bonjour,

    J’ai essayé d’inséré le bout de code pour la partie function.php et ça me met un beau : fatal error call undefined function add_action().

    j’ai insérer le code dans wp-includesfunctions.php

    Avez vous une solution ou je me suis tromper de fichier function.php

    Merci

    1. C’est le fichier functions.php de ton thème dans wp-content/themes/[Ton_theme]/functions.php. Si il n’existe pas il suffit de le créer.

      1. super merci, ça a marché mais finalement je me suis retourné vers « Easy post types ». Sinon dans les deux cas je suis confronté a un autre problème. Comment je fais pour afficher des custome fields selon un post type donné.

        Par exemple sur ce tuto j’ai le post type projet. Dans ce dernier j’ai plusieurs champs personnalisés. J’arrive bien a afficher le champs titre mais pas les custom fields.

        ci-dessous mon code en supposant que le post type est « projet » :
        ‘projet’, ‘posts_per_page’ => 10 );
        $loop = new WP_Query( $args );
        while ( $loop->have_posts() ) : $loop->the_post();
        the_title();
        echo  »;
        the_content();
        echo  »;
        endwhile;
        ?>

        Avec cette fonction : get_post_meta($post->ID, ‘key’, true); j’arrive bien affiche la valeur d’un meta, mais le but est de lister tout les champs personnalisés selon un post type.

        Si quelqu’un pourrait me donner une solution.

        Merci

  15. Bonjour,

    J’aurais trois questions…:

    1. order by / group by – terms clients:
    Je cherche à grouper et ordonner par « clients » l’affichage de la page page-projets.php. En fait, je voudrais afficher, pour chaque client, le libellé du client suivi de la liste des projets lui étant attribués.
    … Et le top:
    2. Est-ce possible d’avoir une première page affichant chaque client, une seconde affichant les projets attribués au client sélectionné, une troisième affichant le projet sélectionné ?
    3. Est-ce possible d’ajouter une image pour chaque client ?

    Et un grand merciiiiii pour ton post!!!

  16. Bonjour, merci pour cette article, il m’a bien confirmé ce que j’avais vu sur différents sites.
    J’aurai une question, qui reste encore sans réponse. Comment pourrait on faire pour afficher une liste de custom post type, d’une catégorie spécifique, je m’explique un peu plus:
    J’ai une query post comme celle ci:

    j’aimerai ajouter une option dans ce query post: une catégorie spécifique à musique, par exemple « top-50″ ou cover.
    cette ligne de code ne fonctionne pas:
    malheureusement, « taxonomy » ne donne rien, tag_id ne fonctionne pas non plus, ni tag__in,category ou je ne sais quoi ^^
    j’ai beaucoup cherché mais je n’ai toujours rien trouvé.
    Merci d’avance!

  17. Bonjour, est-il possible d’afficher toutes les url sous la forme :
    http://nomdedomaine.fr/post-type/catégorie/nom-du-post
    Par exemple, j’ai créé un post type Tutos et une taxonomy logiciels. Le problème c’est que les tutos s’affichent sous la forme : http://nomdedomaine.fr/tutos/nom-du-tuto, sans la taxonomy, par contre, pour la taxonomy j’ai ça : http://nomdedomaine.fr/logiciels/nomdulogiciel alors que je voudrais : http://nomdedomaine.fr/tutos/logiciels/nomdulogiciel. Au final, il me faudrait juste rajouter le post-type dans l’url (y compris le post type de base : Articles).
    Merci d’avance si vous avez une réponse à mon problème !

  18. Bonsoir

    Juste pour savoir.

    Lorsque vous dites « 2)Repérer les lignes ci dessous et enlever les // : »

    //add_action(« admin_init », « admin_init »); function pour ajouter des champs personnalisés
    //add_action(‘save_post’, ‘save_custom’); function pour la sauvegarde de nos champs personnalisés

    D’accord mais si je fais ça j’aurais bien une erreur php car la phrase :
    function pour ajouter des champs personnalisés
    devrait elle aussi être en commentaire et ressembler à ceci, non ?

    //add_action(« admin_init », « admin_init »); //function pour ajouter des champs personnalisés

    et idem pour la 2eme ligne (erreurs du même genre également constatées ailleurs).

  19. Bonjour et merci pour ce tutoriel,
    Serait-il possible de relier tout ceci à une base de données (MySQL) où toutes les informations saisies par les utilisateurs d’un site serait consultable par l’admin via une page par exemple?
    Merci d’avance.

  20. Bonjour,
    je ne sais pas si cet article est encore beaucoup lu mais au cas ou :
    il y a quelques oublis de commentaires :

    function projet_module() {
    $args = array(
    ‘label’ => __(‘Projets’),
    ‘singular_label’ => __(‘Projet’),
    ‘public’ => true,
    ‘show_ui’ => true,
    ‘_builtin’ => false, // It’s a custom post type, not built in
    ‘_edit_link’ => ‘post.php?post=%d’,
    ‘capability_type’ => ‘post’,
    ‘hierarchical’ => false,
    ‘rewrite’ => array(« slug » => « projects »),
    ‘query_var’ => « projets », // This goes to the WP_Query schema
    ‘supports’ => array(‘title’, ‘editor’, ‘thumbnail’) //titre + zone de texte + champs personnalisés + miniature valeur possible : ‘title’,'editor’,'author’,'thumbnail’,'excerpt’
    );
    register_post_type( ‘projet’ , $args ); // enregistrement de l’entité projet basé sur les arguments ci-dessus
    register_taxonomy_for_object_type(‘post_tag’, ‘projet’,'show_tagcloud=1&hierarchical=true’); // ajout des mots clés pour notre custom post type
    add_action(« admin_init », « admin_init »); //function pour ajouter des champs personnalisés
    add_action(‘save_post’, ‘save_custom’); //function pour la sauvegarde de nos champs personnalisés
    }
    add_action(‘init’, ‘projet_module’);

    function admin_init(){ //initialisation des champs spécifiques
    add_meta_box(« url_projet », « Url du projet », « url_projet », « projet », « normal », « low »); //il s’agit de notre champ personnalisé qui apelera la fonction url_projet()
    }
    function url_projet(){ //La fonction qui affiche notre champs personnalisé dans ladministration
    global $post;
    $custom = get_post_custom($post->ID); // fonction pour récupérer la valeur de notre champ
    $url_projet = $custom["url_projet"][0];
    ?>
    <input size="70" type="text" value=" » name= »url_projet »/>
    ID, « url_projet », $_POST["url_projet"]); //enregistrement dans la base de données
    }

  21. zohra

    Bonjour,

    j’imagine que la question a déjà été posée, désolée…
    Mais je cherche désespérément à faire apparaitre les catégorie de mon custom post type dans les widgets. exactement comme les catégories d’articles.

    Help !!

  22. Megane

    Excellent , c’est exatement ce qu’il me fallait . Je vais tester ça ^^ , merci beaucoup