selected option if current category is the value

The problem is how you’ve used selected(). That function outputs selected="selected" if the first argument matches the second argument.

So what you’re doing is marking the option as selected if:

(string) 'https://premium.wpmudev.org/blog/category/news-community/' === (string) true

Which – because the values are cast as strings and compared with === – will never be true, even if the URL is the same as the category you’re viewing. See the function that’s used under the hood for this.

So what you need to do is pass values to this function that can check whether the current option is the same as the currently viewed category. You don’t actually need to use the actual value attribute for the option to do the comparison. Since each option is representing a category, you can just compare the ID for that option and the ID of the current category being viewed.

We can therefore use $cat->term_id for the ID of the current option, and get_queried_object_id() to get the ID of the category that’s currently being viewed. However one important caveat is that get_queried_object_id() will also return the post ID if you’re viewing a post, and since posts and terms are stored separately, you could get a match even if you’re not viewing a category. So you should check that you’re even viewing a category before using get_queried_object_id().

Apply all this and your code should look something like:

$categories = get_categories( array(
    'orderby' => 'name',
    'order'   => 'ASC'
) );

$current_category = is_category() ? get_queried_object_id() : false;

foreach ( $categories as $category ) {   
    printf(
        '<option value="%s" %s>%s</option>',
        esc_url( get_category_link( $category ) ),
        selected( $category->term_id, $current_category, false ),
        esc_html( $category->name )
    );
}

This line is getting the ID of the current category, as long as we are even viewing a category:

$current_category = is_category() ? get_queried_object_id() : false;

Then this line is how the selected() function is working:

selected( $category->term_id, $current_category, false ),

Note that I’m comparing the ID of the category in the foreach loop to the category we’re viewing, as defined above. Also note that the last argument is false. We only want to return the text of the attribute because we’re already echoing.

There’s also a few stylistic changes I made that you don’t need to use but I feel I should explain:

  • I used $category instead of $cat. I don’t like abbreviations in code. You can do what you want.
  • I used printf() instead of concatenating a string together. Concatenating an <option> tag with all these values can result in a really long line of code. Using printf() keeps it more compact and readable (in my opinion).
  • This one you should do: I escaped the name of the category with esc_html(). This is so that the name of the category can’t break the HTML of the option tag we’re creating.