First things first... Why it doesn't work?
Your code doesn't work, because you use WP API incorrectly...
Method set
takes exactly two arguments:
set( $query_var, $value )
Set a named query variable to a specific
value.
So how do you use it in your code?
$query->set( get_terms( array(
'taxonomy' => 'cat_publications',
'orderby',
'slug'
) ) );
There is only one argument (so it's $query_var
- name of variable) and you pass get_terms
result in there...
So what is that function doing? It retrieves the terms in a given taxonomy or list of taxonomies (and it returns a list of terms).
OK, so basically your current code is creating some custom query variable with name set to array containing terms and no value.
So it should be pretty clear right now, why this code doesn't do what you want it to...
So how to order posts by terms using WP_Query?
Let's take a look at Order & Orderby Parameters. As you can see, you can order by many properties, but... Terms are not among these properties.
This is caused by database structure - ordering posts by terms wouldn't be efficient and it is so rare, that there is no point in implementing it.
So how to do it? You can't - there is no way to use WP_Query to order posts by terms. It doesn't matter if you create your own WP_Query
loop, or if you use pre_get_posts
(as you do) to modify global $wp_query
instance...
So is it really impossible?
No, of course it is possible. You can always take control over raw SQL that given WP_Query is creating and modify it.
cenk posted an example of such query in his answer here: https://wordpress.stackexchange.com/a/136825/34172
Of course you don't have to use it as raw query. You can use posts_clauses
filter to add missing SQL parts to the query generated by your WP_Query.
But it won't be efficient and it won't be easy to implement it correctly. There are many boundary conditions and many things can go wrong (what if some posts have multiple terms, etc.)
And you can also cheat a little bit
WP_Query can order posts by meta value. So you can store term name as meta value with save_post hook and then sort posts by this meta value...
$query->set(get_terms(array(...
makes no sense at all. This method assumes first param is name of field and second is new value - you pass only one value - list of terms...