[AUTOMATIQUE] Cet article a plus de 5 ans.
Il se peut donc que les informations qu'il fournit ne soient plus totalement exactes.

Lorsque je travaillais sur mon autre site (Gumdust), j’ai eu besoin de remonter les infos d’un post grâce à son URL.

Après quelques recherches, j’ai trouvé la fonction url_to_postid, mais cette dernière ne permet pas de remonter l’ID d’un Custom Post Type (CPT) grâce à son URL. Elle fonctionne seulement avec « post » et « page ».

Il a donc fallu chercher une fonction similaire, mais qui prenait en compte mes CPT.

Voici un exemple de ce que la fonction ci-dessous m’a permit de mettre en place sur Gumdust : DAT EVO X | Stance Nation.

Vous pouvez voir dans la description de la vidéo qu’il y a un petit cartouche à droite avec un titre, un lien, différentes infos et une image.

Voilà comment ça fonctionne :
– un utilisateur publie une vidéo et ajoute une description qui contient un lien pointant vers une page interne du site.
– la fonction si dessous permet de remonter un ID à partir d’un lien interne, on récupère donc un ID de post.
– on créer ensuite une fonction pour générer le cartouche et remonter les différentes infos du post grâce à son ID.
– on ajoute un filtre pour insérer ce cartouche dans the_content.
– et voilà !

Il s’agit bien évidemment d’un exemple comme un autre, mais si vous avez d’autres idées d’applications intéressantes, n’hésitez pas à les partager, et peut être qu’on pourra en faire un plugin lors d’un prochain tuto 😉

Voici donc la fonction qui permet cette « prouesse » : (j’ai fait ma feignasse, je n’ai pas traduit les commentaires…)

function bw_url_to_postid($url){
    global $wp_rewrite;

    $url = apply_filters('url_to_postid', $url);

    // First, check to see if there is a 'p=N' or 'page_id=N' to match against
    if ( preg_match('#[?&](p|page_id|attachment_id)=(\d+)#', $url, $values) )   {
        $id = absint($values[2]);
        if ( $id )
            return $id;
    }

    // Check to see if we are using rewrite rules
    $rewrite = $wp_rewrite->wp_rewrite_rules();

    // Not using rewrite rules, and 'p=N' and 'page_id=N' methods failed, so we're out of options
    if ( empty($rewrite) )
        return 0;

    // Get rid of the #anchor
    $url_split = explode('#', $url);
    $url = $url_split[0];

    // Get rid of URL ?query=string
    $url_split = explode('?', $url);
    $url = $url_split[0];

    // Add 'www.' if it is absent and should be there
    if ( false !== strpos(home_url(), '://www.') && false === strpos($url, '://www.') )
        $url = str_replace('://', '://www.', $url);

    // Strip 'www.' if it is present and shouldn't be
    if ( false === strpos(home_url(), '://www.') )
        $url = str_replace('://www.', '://', $url);

    // Strip 'index.php/' if we're not using path info permalinks
    if ( !$wp_rewrite->using_index_permalinks() )
        $url = str_replace('index.php/', '', $url);

    if ( false !== strpos($url, home_url()) ) {
        // Chop off http://domain.com
        $url = str_replace(home_url(), '', $url);
    } else {
        // Chop off /path/to/blog
        $home_path = parse_url(home_url());
        $home_path = isset( $home_path['path'] ) ? $home_path['path'] : '' ;
        $url = str_replace($home_path, '', $url);
    }

    // Trim leading and lagging slashes
    $url = trim($url, '/');

    $request = $url;
    // Look for matches.
    $request_match = $request;
    foreach ( (array)$rewrite as $match => $query) {
        // If the requesting file is the anchor of the match, prepend it
        // to the path info.
        if ( !empty($url) && ($url != $request) && (strpos($match, $url) === 0) )
            $request_match = $url . '/' . $request;

        if ( preg_match("!^$match!", $request_match, $matches) ) {
            // Got a match.
            // Trim the query of everything up to the '?'.
            $query = preg_replace("!^.+\?!", '', $query);

            // Substitute the substring matches into the query.
            $query = addslashes(WP_MatchesMapRegex::apply($query, $matches));

            // Filter out non-public query vars
            global $wp;
            parse_str($query, $query_vars);
            $query = array();
            foreach ( (array) $query_vars as $key => $value ) {
                if ( in_array($key, $wp->public_query_vars) )
                    $query[$key] = $value;
            }

			// Taken from class-wp.php
			foreach ( $GLOBALS['wp_post_types'] as $post_type => $t )
				if ( $t->query_var )
					$post_type_query_vars[$t->query_var] = $post_type;

			foreach ( $wp->public_query_vars as $wpvar ) {
				if ( isset( $wp->extra_query_vars[$wpvar] ) )
					$query[$wpvar] = $wp->extra_query_vars[$wpvar];
				elseif ( isset( $_POST[$wpvar] ) )
					$query[$wpvar] = $_POST[$wpvar];
				elseif ( isset( $_GET[$wpvar] ) )
					$query[$wpvar] = $_GET[$wpvar];
				elseif ( isset( $query_vars[$wpvar] ) )
					$query[$wpvar] = $query_vars[$wpvar];

				if ( !empty( $query[$wpvar] ) ) {
					if ( ! is_array( $query[$wpvar] ) ) {
						$query[$wpvar] = (string) $query[$wpvar];
					} else {
						foreach ( $query[$wpvar] as $vkey => $v ) {
							if ( !is_object( $v ) ) {
								$query[$wpvar][$vkey] = (string) $v;
							}
						}
					}

					if ( isset($post_type_query_vars[$wpvar] ) ) {
						$query['post_type'] = $post_type_query_vars[$wpvar];
						$query['name'] = $query[$wpvar];
					}
				}
			}

            // Do the query
            $query = new WP_Query($query);
            if ( !empty($query->posts) && $query->is_singular)
                return $query->post->ID;
            else
                return 0;
        }
    }
    return 0;
}

Puis pour utiliser cette fonction qui n’a qu’un paramètre (l’URL de la page recherchée), il vous suffit de faire ceci :

<?php $postid = bw_url_to_postid( $url ); ?>

A noter, que si l’URL ne correspond à aucune page de votre site, et qu’elle ne retrouve donc aucun ID, elle retournera 0.

Cette fonction est (à priori) un peu gourmande en ressources, elle est donc à utiliser avec parcimonie (c’est qui celui là ?).

Arpès avoir rédigé cet article, j’ai à nouveau fait une petite recherche et je me suis rendu compte que la fonction url_to_postid qui existe depuis la création de WordPress (1.0.0), est désormais compatible avec les CTP… (depuis la version 3.7)

En somme, vous n’êtes pas obligé d’utiliser la fonction présentée plus haut, sauf si vous souhaiter la customiser.
Pour utiliser url_to_postid, il vous suffit de faire comme ceci :

<?php $postid = url_to_postid( $url ); ?>

Article rédigé parBrice CAPOBIANCO

Autodidacte passionné par WordPress. J'aime apprendre et créer pour ensuite partager !

Coorganisateur des Meetups WordPress Rennes et fondateur de bweb.
Partager cet article

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *