What is the better for call files: bloginfo() or echo esc_url()?

Note that bloginfo('template_url') is a wrapper for get_template_directory_uri().

It doesn’t seems to explicitly escape it, though.

It’s better to escape it in your example.

Here are two examples how we can break the HTML in the case it’s not escaped:

Break Example #1

add_filter( 'template_directory_uri', function( $uri )
{
    return $uri .'">';
} );

Break Example #2

add_filter( 'bloginfo_url', function( $output )
{
    return $output .'">';
} );

So the suggestion:

echo esc_url( get_template_directory_uri() );

is safer than use it unescaped.

The get_template_directory_uri() and get_stylesheet_directory_uri() are commonly used core functions, where the latter is child-theme aware.

New functions in WordPress 4.7

There will be new functions introduced to e.g. make it easier to reference and override parent theme files

Let’s take a look inside two of them:

  • The new get_theme_file_uri( $file ) function is child-theme aware and uses bothget_template_directory_uri() and get_stylesheet_directory_uri() to construct the correct file URL.

    if ( empty( $file ) ) {
        $url = get_stylesheet_directory_uri();
    } elseif ( file_exists( get_stylesheet_directory() . "https://wordpress.stackexchange.com/" . $file ) ) {
        $url = get_stylesheet_directory_uri() . "https://wordpress.stackexchange.com/" . $file;
    } else {
        $url = get_template_directory_uri() . "https://wordpress.stackexchange.com/" . $file;
    }
    

    where $file is the function’s input.

    Let’s try to describe the above logic in few words, to better understand it:

    • For an empty file input, get_theme_file_uri(), it’s the same as: get_stylesheet_directory_uri().

    • If there’s a child theme that overrides the file, then it’s get_stylesheet_directory_uri() . "https://wordpress.stackexchange.com/" . $file;

    • If there’s a child theme that doesn’t override the file (it doesn’t exist in the child theme ) then it’s the parent file fallback: get_template_directory_uri() . "https://wordpress.stackexchange.com/" . $file;

    • If there’s no child theme and the file exists, then it’s get_stylesheet_directory_uri() . "https://wordpress.stackexchange.com/" . $file;

    • If there’s no child theme, and the file doesn’t exists, then it’s get_template_directory_uri() . "https://wordpress.stackexchange.com/" . $file;

  • The new get_parent_theme_file_uri( $file ) function, on the other hand, uses only get_template_directory_uri():

    if ( empty( $file ) ) {
        $url = get_template_directory_uri();
    } else {
        $url = get_template_directory_uri() . "https://wordpress.stackexchange.com/" . $file;
    }
    

    This is to construct the file URL within the parent theme, as the name suggests.

  • Similarly there are corresponding functions for the path instead of url: get_file_directory_path() and get_parent_file_directory_path().

We should also note that it doesn’t matter if $file starts with a forward slash / or not, that’s taken care of with a masked ltrim:

$file = ltrim( $file, "https://wordpress.stackexchange.com/" );

See ticket #18302 for more info.

Example:

So in WordPress 4.7+ we could try:

<img src="https://wordpress.stackexchange.com/questions/245707/<?php echo esc_url( get_theme_file_uri("static/img/logo.svg') ); ?>">

or for the parent theme file location, depending on the needs:

<img src="https://wordpress.stackexchange.com/questions/245707/<?php echo esc_url( get_parent_theme_file_uri("static/img/logo.svg') ); ?>">

It would be nice though to have the corresponding the_* functions as well to simplify things:

<img src="https://wordpress.stackexchange.com/questions/245707/<?php the_theme_file_uri("static/img/logo.svg') ); ?>">

<img src="<?php the_parent_theme_file_uri('static/img/logo.svg') ); ?>">

where they would include the escaping, similar to how the_permalink() escapes the filtered output from get_permalink().