WordPress - request post by url with custom field

2019-07-27 11:52发布

I have an URL like this: example.com/movies/157336/Interstellar

For reference: example.com/movies/%movie_id%/%movie_name%

Please note, the movie_id is a custom field, and not the actual post ID. The movie_name is the post title slug, but is only there for SEO reasons.

I need WordPress to load the page based on the custom field movie_id found in the URL and not use the page name, and if the movie_id is not found, throw the regular 404 error.

The main problem I am having, is that I can’t seem to get WordPress to load a page based on the custom field movie_id from the URL, it always uses movie_name as reference point.

How do I know that? Well the correct URL would be example.com/movies/157336/Interstellar and if I change the title to example.com/movies/157336/Intersterlarxyz then WordPress gives a 404 error. And if I change the ID but leave the movie name correct, like this: example.com/movies/123/Interstellar then WordPress still loads the correct page.

Based on this behavior, it's safe to say WordPress loads the page based on the page slug from the URL, rather than the movie ID, and that is what I need to fix.

Here is my code so far:

movie-plugin.php

// Register Custom Post Type "movies"
function register_moviedb_post_type() {
  register_post_type( 'movies',
    array(
            'labels' => array(
                'name' => __( 'Movies' ),
                'singular_name' => __( 'Movies' )
            ),
            'taxonomies' => array('category'), 
            'public' => true,
            'has_archive' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => array('slug' => 'movies','with_front' => FALSE),
            'supports' => array( 'title', 'editor', 'custom-fields','comments','page-attributes','trackbacks','revisions', 'thumbnail')
    )
  );
  flush_rewrite_rules();
}
add_action( 'init', 'register_moviedb_post_type' );


// Add custom rewrite tag 'movie_id'
function custom_rewrite_tag() {
  add_rewrite_tag('%movie_id%', '([^/]+)', 'movie_id=');
}
add_action('init', 'custom_rewrite_tag');


// Add rewrite rule
function custom_rewrite_basic() {
  add_rewrite_rule(
            '^movies/([^/]*)/([^/]*)/?',
            //'index.php?post_type=movies&movie_id=$matches[1]',
            'index.php?post_type=movies&movie_id=$matches[1]&name=$matches[2]',
            'top'
        );
}
add_action('init', 'custom_rewrite_basic');


// Query var 'movie_id'
function add_query_vars_filter( $vars ){
  $vars[] = "movie_id";
  return $vars;
}
add_filter( 'query_vars', 'add_query_vars_filter' );


// Custom Page Template
function custom_movie_page_template() {
    if ( is_singular( 'movies' ) ) {
        add_filter( 'template_include', function() {
            return plugin_dir_path( __FILE__ ) . '/movies.php';
        });
    }
}
add_action( 'template_redirect', 'custom_movie_page_template' );

// Create custom post type link for movies
function movie_post_type_link( $link, $post = 0 ){
    if ( $post->post_type == 'movies' ){

            $id = $post->ID;
            $post = &get_post($id);
            $movie_id = get_post_meta($post->ID,'movie_id', true);

            empty ( $post->slug )
            and $post->slug = sanitize_title_with_dashes( $post->post_title );
            return home_url(
           user_trailingslashit( "movies/$movie_id/$post->slug" )
        );
    } else {
        return $link;
    }
}
add_filter( 'post_type_link', movie_post_type_link, 1, 2 );

If I remove the movie_name from the URL in add_rewrite_rule, WordPress just loads the archive page of that post type. 'index.php?post_type=movies&movie_id=$matches[1]',

If I use the page name in the URL rewrite, it always loads the page based on the name, rather than the movie_id. 'index.php?post_type=movies&movie_id=$matches[1]&name=$matches[2]',

标签: php wordpress
1条回答
一纸荒年 Trace。
2楼-- · 2019-07-27 12:28

I didn't test code below, but movies.php could be like this:

<?php $movieId = (int)get_query_var('movie_id') ;
if(movieId ==! 0):

    $args = array(
        'post_type' => 'movies',
        'posts_per_page' => 1,
        'meta_key'      => 'movie_id',
        'meta_value'    => $movieId
    );

    $the_query = new WP_Query( $args );

    if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
    //code that display data
    <?php endwhile; else : ?>
    //code to create post
    <?php endif;
else:
//normal loop
endif;
查看更多
登录 后发表回答