I'm migrating a Joomla! database to Wordpress and the website has to remain exact regarding URLs. The Joomla site has its posts with .html extensions, and the importer I created maps the Joomla file URL to the Wordpress post_name as such:

joomla-site.com/Title-of-Joomla-Content.html -> Wordpress DB::post_name title-of-joomla-content

I can access right-out-of-the-box the post on the Wordpress install by of course: wordpress-site.com/Title-of-Joomla-Content

But I need to change how the permalink system responds. I don't want to use a redirect (which shows in headers), so I'm trying to hook in a function that will select the post ID differently if the URL ends with .html.

Since Wordpress only is activated when a file is not found, real .html files are unaffected. So having a blanket check and change function for any .html files isn't a problem.

I've attempted this:

function custom_redirect() {
 global $post_id,$wpdb;
 if (substr($_SERVER['REQUEST_URI'],-5) == '.html') {
    $check = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name=%s AND post_status = 'publish'",substr(basename($_SERVER['REQUEST_URI']),0,-5)));
    if ($check > 0) $post_id = $check;
    // Need to set the post ID for the wp_query here.

if (!is_admin()) add_action( 'init', 'custom_redirect' );

The above code correctly selects the post ID correctly, but I'm not sure what function or hook to use to force the post (single.php) to display it.

I was able to use the following to set the post ID for every archive.php run, but this doesn't affect the single.php file which simply calls the function the_post.

function force_ID($query) {
 $query->set('post_id', '96');

I have a feeling it might be something simple like changing a global instance of $wp_query, but I'm not sure the best way to do this. Using an init hook probably is too high in the order of execution too.

1 Answer 1


I figured it out, here is the solution for anyone else wondering how to do something like this:

function force_ID($query) {
 global $wpdb;
 if (substr($_SERVER['REQUEST_URI'],-5) == '.html') {
    $post_id = $wpdb->get_var($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_name=%s AND post_status = 'publish'",substr(basename($_SERVER['REQUEST_URI']),0,-5)));
    if ($post_id > 0) $query->set('page_id',$post_id);

In examining the wp-includes/query.php file, I noticed that the object accepts page_id to exclusively select an ID. Using post_id worked for archive post loops, but page_id worked for a single post call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.