Optimizing WordPress Performance Through Permalinks (Practice)
In the first part of the article, I discussed the theoretical basics of how permalinks work in WordPress and proposed to answer the readers on how to optimize, in my opinion, the not very optimal use of permalinks. Unfortunately, I did not receive any options, and a considerable amount of time has passed, so I decided to publish my own version of how I came up with it.
Essence of the Method
Since we need to get rid of constant link generations, it is logical to generate a link and save it somewhere, and then simply "take" it from there. I decided to save it in the Database, where, as it turned out, there is even a field for this – guid. However, guid is not created specifically for this, and developers do not recommend changing guid; it is created once when a post is published and then never changes.
The field guid
of the wp_posts table is created to store a unique value - the record identifier. It is needed to identify the record in the RSS feed. The acronym GUID stands for Globally Unique Identifier. RSS parsers use this field to determine whether they should process the record or not.
That's why developers do not recommend changing this field, ever, even if your site has moved to another domain. If you change this field, your RSS readers may receive a bunch of already published materials.
But since very few people use RSS and the link to the post changes very rarely, I think we can overlook this warning and change guid, storing the permanent link there. The reasoning is that now very few people use RSS, and this link will change only if you move to another domain or change the URL structure, which happens rarely, and even if it changes, your readers will see the last 10 posts in their RSS, which they have already seen - I think it's not too scary...
The convenience of constant generation is that if for some reason our permanent link to the article changes, the generated links will always remain working (relevant), whereas the links that are recorded can become non-functional when changed. However, in practice, the links almost never change, and if we have changed the domain of the site or changed the URL structure of the articles, it is very easy to rewrite (create new) links in the database (I made a mini-plugin for that).
The field where we will write the "ready" permanent links is located in the wp_posts table (where all the records are stored) and is called guid. This field is not used anywhere - only for RSS, see above. It is designed exactly for writing ready permalinks - ready permalinks are written there sometimes, and sometimes links like http://example.com/?p=133 are written, and this happens in a somewhat random order, seemingly depending on whether the material is published before or after the first draft record. Yes, and that's not important.
Thus, in order not to constantly generate links, we need to:
- When publishing/updating a post, write the permanent link to the article in the guid field of the wp_posts table.
- When using the link in the WordPress template, do not use the get_permalink() function, but rather use the ready link: $post->guid.
Implementation
To correctly write permanent links into the guid field in the database, I made such a hack in the theme file functions.php:
add_action( 'save_post', 'guid_write', 100 ); function guid_write( $id ){ if( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) return false; if( $id = intval($id) ){ global $wpdb; $wpdb->update( $wpdb->posts, ['guid'=>/*wp_make_link_relative*/( get_permalink($id) ) ], ['ID'=>$id] ); } clean_post_cache( $post_id ); }
This hack works when a post/page is published or updated. The hack also works when publishing is done remotely via xml-rpc.
Thus, this hack should be inserted in the functions.php file of the theme for a newly created site. Then in the template, in the loops for displaying posts, instead of using:
<?php echo get_permalink() ?>
use:
<?php echo $post->guid ?>
In this case, we will simply take the ready link and display it, without any data requests, generation, or PHP calculations. The only problem is that you will have to go into the template and change all instances of:
echo get_permalinks(); echo get_permalinks( $post->ID ); the_permalink(); the_permalink( $post->ID );
to:
echo $post->guid
It is important to understand that, for example, constructions like the_permalink(25);
or the_permalink( $post_id );
, where $post_ id is set in advance as the ID of a certain post, cannot be changed to echo $post->guid, because such constructions retrieve links for a specific post, while echo $post->guid outputs a link to the post that is currently in the global variable $post.
By the way, in my display functions: displaying the latest posts, previous posts from the category, you also need to and even should replace get_permalink($pst->ID) with $pst->guid. I deliberately added the guid field to the selection in them. Once I even forgot to change it to get_permalink(), and in the comments, someone reminded me that the function is not sensitive to permalinks
For Already Functioning Sites Where the guid Field Is Already Defined "Incorrectly"
If the site is already functioning and there are already many records in it, the permanent links of which are recorded "incorrectly" in the guid field, I made a plugin for such cases to rewrite (repair) the guid field:
Download the Plugin
Install the plugin as usual: copy the file from the fix_guid.php archive to the plugins directory and activate it in the admin panel.
After the guid fields have been "repaired," the plugin can be deleted. The plugin can also properly delete post revisions (everything is deleted, including auto-saves).
Recommendations
If your URL structure does not contain the tags %category%, %tag%, %author%, there is no urgent need to use this optimization method. However, if these tags are used, then this method will have an excellent effect.
Tests
In the comments, I was "provoked" to conduct tests to see how such a method actually affects optimization. Here's what I found:
With the URL structure /%category%/%postname%, the the_permalink() function (which is also get_permalink() but without filters) takes 0.12 seconds to generate 10 links. Whereas with a URL structure like, for example, /%year%/%monthnum%/%day%/%postname%, it takes only 0.02 seconds.
I conducted measurements on my computer, where, for comparison, the main page of WordPress 3.0.1 with the default theme is generated in 1.3 seconds.
Thus, if our URL contains %category% and 50 unique (non-repeating) links are displayed on the page, it will take an additional 0.6 seconds (0.12*5=0.6) to generate that page, almost half a second.
It should be noted (I didn't know this before) that after generating a link once, WordPress caches it and when the_permalink() is called again for the same post, the link is generated in a fraction of a second. I mean this:
//get the link for post with ID 25 the_permalink(25); //time 0.012 //get the link again the_permalink(25); //time, approximately, 0.0001
It seems like I've said everything I wanted, everything else can easily be clarified in the comments