On certain pages I'm looking to remove the parent page from the URL.
So instead of:
example.com/parent-page/child-page
I'd like it to display:
example.com/child-page
I have tried the following method but no luck:
function wpse_101072_flatten_hierarchies( $post_link, $post ) {
if ( 'page' != $post->post_type )
return $post_link;
$uri = '';
foreach ( $post->ancestors as $parent ) {
$uri = get_post( $parent )->post_name . "/" . $uri;
}
return str_replace( $uri, '', $post_link );
}
add_filter( 'post_type_link', 'wpse_101072_flatten_hierarchies', 10, 2 );
Is there any known solution that works without a plugin?
Related
I registered custom post type and I registerem custom taxonomy. I added category "Hormann" and I added subcategory "Bramy". I would like to have url in my post "mysite.com/archive_name/category/subacategory/post_name". Please help me.
Edit: I did it writed code in my file functions.php, but my code is not working properly, because displays the link after entering the category "mysite.com/archive_name/category/", but it displays the wrong link after click in the post "mysite.com/archive_name/subacategory/post_name"
add_filter('post_type_link', 'projectcategory_permalink_structure', 10, 4);
function projectcategory_permalink_structure($post_link, $post, $leavename, $sample) {
if (false !== strpos($post_link, '%kategorie_dladomu%')) {
$projectscategory_type_term = get_the_terms($post->ID, 'kategorie_dladomu');
$slug = [];
foreach ( $projectscategory_type_term as $project ){
if ( $project->parent == 0 ) {
array_unshift( $slug, sanitize_title_with_dashes( $project->name ) );
} else {
array_push( $slug, sanitize_title_with_dashes( $project->name ) );
}
if ( ! empty( $slug ) ) {
return str_replace( '%kategorie_dladomu%' , join( '/', $slug ) , $post_link );
}
}
}
return $post_link;
}
I feel like I'm very close with the code I have so far, but something is still not working. None of the other similar questions on Stack Overflow solve this issue.
I have parent pages and child pages (not posts, not custom post type) in WordPress, and the default mydomain.com/%postname% structure selected.
Currently the permalink structure for pages is mydomain.com/parent-page/child-page
In the backend on the single page editor, the desired permalink displays correctly (with the parent page removed). i.e. mydomain.com/child-page
However when I visit mydomain.com/child-page I get a 404.
I have flushed rewrite rules by visiting the permalink settings page already.
What am I doing wrong?
function wpse_101072_flatten_hierarchies( $page_link, $post ) {
$post = get_post($post);
$uri = '';
if($post->post_parent !== 0) {
$uri = get_post( $post->post_parent )->post_name . "/" . $uri;
return str_replace( $uri, '', $page_link );
} else {
return $page_link;
}
}
add_filter( 'page_link', 'wpse_101072_flatten_hierarchies', 10, 2 );
function wp_pages_permalink( $permalink_structure, $post_id ) {
if ( empty( $post_id ) ) return $permalink_structure ;
$post = get_post( $post_id );
if($post->post_parent !== 0) {
$par = get_post($post->post_parent);
$parname = $par->post_name . '/';
$permalink_structure = str_replace( '%pagename%', $post->post_name, $permalink_structure);
return $permalink_structure;
}
}
add_filter( 'page_link', 'wp_pages_permalink', 10, 2 );
I'm having a problem with receiving the value from %category% in $wp_rewrite->page_structure :
function custom_page_rules() {
global $wp_rewrite;
$wp_rewrite->page_structure = $wp_rewrite->root .'/%category%/%pagename%';
//flush_rewrite_rules();
}
add_action( 'init', 'custom_page_rules',1 );
How can I receive the %category% in a $wp_rewrite->page_structure?
Now it returns:
http://example.com/%category%/the-page-slug/
Instead:
http://example.com/my-cat-slug/the-page-slug/
Note Categories for pages are working well:
http://example.com/my-cat-slug/
returns all pages from this category.
A solution could be:
function rudr_post_permalink( $url, $post ){
if( !is_object( $post ) )
$post = get_post( $post_id );
$replace = $post->post_name;
/* We should use a post ID to make a replacement. It is required if you use urf-8 characters in your URLs */
if( $post->ID == 1 )
$replace = 'hello-planet';
if( $post->ID == 12 )
$replace = 'Contacts';
$url = str_replace($post->post_name, $replace, $url );
return $url;
}
add_filter( 'post_link', 'rudr_post_permalink', 'edit_files', 2 );
add_filter( 'page_link', 'rudr_post_permalink', 'edit_files', 2 );
add_filter( 'post_type_link', 'rudr_post_permalink', 'edit_files', 2 );
Which is explained here
You can change the if( $post->ID == 1 ) to anything you need.
I have changed the whole code to add categories in the URL's when it are pages.
Regards, Danny
I've created a custom post type with a rewrite to use the grandparent relationship as the URL like so:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
This all works great, but unfortunately the rewrite rule matches regular pages as well which makes them 404.
I can prevent this by adding a custom slug, for example 'relationship': http://example.com/relationship/grandparent/parent/child
But I'd really like to use http://example.com/grandparent/parent/child and have it not break regular pages.
I might have to resort to using non native Wordpress rewrites using htaccess.
Thanks in advance!
I managed to find a solution thanks to Milo's previous answers on other related questions. I found this particular post Remove base slug in CPT & CT, use CT in permalink to be extremely helpful.
My initial CPT with grandparent relationship rewrite remains the same:
function cpt_child(){
$args = array(
//code
'rewrite' => array( 'slug' => '%grandparent%/%parent%', 'with_front' => false),
);
register_post_type( 'child', $args );
}
add_action( 'init', 'cpt_child' );
Then I update the permalink:
add_filter( 'post_type_link', 'filter_the_post_type_link', 1, 2 );
function filter_the_post_type_link( $post_link, $post ) {
switch( $post->post_type ) {
case 'child':
$post_link = get_bloginfo( 'url' );
$relationship_child = p2p_type('children_to_parents')->get_adjacent_items($post->ID);
$parent = $relationship['parent']->post_name;
$relationship_parent = p2p_type('parents_to_grandparents')->get_adjacent_items($parent['parent']->ID);
$grandparent = $relationship_parent['parent']->post_name;
$post_link .= "/{$grandparent}/";
$post_link .= "{$parent}/";
$post_link .= "{$post->post_name}";
break;
}
return $post_link;
}
Hooked into request and changed query based on request vars that match my needs. Added is_admin() check to prevent request filter from changing the CPT's back end.
// URL rewrite pages 404 fix
if ( ! is_admin() ) {
function svbr_fix_requests( $request ){
// if it's not a section request and request is not empty treat request as page or post
if( ( ! array_key_exists( 'section' , $request ) ) && ( ! empty($request) ) ){
$request['post_type'] = array( 'post', 'page' );
}
// return request vars
return $request;
}
add_filter( 'request', 'svbr_fix_requests' );
}
Because we changed the query vars we have to add template functionality.
// Use single_template filter to properly redirect to page.php and custom page templates
function svbr_get_template_file($single_template) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
if ($post->post_type == 'page') {
if($page_custom_template != 'default') {
// We are using a child theme, so get_stylesheet_directory()
$single_template = get_stylesheet_directory() . '/' . $page_custom_template;
}
else {
$single_template = get_template_directory() . '/page.php';
}
}
return $single_template;
}
add_filter( 'single_template', 'svbr_get_template_file' );
Last but not least we have to add the template class to the body for styling purposes.
// Add template class to body
add_filter( 'body_class', 'template_class_name' );
function template_class_name( $classes ) {
global $post;
$page_custom_template = get_post_meta( $post->ID, '_wp_page_template', true );
$page_custom_template = str_replace('.php','',$page_custom_template);
$page_custom_template = 'page-template-' . $page_custom_template;
// add 'class-name' to the $classes array
$classes[] = $page_custom_template;
// return the $classes array
return $classes;
}
I’m trying to remove the attachment slug from the attachment URL generated by wordpress. My current URL structure looks like:
www.site.com/category/folder/attachment/file
I made a function for that but the url output I’m getting is www.site.com/folder/file, its missing the category. Any idea how I can fix that? Here is what I got so far:
function wpd_attachment_link( $link, $post_id ){
$post = get_post( $post_id );
$post_data = get_post($post->post_parent);
return home_url( single_cat_title('', false)."/".$post_data->post_name."/". $post->post_title );
}
add_filter( 'attachment_link', 'wpd_attachment_link', 20, 2 );
P.S: i know that can be done if i change the permalink structure from the main wordpress menu, but dont want to change the current permalink structure.
Try following code:
function __filter_rewrite_rules( $rules )
{
$_rules = array();
foreach ( $rules as $rule => $rewrite )
$_rules[ str_replace( 'attachment/', '/', $rule ) ] = $rewrite;
return $_rules;
}
add_filter( 'rewrite_rules_array', '__filter_rewrite_rules' );
function __filter_attachment_link( $link )
{
return preg_replace( '#attachment/(.+)$#', '/$1', $link );
}
add_filter( 'attachment_link', '__filter_attachment_link' );