What you’re asking is a generic (My)SQL question, but anyway, as I already said in my comment, if the post title is always in the form of TM.74.G.<number>
like TM.74.G.358
and TM.74.G.1000
, then you can use the SUBSTRING()
function in MySQL/MariaDB to firstly extract the <number>
value (e.g. 358
) and then sort the posts by that number.
So in your filter function, just replace the return
part with:
return "SUBSTRING( wp_posts.post_title, 9 ) + 0 ASC";
Now here’s something specific to WordPress: You should conditionally apply your filter because posts_orderby
is run on many pages like category archive pages, search results pages, single post pages, etc., including on the admin side, e.g. the “Posts” page (e.g. at wp-admin/edit.php
), so you wouldn’t want to mess with the posts’ sorting on those pages, right?
Secondly, instead of hard-coding the table prefix (which defaults to wp_
), you should use $wpdb->prefix
like so {$wpdb->prefix}posts
, but for core tables, they are actually available as public properties in the wpdb
class, so for example the posts table, you could use $wpdb->posts
to reference that table.
global $wpdb; // don't forget to declare the $wpdb global
return "SUBSTRING( $wpdb->posts.post_title, 9 ) + 0 ASC";
And here’s an example of how can you conditionally apply your filter:
add_filter( 'posts_orderby', 'my_posts_orderby', 10, 2 );
// **Replace "foo" with the correct post type.
function my_posts_orderby( $orderby, $query ) {
// Check if it's *not* the main query (which runs automatically on page load).
// And if it's not, then do nothing.
if ( ! $query->is_main_query() ) {
return $orderby; // always return it :D
}
// 1. Apply the filter if we're on the "foo" post type archive.
if ( ! is_admin() && is_post_type_archive( 'foo' ) ) {
global $wpdb;
return "SUBSTRING( $wpdb->posts.post_title, 9 ) + 0 ASC";
}
// 2. Or if we're on the admin page for managing the CPT's posts.
if ( is_admin() && 'edit-foo' === get_current_screen()->id ) {
global $wpdb;
return "SUBSTRING( $wpdb->posts.post_title, 9 ) + 0 ASC";
}
return $orderby;
}