Maybe it makes sense to you, but using the label “category” for custom taxonomy terms is confusing to others who might be reading your code. Even if you will be the only one to ever read the code, it could be confusing to you as well a year later when it comes time to modify the code. Even though many category functions accept custom taxonomies, there generally are equivalent generic term functions that would be less confusing. Follow through with your variable names by not using category terminology. Use terminology that relates to the taxonomy, or at least use the abstract “taxonomy” and “term” labels.
The first get_term_link() where you foreach $terms is problematic unless you only want the last link of whatever terms are assigned, as the previous links are discarded with each iteration. You generally would either push all the links into an array or concatenate them together in these situations. Or immediately echo out within the loop.
In this line:
foreach((get_the_category($garbage)) as $category)
I’m not sure calling a function as the foreach source is good practice. I think get_the_category() is called on every iteration, though I may be wrong. I’d assign the terms to a variable before looping through them to ensure the function is only called once. Such constructs usually read a little better too. And now we are using actual categories here? Isn’t this all supposed to be for the neighborhood taxonomy?
Outputting lists of things separated by characters always introduces the issue of trailing separators that need to be dealt with. Using substr() like you do is fine, but for the sake of discussion, another nice approach is to collect the list items into an array, then implode() the array. Then if you decide to change the length of the “glue” string, you don’t need to coordinate it anywhere else, just change the glue string and PHP handles the rest. Something like this:
$neighborhood = [];
$neighbors = wp_get_post_terms( get_the_ID(), 'neighborhood');
foreach( $neighbors as $neighbor ) {
$neighborhood[] = $neighbor->term_name;
}
echo implode(' | ', $neighborhood );
This isn’t intended to replace anything you have, it’s just an example. You could actually get wp_get_post_terms to only return term_names in an array, which can then be immediately imploded. No need for a foreach structure.
You’ve covered what to do when there is no parent term, but I don’t see anything to handle parent terms when they exist. There ought to be an else
conditional for if ($category->category_parent == 0)
to output parent links.
Similar comments for getting child terms. Avoid category specific functions and names in favor of generic term functions and variable names that relate to the taxonomy. You’ve dealt with the no children condition, but not when children occur. I’m assuming it’s beyond the snippet you posted, but the same last link issue exists that I first mentioned (paragraph 2). Only the last term’s children will be available outside the loop. Previous term children are overwritten.