As @CharlesClarkson has already explained, you cannot modify the page output with PHP after the output has been sent to the browser. Your menu certainly runs after body_class
since the menu must run inside the <body>
tag.
The only PHP solution I see would involve editing your theme templates in addition to the code above (with changes).
If you run wp_nav_menu
before the <body>
tag but use output buffering to capture the content instead of print it, what you are trying to do might work.
You would need to run your menu before the <body>
tag, like this:
ob_start();
wp_nav_menu();
$my_captured_menu = ob_get_contents();
ob_end_clean();
In your function callback, instead of lines like this:
$body_class="has-submenu";
You would need this:
add_filter(
'body_class',
function($classes) {
$classes[] = 'has-submenu'; // or 'is-submenu'
return $classes;
}
);
And of course, use echo $my_captured_menu
wherever it needs to be printed.