Do I have to add_filter() before apply_filters() in WordPress?

Solution:1

apply_filters is like, ‘if there are any filters with this name, run the attached callbacks with these parameters’. So if there is no add_filter for that name, it means that there is no filter that’s going to be run with the apply_filters call at the moment.

The same goes with do_action and add_action.

Solution:2

I have come across this type of code in a plugin or theme where the apply_filter is used without necessarily having an existing filter or add_filter

In this case, where the apply_filters is used without a filter you will have to call the function again where you want to run it. For example, in the header of a theme.

The following is an example of apply filters used in a function that is again called in the header.php

if ( ! function_exists( 'header_apply_filter_test' ) ) {

    function header_apply_filter_test() {

        $filter_this_content = "Example of content to filter";

        ob_start();

            echo $filter_this_content; 

        $output = ob_get_clean();

        echo apply_filters( 'header_apply_filter_test', $output );//used here 
    }
}

Now in the header.php file, you would have to call this function since it is not hooked anywhere. So, in this case, to display the output in the header you would call the function like this :

<?php  header_apply_filter_test(); ?>

You could as well write this code with a hook and it would do the same thing i.e display the output in the header.

add_filter('wp_head', 'header_apply_filter_test');

if ( ! function_exists( 'header_apply_filter_test' ) ) {

        function header_apply_filter_test() {

            $filter_this_content = "Example of content to filter";

            ob_start();

                echo $filter_this_content; 

            $output = ob_get_clean();

            echo $output; 
        }
    } 

For this second option, you would still have the capability of using apply_filters anywhere else to call the callback function header_apply_filter_test() since the filter now exists.

So the bottom line in my view is a use case since either approach works!