Simply speaking i want to do something like this.
change into
I found some solutions, but they are not perfect. For instance i found this code which do the thing almost right.
add_filter( 'post_link', 'remove_parent_category', 10, 3 );
function remove_parent_category( $permalink, $post, $leavename )
{
$cats = get_the_category( $post->ID );
if ( $cats ) {
usort( $cats, '_usort_terms_by_ID' );
$category = $cats[0]->slug;
if ( $parent = $cats[0]->parent ) {
// Find parent categories and replace them in the link
$parentcats = get_category_parents( $parent, false, '/', true );
$permalink = str_replace( $parentcats, '', $permalink );
}
}
return $permalink;
}
Because of str_replace it breaks links if categories has similar names. Like
It will delete house from both categories. Can someone fix this code to work with any names?
Simply speaking i want to do something like this.
http://example/parent-category/child-category/post-name
change into
http://example/child-category/post-name
I found some solutions, but they are not perfect. For instance i found this code which do the thing almost right.
add_filter( 'post_link', 'remove_parent_category', 10, 3 );
function remove_parent_category( $permalink, $post, $leavename )
{
$cats = get_the_category( $post->ID );
if ( $cats ) {
usort( $cats, '_usort_terms_by_ID' );
$category = $cats[0]->slug;
if ( $parent = $cats[0]->parent ) {
// Find parent categories and replace them in the link
$parentcats = get_category_parents( $parent, false, '/', true );
$permalink = str_replace( $parentcats, '', $permalink );
}
}
return $permalink;
}
Because of str_replace it breaks links if categories has similar names. Like
http://example/myhouse/house/post-title
It will delete house from both categories. Can someone fix this code to work with any names?
Share Improve this question edited May 30, 2017 at 2:15 Recofa asked May 28, 2017 at 1:04 RecofaRecofa 677 bronze badges1 Answer
Reset to default 1With either str_replace
or preg_replace
, without either some naming conventions on the user end or some strong work in the method's directives (linked, you can read about patterns here, ), you're going to run into issues with the
House | My House | New House
scenarios; especially once you're dealing with slugs, and if those slugs are things like myhouse
and newhouse
.
Then the questions become "what of grandchildren?", and "what if the post is in multiple child categories with different parents and the wrong parent is in the first position of that $cats
array?"
Possible Solution: filter the permalink to remove parent categories
The below seemed to work on my end for the scenarios I mentioned above, and it avoids str_
- and preg_
-replace altogether.
I assume by your link example:
http://example/myhouse/house/post-title
that your permalinks structure is /%category%/%postname%/
And that the goal here is to limit the permalink to the youngest member of the category family and post title. So, example/child-cat/post-title/
or example/grandchild-cat/post-title
Since we know we only want those two last values to remain, and we have the permalink, let's parse it, explode the path portion into an array, count the array entries, keep the last and second-to-last entries, and reform the permalink and return it.
After we make sure we're dealing with a post that even has a child category, of course.
Something like this maybe:
add_filter( 'post_link', 'remove_parent_category', 10, 3 );
function remove_parent_category( $permalink, $post, $leavename ) {
$cats = get_the_category( $post->ID );
if ( $cats ) {
foreach ($cats as $cat => $parent) {
$cat_parent_values[] = $parent->parent;
}
if( array_sum( $cat_parent_values ) > 0 ) {
$url_array = parse_url( $permalink );
$url_path = array_filter( explode( '/', $url_array['path'] ) );
$url_path = array_values($url_path);
$url_path_count = count( $url_path );
$name_slot = $url_path_count - 1;
$child_cat_slot = $name_slot - 1;
$new_url_path[] = '/'. $url_path[ $child_cat_slot ];
$new_url_path[] = '/'. $url_path[ $name_slot ] .'/';
$new_permalink = $url_array['scheme'] .'://'. $url_array['host'] . $new_url_path[0] . $new_url_path[1];
}//end if sum > 0
}//end if $cats
return $new_permalink;
}
A preliminary test of it seems to work on my end on a fresh install, and it with no str_replace it passes the House|MyHouse test. I'm sure it can be improved upon, and you will have to really test it and make sure there aren't any other issues/scenarios that break it. There could very well be a better approach altogether that doesn't involve filtering the permalink, but I'm not sure of one off hand.
Explanation:
First we use get_the_category
like you already had to get an array of category objects.
We verify we have some, and then we do a foreach loop of array as $key => $value
, casting each value to a new array.
Wordpress stores the value of parent
for a category as the id, and that id is an (int)
. If there is no parent, it gets a 0
.
So, if the sum of all values in our new array is greater than 0
, we have at least one parent category in there.
And that means we have at least one path part in our permalink we want removed, so we continue.
php's parse_url
will give us an array() of 'scheme' => 'http', 'host' => 'example', 'path' => '/category/child-cat/postname/'
we explode()
that, $url_array
, at each /
which gives us an array of each section. It also gives us some empty array values,
so we wrap it in array_filter
and it cleans that up for us hopefully and we set it to $url_path
. The we can use [array_values()][5]
to clean up any missing numerical keys removed by array_filter
and give us [0],[1],[2]
for keys in an array of three items.
As mentioned earlier, we are assuming the name of the post is at the end, so with our filtered and re-valued array we use count()
to know how many keys are in this array,
and use that to find our post name by subtracting "one" since the array starts at [0]. Then subtract one from that and we have our "youngest category".
Then we put the permalink back together with using our $url_array and the path parts for the post name and category we want to keep, ignoring whatever else was there.
and we return it to the post_link filter.
Other possible issues I noticed with your example:
There are some other potential issues with the example you provided:
get_the_category()
will return an array of category objects, but if that usort()
is intended to arrange them by their ids, then if you create a category that becomes the parent to an existing category then first position of that array, $cats[0]
, will not necessarily be a parent category. (unless I'm misunderstanding the nature of _usort_terms_by_id
.
It is also unclear what the $parent
variable in if($parent = $cats[0]->parent)
is intended to be set to.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744831655a4596120.html
评论列表(0条)