substr() still echoing whole string | help
-
Here’s the code. Help please.
<?php $prevpost = substr(previous_post_link('<li>%link</li>', '« %title'),0,14); echo $prevpost; if (strlen($prevpost) > 14 ){ echo ' ...'; } ?>
-
I’ve been trying to solve the problem of too-long-titles myself.
The problem you’re having is that the previous_post_link function echoes its output directly. It doesn’t return a string for substr to then chop up and echo manually. The moment previous_post_link gets called in your code, BOOM, it gets echoed. So it’s not being processed. A lot of WordPress functions are like this. If you want to capture the output to shorten it, you have to use output buffering, like this:
ob_start(); next_post_link('%link'); $next_post_link = ob_get_contents(); ob_clean(); previous_post_link('« %link'); $previous_post_link = ob_get_clean();
Now you have the links output as variables you can process, and nothing has been echoed to the screen yet.
But there still remains a problem. If you use the above code, the content of the $next_post_link variable is HTML and wrapped in an A tag. So you’ll have succesfully captured, for example:
« Previous Post Title
Now if you try to run substr on that and add ellipses, you’ll be butchering the HTML and breaking the page. It’ll create something like:
« Previous Post Title<...
So you can see, it breaks the closing A tag and doesn’t actually shorten the title. So if you did this you’d have to use a regular expression (like preg_replace) to find and shorten the title inside the tag. (WordPress should really add an argument to the functions to allow you to shorten it.)The output buffer + regular-expression approach is the only one I’ve found so far, and I haven’t implemented it yet because regular expressions are a colossal pain in the ass.
Darnit, the comment system converted some of what I typed above to code, so let me try again starting with the paragraph “But there still remains a problem:”
*snip*
But there still remains a problem. If you use the above code, the content of the $next_post_link variable is HTML and wrapped in an A tag. So you’ll have succesfully captured, for example:
« <a href="https://www.example.com/prevpost">Previous Post Title</a>
Now if you try to run substr on that and add ellipses, you’ll be butchering the HTML and breaking the page. It’ll create something like:
« <a href="https://www.example.com/prevpost">Previous Post Title<...
*/snip*
A simpler way would be to notice that previous_post_link has a filter on it, so you can define a function to do what you like with it.
function my_filter($post_link_string, $link); // modify $post_link_string here as you see fit, then return it. // $link contains just the link, if you need to know that. return $post_link_string; } add_filter('previous_post_link','my_filter');
No need to use output buffering.
Same goes for next_post_link, BTW.
I was just about to post my regex solution to this, but that’s a brilliant find. I had no idea such a filter existed.
One problem though: there doesn’t seem to be an actual ‘previous_post_link’ filter in the API (https://codex.www.ads-software.com/Plugin_API/Filter_Reference), just one for ‘post_link’ — which the documentation seems to suggest would apply to all permalinks, which is not what I want. Am I wrong here? The filter documentation is:
post_link
applied to the calculated post permalink by the get_permalink function, which is also called by thethe_permalink
,post_permalink
,previous_post_link
, andnext_post_link
functions. Filter function arguments: permalink URL, post data list.Okay, I found out that the filter DOES exist, it’s just not on the Plugin API page. It’s here:
https://adambrown.info/p/wp_hooks/hook/%7B$adjacent%7D_post_linkSo, thank you Otto! Now here is my solution:
function filter_shorten_linktext($linkstring,$link) { $characters = 33; preg_match('/<a.*?>(.*?)<\/a>/is',$linkstring,$matches); $displayedTitle = $matches[1]; $newTitle = shorten_with_ellipsis($displayedTitle,$characters); return str_replace('>'.$displayedTitle.'<','>'.$newTitle.'<',$linkstring); } function shorten_with_ellipsis($inputstring,$characters) { return (strlen($inputstring) >= $characters) ? substr($inputstring,0,($characters-3)) . '...' : $inputstring; } // This adds filters to the next and previous links, using the above functions // to shorten the text displayed in the post-navigation bar. The last 2 arguments // are necessary; the last one is the crucial one. Saying "2" means the function // "filter_shorten_linktext()" takes 2 arguments. If you don't say so here, the // hook won't pass them when it's called and you'll get a PHP error. add_filter('previous_post_link','filter_shorten_linktext',10,2); add_filter('next_post_link','filter_shorten_linktext',10,2);
You simply place this in your theme folder’s “functions.php” file and it will start working. Change
$characters = 33;
to the number of characters you want it to cut off at. I may write a plugin to do this, too; we’ll see.The documentation, as you have discovered, is incomplete. I suggest referring to the actual code in WordPress instead, it’s easier to understand.
I put together a plugin to automate this fix. I applied for an account to post the plugin officially but haven’t heard back yet, so for now, find the plugin and instructions and screenshots here:
https://www.filmtraveler.com/2008/11/18/wordpress-plugin-shorten-link-text/Thanks for your help, Otto, in recommending the filter!
- The topic ‘substr() still echoing whole string | help’ is closed to new replies.