Background
I'm building a course catalog for a school and am trying to make friendly, dynamic URLs. It has three custom post types:
catalog.
course. This post type contains a title, course number, and course description.
section. This post type contains a cost, start and end dates and times, etc. A section is an instance of a course; for example, there might be two sections of Drawing for Beginners, one on Thursday morning and one on Monday night and taught by two different faculty.
There is a one-to-many relationship between course and section. When viewing a section, it displays the parent course's course name, course number, and course description. It also displays that section's cost, start and end dates and times, etc.
The current URL for a section is this:
http://website.org/section/section-slug/
I would like it to be this:
http://website.org/class/spring-2019/drawing-for-beginners/01/
...where "class" is a 'virtual' folder / synthetic prefix
...where "spring-2019" corresponds to a "catalog" custom post type
...where "drawing-for-beginners" corresponds to a slug for the parent "course" custom post type
...where "01" corresponds to the section of the course.
WordPress should display the section post type that matches these criteria.
Research
I've read quite a bit about both the Rewrite API and the Endpoints API. The best article I could find on a topic closest to what I'm trying to accomplish is this one. Sadly, the example code on the page didn't work for me, resulting in a "too many redirects error." I can provide more details about exactly which portion didn't work, if desired. I also read this article on Make WordPress Plugins but it doesn't cover dynamic lookups.
What I'm trying to accomplish
http://website.org/class/spring-2019/drawing-for-beginners/01/
When the virtual URL is supplied to WordPress, I need the system to perform a query to look up the section whose number is "01" and which belongs to the "spring-2019" catalog and whose parent course has a slug of "drawing-for-beginners." That query isn't a challenge, it's all of the hooks that need to be called to execute that code and return the correct template (for the section page). I'm not sure whether I need to create an Endpoint or can just get away with adding rewrite rules.
Can someone offer some guidance?
--
As a "bonus," I'm also trying to accomplish this:
http://website.org/class/spring-2019/drawing-for-beginners/01/faculty_name
...where "faculty_name" is dynamic and is the name of the person teaching that section (and corresponds to a "faculty" custom post type).
http://website.org/class/spring-2019/drawing-for-beginners/01/gallery
...where "gallery" is a static name and shows a gallery custom post type.
After much investigation, I've found an answer to my question. Here it goes.
This is how to create truly dynamic URLs / slugs in WordPress. The URLs don't correspond to a page. Instead, the parts of the slug are used to look up a post ID and then render that post accordingly.
Step 1: Add the rewrite rule
function pce_rewrite_rules ( ) {
add_rewrite_rule ( '^class/([^/]*)/([^/]*)/([^/]*)/?', 'index.php?post_type=section&catalog_name=$matches[1]&course_name=$matches[2]§ion_no=$matches[3]','top' ) ;
add_action ( 'init', 'pce_rewrite_rules', 10, 0 ) ;
Step 2: Register the query variables
function pce_register_query_vars ( $vars ) {
$vars[] = 'course_name';
$vars[] = 'catalog_name';
$vars[] = 'section_no';
return $vars;
}
add_filter ( 'query_vars', 'pce_register_query_vars' );
Step 3: Modify the WP query
Use pre_get_posts to modify the main query. But you have to force some variables in the query so that WordPress loads the template that you need. To find the variables I needed to manually set, I used a WP plugin (Query Monitor) to examine the contents of the WP query, and I used var_dump on the type of post I wanted to "copy."
function pce_dynamic_section_lookup ( $wp ) {
if ( is_admin() || ! $wp->is_main_query() ){
return;
}
if ( $wp->is_main_query() ) {
// Only defined if we're looking at a "fake" URL.
// Example: http://pce.local/class/spring-2019/handmade-books/01/
if ( get_query_var ('course_name' ) ) {
// These are some of the variables I needed to set manually.
$wp->query_vars['post_type'] = 'section' ;
$wp->query_vars['is_single'] = true ;
$wp->query_vars['is_singular'] = true;
$wp->query_vars['is_archive'] = false;
$course_name = get_query_var ('course_name' ) ;
$catalog_name = get_query_var ('catalog_name' ) ;
$section_no = get_query_var ('section_no' ) ;
// More code is here to look up the post ID I need.
// Set the post ID here. This makes the magic happen.
$wp->query_vars['p'] = $post_id ;
// This also makes the magic happen. It forces the template I need to be selected.
$wp->is_single = true ;
$wp->is_singular = true ;
$wp->is_archive = false ;
$wp->is_post_type_archive = false ;
}
}
}
add_action ( 'pre_get_posts', 'pce_dynamic_section_lookup', 0, 2 ) ;
I had a post with this original URL:
http://pce.local/section/handmade-books-01/
And now I can load it at this URL (and it loads it, it does not forward it):
http://pce.local/class/spring-2019/handmade-books/01/
I needed to do this because multiple sections are going to be added in future catalogs and I wanted to keep the URLs friendly. In the summer if the class is offered, it will be...
http://pce.local/class/summer-2019/handmade-books/01/
Instead of...
http://pce.local/section/handmade-books-01-2/
or whatever slug WordPress assigns it. Having only a couple of sections isn't a big deal, but there will be several in the future.
If i understood good, this might help you.
I am not sure how did you make relationship but i will put the code that i usually use. And lets say that catalog-course also have a relationship.
function add_rewrite_rules( $wp_rewrite )
{
$section_rules = array(
'class/(.+?)/?$' => 'index.php?post_type=post&name='. $wp_rewrite->preg_index(1),
);
$wp_rewrite->rules = $section_rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'add_rewrite_rules');
function change_section_links($post_link, $id=0){
$courses = new WP_Query( array(
'post_type' => 'course',
'post__in' => get_post_meta( $catalog_id, '_course', true ),
) );
if ( $courses-> have_posts() ) { while ( $courses->have_posts() ) {
$courses->the_post();
$catalog_name = get_the_title();
}
$sections = new WP_Query( array(
'post_type' => 'section',
'post__in' => get_post_meta( $course_id, '_section', true ),
) );
if ( $sections-> have_posts() ) { while ( $sections->have_posts() ) {
$sections->the_post();
$course_name = get_the_title();
}
$post = get_post($id);
if( is_object($post) && $post->post_type == 'section'){
return home_url('/class/'. $catalog_name. '/'. $course_name. '/'. $post->post_name.'/');
}
return $post_link;
}
add_filter('post_link', 'change_section_links', 1, 3);
I hope that it would help you. If it doesnt, tell me how did you make relationship.
Related
I've been searching for examples of this online and through the WP documentation on filters but I can't find a suitable hook, so apologies for posting a question without a good example of what I'm trying to do!
When you add a link to text or to a button in the editor, you can search for the page/post you want to link to. What you can't search for is a post type archive link.
I want to be able to type the name of a post type into the search box (pictured below), and include the post type archive link in the search results. In this example, I have a post type called members that I'd like to link to.
I find the need to do this a lot, and I always end up just typing /post-type-link into the box and leaving it at that, but I don't think this is an elegant solution and is clunky for users.
I have tried to write some code, but I don't believe I have the right hook:
function include_cpt_search( $query ) {
if ( is_admin() && is_single() ) {
$query->set( 'post_type', array( 'services' ) );
}
return $query;
}
add_filter( 'pre_get_posts', 'include_cpt_search' );
Has anyone done this before? Know of a filter or hook I could work with? Anything really!
The Link format in the RichText toolbar uses the Search REST API endpoint at /wp/v2/search, so although that endpoint doesn't provide a specialized hook for filtering the response, you can use rest_post_dispatch to add custom links to the search results returned via /wp/v2/search.
So in the examples below, I'm checking if the route is /wp/v2/search and if so, then we add the (custom) post type's archive link. Also note that, you should provide an array with the items mentioned here (the LinkControl component used by the Link format).
Basic Example
Includes only the (i.e. one) post type whereby its name matched exactly the search keyword.
add_filter( 'rest_post_dispatch', 'so_62472641', 10, 3 );
function so_62472641( $response, $server, $request ) {
// Don't modify the data if the REST API route is not /wp/v2/search
if ( 'post' !== $request->get_param( 'type' ) ||
'/wp/v2/search' !== $request->get_route() ) {
return $response;
}
// Let's see if there's a post type that matched the search keyword.
$search = $request->get_param( 'search' );
if ( ! $post_type = get_post_type_object( $search ) ) {
return $response;
}
// Now add the post type archive URL, if any, to the response data.
if ( $url = get_post_type_archive_link( $search ) ) {
$data = (array) $response->get_data();
$data[] = [
'id' => 'post_type-' . $search,
'type' => 'Post Type Archive',
'title' => $post_type->label,
'url' => $url,
];
$response->set_data( $data );
}
return $response;
}
Extended Example
Includes all post types whereby the name/label matched the search keyword.
add_filter( 'rest_post_dispatch', 'so_62472641', 10, 3 );
function so_62472641( $response, $server, $request ) {
// Don't modify the data if the REST API route is not /wp/v2/search
if ( 'post' !== $request->get_param( 'type' ) ||
'/wp/v2/search' !== $request->get_route() ) {
return $response;
}
$search = $request->get_param( 'search' );
$post_types = get_post_types( [], 'objects' );
$extra_data = [];
// Let's see if there's a post type that matched the search keyword.
foreach ( $post_types as $obj ) {
if ( $search === $obj->name ||
// look for the search keyword in the post type name/slug and labels (plural & singular)
false !== stripos( "{$obj->name} {$obj->label} {$obj->labels->singular_name}", $search )
) {
if ( $url = get_post_type_archive_link( $obj->name ) ) {
$extra_data[] = [
'id' => 'post_type-' . $obj->name,
'type' => 'Post Type Archive',
'title' => $obj->label,
'url' => $url,
];
}
}
}
// Now add the post type archive links, if any, to the response data.
if ( ! empty( $extra_data ) ) {
$response->set_data( array_merge( (array) $response->get_data(), $extra_data ) );
}
return $response;
}
Sample Output (for the second example above)
Note: The above is a screenshot of a real response, but I deliberately (via PHP) changed the domain name to example.com (i.e. the actual domain name is different).
And the examples were both tried & tested working on WordPress 5.5.1 (latest release as of writing). Also, you can exclude the default post post type, if you want to.
Additional Notes
It should be noted that the examples do not take into account the pagination, which means, if there were 10 post types that matched the search keyword, then they would always be included in the response (on page 1, 2, 3, etc.). So you might want to just use the first example because at least it always includes at most 1 post type only. However, with the second example, you can actually limit the $extra_data to, say, 5 items (per page - but it's up to you on how to distribute the items per page).
You can also use a custom search handler class, e.g. one that extends the default class (WP_REST_Post_Search_Handler) and use the wp_rest_search_handlers hook to add your class to the list. Here's a very basic example...
In your-class.php:
class My_WP_REST_Post_Search_Handler extends WP_REST_Post_Search_Handler {
// ... you'll need to actually write the code on your own..
}
return new My_WP_REST_Post_Search_Handler;
In the theme's functions.php file or somewhere in your plugin:
add_filter( 'wp_rest_search_handlers', 'my_wp_rest_search_handlers' );
function my_wp_rest_search_handlers( $search_handlers ) {
$search_handlers[] = include_once '/path/to/the/your-class.php';
return $search_handlers;
}
I've googled around for this like crazy, but can't seem to find a not too outdated answer for this question or something that actually works.
My problem is just like the one this guy describes on this forum post (from 4, holy FOUR years ago!):
https://wordpress.org/support/topic/duplicate-subcategory-slug-problem
I'm currently using the latest version, Wordpress 4.1 and what I'm trying to achieve is this:
Let's say I have 2 categories on my website, which are called Boots and Shoes.
Inside both of them, I want to make a category named Red. That's how my category structure would look like then:
- Boots // -> URL: http://example.com/boots
| ----- Red // -> URL: http://example.com/boots/red (GREAT!)
- Shoes // -> URL: http://example.com/shoes
| ----- Red // -> URL: http://example.com/shoes/red-shoes (cmon, wp, nooo !)
When what I'd like to achieve, is this:
- Boots // -> URL: http://example.com/boots
| ----- Red // -> URL: http://example.com/boots/red
- Shoes // -> URL: http://example.com/shoes
| ----- Red // -> URL: http://example.com/shoes/red
This way would be perfect !!!
In case you're wondering, yes, I know that's just part of wordpress and they don't want that to be changed, I understand why and all that jazz, yeah.
But for this particular project, I really need this.
I guess I'll probably have to alter the core, not being able to update Wordpress if I do so, I know, but I have no problem with that if I need to.
But if there's another way to make up this hierarchy that doesn't involve categories and doesn't break my URIs, I can try that too. Any help or tip is appreciated guys, thank you very much !
I've had the same problem with my taxonomies and I've just fixed it, hope it helps.
First, you have your parents taxonomies and when you create the children you must be sure that the parent slug is added to the subcategorie slug. In your example it would look like:
boots-red
boots-blue
shoes-red
shoes-blue
This is to have a unique slug for each subcategory.
Now the important thing, the rewrite rules and and taxonomy links:
When you define the taxonomy, you should do this way:
register_taxonomy('mytaxonomy',array('mycustompost'), array(
'hierarchical' => true,
'sort' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array(
'slug' => '/%parent%'
)
));
Also, you have to modify the permalinks so it has the structure that you need, if its a custom taxonomy (as my case) you do it with the term_link filter. My function looks like this:
function mytaxonomy_link( $permalink, $term, $taxonomy )
{
if ( $taxonomy !== 'mytaxonomy' && false === strpos( $permalink, '%parent%' ) )
return $permalink;
$temp_padre = $term->parent;
$padre = get_term_by('id', $temp_padre, 'mytaxonomy');
$cat_name = 'general';
if(isset($padre) && !empty($padre))
{
$cat_name = $padre->slug;
$termslug = $term->slug;
$new_slug = str_replace( $cat_name , '' , $termslug);
$new_slug = ltrim($new_slug, '-');
$permalink = str_replace( '%parent%' , $cat_name , $permalink );
$permalink = str_replace( $termslug , $new_slug , $permalink );
}
return $permalink;
}
add_filter( 'term_link', 'mytaxonomy_link', 10, 3 );
This function will transform the subcategory link into: http://example.com/boots/red
And the rewrite rule that makes all the magic:
add_rewrite_rule('([^/]+)/([^/]+)/?$', 'index.php?mytaxonomy=$matches[1]-$matches[2]','top');
add_rewrite_rule('([^/]+)/([^/]+)', 'index.php?mytaxonomy=$matches[1]-$matches[2]','top');
In my case my posts / taxonomies relation was much more complicated but I think that this solution will help you.
Hope this helps because I've had a really awful time trying to get to the solution for this problem.
If your subcategory structure doesn't go deeper than shoes/red (not shoes/red/hiking for instance), you can use permalink endpoints to simulate categories. Permalink endpoints are rewritten from domain.com/request/url/?endpoint.
After each color or similar is set as an endpoint to EP_CATEGORY, category URLs can be suffixed with /red, /blue and so on. Applying the endpoints to EP_ALL_ARCHIVES allows the endpoints on CPT and date archives too.
Then in a filter or action such as template_include you can read the appended endpoint using the global $wp_query object and filter the category items accordingly.
If a user enters another suffix to the URL (e.g. /red/hiking), $wp_query will recognize them as a key/value pair as red => hiking (?red=hiking as a raw query string) in the query variables ($wp_query -> get( 'red' ); returns hiking). This might be a good or a bad thing depending on how you implement the logic.
After you add permalink endpoints, you need to flush your installation's rewrite rules either using the function flush_rewrite_rules() or by going to the admin panel permalinks management section and pressing update once.
Note: You can't use dynamic names for endpoints. You need to define a static endpoint for each variant (red, blue, etc.).
In every problem there is the proper way to solve it, and any other indirect way...
It took me two days to figure this out in the proper way, so I'll add it here for anyone else that may need it in the future.
add_filter('wp_unique_term_slug', 'prevent_cat_suffix', 10, 3);
function prevent_cat_suffix($slug, $term, $original_slug)
{
if ($term->post_type == 'product' && $term->parent !== 0) {
return $original_slug;
}
return $slug;
}
As you can see in the code, I've narrowed it down to products only, but you can make it suitable for any other post type also by removing the $term->post_type == 'product' && in the code above.
I am using Wordpress auto suggests using this snippet of code
and currently it is searching all tags, I want it to search only post titles. Any help is appreciated.
This is sql query calling all the tags which needs to be modified for all posts.
<?php global $wpdb;
$search_tags = $wpdb->get_results("SELECT name from wp_terms WHERE name LIKE '$search%'");
foreach ($search_tags as $mytag)
{
echo $mytag->name. " ";
}
?>
These days i had to do some request in a wordpress theme.
In your case ( getting title can be done easier than getting tags, as in your example link ) the stuff can be done easier (i guess).
Firstly you have to make a php page to get posts. As you maybe know you won't be able to use wp stuff in standalone php files, so your file ( let call it get_posts.php ) will look like
<?php
// Include the file above for being able to use php stuff
// In my case this file was in a folder inside my theme ( my_theme/custom_stuff/get_posts.php ).
// According to this file position you can modify below path to achieve wp-blog-header.php from wp root folder
include( '../../../../wp-blog-header.php' );
// Get all published posts.
$list_posts = get_posts( array( 'numberposts' => -1 ) );
// Get "q" parameter from plugin
$typing = strtolower( $_GET["q"] );
//Save all titles
$list_titles = array();
foreach( $list_posts as $post ) { $list_titles[] = $post->post_title; }
// To see more about this part check search.php from example
foreach( $list_titles as $title ) {
if( strpos( strtolower( $title ), $typing ) ){
echo $title;
}
}
?>
I added some comments trying to help you better.
Now stuff get easy, you only have to call your page through jQuery plugin like
$('#yourInput').autocomplete( "path_to/get_posts.php" );
You can directly use wordpress in-build feature to get all post titles
// The Query
query_posts( 'posts_per_page=-1' );
// The Loop
while ( have_posts() ) : the_post();
echo '<li>';
the_title();
echo '</li>';
endwhile;
None of the answers here answer your real question:
How to query JUST post titles
The "raw SQL" way:
Few important things:
escape search for SQL! (also do that for the tags search!) use $GLOBALS['wpdb']->esc_like()
if you only need 1 column, you can use $GLOBALS['wpdb']->get_col()$GLOBALS['wpdb']->get_results() is if you want to fetch more columns in one row
use $GLOBALS['wpdb']->tableBaseName to make your code portable - takes care of the prefixe.g. $GLOBALS['wpdb']->posts
When querying posts you must also think about which post_type and post_status you want to query=> usually the post_status you want ispublish, but post_type may vary based on what you want
WordPress table "posts" contains ALL post types - post, page, custom, but also navigation, contact forms etc. could be there! => I strongly advice to use explicit post_type condition(s) in WHERE ! :)
...$GLOBALS is same as globalizing variabl -today performance difference is little
<?php
// to get ALL published post titles of ALL post types (posts, pages, custom post types, ...
$search_post_titles = $GLOBALS['wpdb']->get_col(
"SELECT post_title from {$GLOBALS['wpdb']->posts}
WHERE (
(post_status = 'publish')
AND
(post_title LIKE '{$GLOBALS['wpdb']->esc_like($search)}%')
)
ORDER BY post_title ASC
"); // I also added ordering by title (ascending)
// to only get post titles of Posts(Blog)
// you would add this to conditions inside the WHERE()
// AND (post_type = 'post')
// for Posts&Pages
// AND ((post_type = 'post') OR (post_type = 'page'))
// test output:
foreach ($search_post_titles as $my_title) {
echo $my_title . " ";
}
?>
The WP_Query way
This is more wordpress but has a little overhead, because although there is a fields param for new WP_Query()/get_posts(), it only has options:
'all' - all fields (also default), 'ids' - just ids, 'id=>parent' - ... if you pass anything else, you still get all, so you still need to add "all" BUT - WP however has filters for altering fields in SELECT.
I tried to make it the same as the raw SQL version, but it depends on how does WP does it's "search" - which I think is %search% for 1 word + some more logic if there are more words. You could leverage the $clauses filter used for fields to also add your custom where INSTEAD of adding the 's' into $args (remember to append to not-lose existing WHEREs $clauses['where' .= "AND ...;). Also post_type => 'any' does not produce always the same results as the raw query in cases like Navigation, Contact forms etc...
Also WP_Query sanitizes the input variables so actually don't escape $args!
<?php
$args = [
'fields' => 'all', // must give all here and filter SELECT(fields) clause later!
'posts_per_page' => -1, // -1 == get all
'post_status' => 'publish',
's' => $search,
// I also added ordering by title (ascending):
'orderby' => 'title',
'order' => 'ASC',
'post_type' => 'any', // all "normal" post types
// 'post_type' => 'post', // only "blog" Posts
// 'post_type' => ['post', 'page'], // only blog Posts & Pages
];
$onlyTitlesFilter = function($clauses, $query) {
// "fields" overrides the column list after "SELECT" in query
$clauses['fields'] = "{$GLOBALS['wpdb']->posts}.post_title";
return $clauses; // !FILTER! MUST RETURN!
};
$onlyTitlesFilterPriority = 999;
// add filter only for this query
add_filter('posts_clauses', $onlyTitlesFilter, $onlyTitlesFilterPriority, 2);
// Pro-tip: don't use variable names like $post, $posts - they conflict with WP globals!
$my_posts = (new WP_Query($args))->get_posts();
// !IMPORTANT!
// !remove the filter right after so we don't affect other queries!
remove_filter('posts_clauses', $onlyTitlesFilter, $onlyTitlesFilterPriority);
// test output:
// note that I used "my"_post NOT just $post (that's a global!)
foreach($my_posts as $my_post) {
echo $my_post->post_title . " ";
}
?>
Don't be confused - you will still get the array of WP_Posts - WP will throw some default properties&values into it, but in reality it will only query and fill-in with real values the fields you specify in the filter.
PS: I've tested these - they are working codes (at least on WP 5.4 and PHP7 :) )
UPDATE: I have tried using the following code:
<?php if (is_category(events)) {
$posts = query_posts($query_string . '&orderby=event_date&order=desc');
} else {
$posts = query_posts($query_string . '&orderby=title&order=asc');
}
?>
Is there any reason why that wouldnt work? It seems to work fine organising posts in alphabetical order, but still no luck on the date order within 'events'.
--
After searching through various existing questions I can't quite find a solution to what I am trying to do.
Currently all posts on my site are ordered alphabetically, which is fine except for one new category that I have added. For this category I want to order all posts by a value that I enter into a custom field. The field is called 'event_date' - so I want to order the posts by date essentially, but not the date the post was created, the date the user manually enters into this field.
I managed to get it working by using:
<?php if (is_category($events)) { $posts = query_posts($query_string . '&orderby=$event_date&order=asc'); } ?>
However this overrides the aphabetical order for all other pages.
For alphabetical order I am using:
<?php if (is_category()) { $posts = query_posts( $query_string . '&orderby=title&order=asc' ); } ?>
Essentially I want a statement that tells the page to order all posts in aphabetical order, unless the category is 'events', where I want to order them by the custom event date.
As you can probably tell I'm very much front end, not back end so a lot of this is fairly new to me, so any help or advice is appreciated.
To order posts by a custom field value, you need add the custom meta field to the query itself. orderby=meta_value in addition to meta_key=metafieldid will allow ordering in this fashion.
I would use the pre_get_posts hook and modify the query object if get_query_var( "cat" ) (or a similar query var) returns the desired post category.
add_action( "pre_get_posts", "custom_event_post_order" );
function custom_event_post_order( $query )
{
$queried_category = $query -> get_query_var( "cat" );
/*
* If the query in question is the template's main query and
* the category ID matches. You can remove the "is_main_query()"
* check if you need to have every single query overridden on
* a page (e.g. secondary queries, internal queries, etc.).
*/
if ( $query -> is_main_query() && $queried_category == 123 )
{
$query -> set( "meta_key", "event_date" ); // Your custom field ID.
$query -> set( "orderby", "meta_value" ); // Or "meta_value_num".
$query -> set( "order", "ASC" ); // Or "DESC".
}
}
Remember that this approach overrides all queries that are using the category in question. You can build custom WP_Query objects that use their own parameters for constructing loops.
You also should standardize the way you save the custom field data to the database. For dates I prefer using UNIX-timestamp formatted times that are easy to move around and manipulate. This way no accidents happen when querying and some data is formatted in another way that the rest is.
Disclaimer: I did not have the time to test the above code in action, but the general idea should work properly.
EDIT: of course the above code should be inserted to functions.php or a similar generic functions file.
What about:
<?php $posts = query_posts($query_string . (is_category($events)?'&orderby='.$event_date:'&orderby=title') . '&order=asc'); ?>
<?php
$recent = new WP_Query(“cat=ID&showposts=x”);
while($recent->have_posts()) : $recent->the_post();
?>
Hopefully I understood your question, use the WP_Query and within the orderby add a space between your order by columns:
$args = array(
'posts_per_page' => 100,
'orderby' => 'title',
'order' => 'ASC',
);
if(is_category($events)){
$args['orderby'] .= " meta_value_num";
$args['meta_key'] = 'event_date';
}
$posts = (array) new WP_Query( $args );
I have 3 custom post types setup and I have created a custom permalink structure for each. The problem I am having is that the third custom post type I have setup with the custom permalink, is being used for the previous 2.
Example:
Classified
Employment
Sponsorship
The above are the post types and I have the custom permalink structure set to (for each):
/post_type/post_id/
Now, The above order are the order they are set in and sponsorship takes over all of them. So for instance:
/classified/100/
/employment/101/
/sponsorship/102/
The above all use the permalink:
/sponsorship/100/
/sponsorship/101/
/sponsorship/102/
What am I doing wrong to get this error happening? Is it a permalink structure error? below is my code I am using to create the custom permalink structures for each. The only difference is that %c_id% is changed to %e_id% and %s_id% for classifieds, employment and sponsorship. And also any reference to 'classifieds' is changed to employment and sponsorship respectively.
add_action('init', 'classifieds_rewrite');
function classifieds_rewrite() {
global $wp_rewrite;
$queryarg = 'post_type=classifieds&p=';
$wp_rewrite->add_rewrite_tag('%c_id%', '([^/]+)', $queryarg);
$wp_rewrite->add_permastruct('classifieds', '/classifieds/%c_id%/', false);
}
add_filter('post_type_link', 'classifieds_permalink', 1, 3);
function classifieds_permalink($post_link, $id = 0) {
global $wp_rewrite;
$post = &get_post($id);
if ( is_wp_error( $post ) )
return $post;
$newlink = $wp_rewrite->get_extra_permastruct('classifieds');
$newlink = str_replace("%c_id%", $post->ID, $newlink);
$newlink = home_url(user_trailingslashit($newlink));
return $newlink;
}
Thanks for the help! :)
If I understand correctly, you registered 3 different post types and you are trying to rewrite each post type so their slug precedes the post id. To start with just the slug of each post type, it doesn't seem like you are issuing the rewrite when you register each post type, is this correct? If not, you can take care of this part by adding the following with the other arguments when registering each post type.
'rewrite' => array( 'slug' => 'classified', 'with_front' => true )
Additional reference with extensive permalink rewrites here: http://shibashake.com/wordpress-theme/wordpress-permalink-add