WordPress 提供了一個非常簡單方便的函式來顯示當前文章的標題,那就是:the_title() 。

這個函式經常被開發者在 header,post,page,loop,footer 裡使用,這幾乎是開發主題裡最常用的 WordPress 函式之一,然而許多開發者並沒有意識到這裡有個地方並不應該使用此函式,那就是在 attributes 裡,如:

<a href="<?php%20the_permalink();%20?>" title="<?php the_title(); ?>"> 繼續閱讀 <?php the_title(); ?></a>

很多開發者在 loop,page,post 裡使用這樣的寫法設定一個超連結到指定的文章,看起來似乎並沒有什麼問題,但其實正確安全的寫法應該把 title=」<?php the_title(); ?>」 改寫成 title=」<?php the_title_attribute(); ?>」

為什麼要這樣寫,大家看看 WordPress 原始檔中的相關函式核心檔案便知了:

the_title() 原始碼:

/**
 * Display or retrieve the current post title with optional content.
 *
 * @since 0.71
 *
 * @param string $before Optional. Content to prepend to the title.
 * @param string $after Optional. Content to append to the title.
 * @param bool $echo Optional, default to true.Whether to display or return.
 * @return null|string Null on no title. String if $echo parameter is false.
 */
function the_title($before = '', $after = '', $echo = true) {
        $title = get_the_title();
        if ( strlen($title) == 0 )
                return;
        $title = $before . $title . $after;
        if ( $echo )
                echo $title;
        else
                return $title;
}

這個函式並沒有提供給我們有效的資訊, 只是執行了 get_the_title() 函式,我們再看下這個函式的相關檔案.

/**
 * Retrieve post title.
 *
 * If the post is protected and the visitor is not an admin, then "Protected"
 * will be displayed before the post title. If the post is private, then
 * "Private" will be located before the post title.
 *
 * @since 0.71
 *
 * @param mixed $post Optional. Post ID or object.
 * @return string
 */
function get_the_title( $post = 0 ) {
        $post = get_post( $post );
        $title = isset( $post->post_title ) ? $post->post_title : '';
        $id = isset( $post->ID ) ? $post->ID : 0;
        if ( ! is_admin() ) {
                if ( ! empty( $post->post_password ) ) {
                        $protected_title_format = apply_filters( 'protected_title_format', __( 'Protected: %s' ) );
                        $title = sprintf( $protected_title_format, $title );
                } else if ( isset( $post->post_status ) && 'private' == $post->post_status ) {
                        $private_title_format = apply_filters( 'private_title_format', __( 'Private: %s' ) );
                        $title = sprintf( $private_title_format, $title );
                }
        }
        return apply_filters( 'the_title', $title, $id );
}

這個函式非常簡單,它用 get_post() 取回了 post object,然後把它傳遞給一個叫做 the_title 的 filter,返回 $post->post_title

這個函式最重要的地方就是 apply_filters( 『the_title』, $title, $id );

這個 filter 可以提供給開發者自定義標題的輸出形式,比如新增額外的 html 標籤。

the_title_attribute() 原始碼:

/**
 * Sanitize the current title when retrieving or displaying.
 *
 * Works like {@link the_title()}, except the parameters can be in a string or
 * an array. See the function for what can be override in the $args parameter.
 *
 * The title before it is displayed will have the tags stripped and {@link
 * esc_attr()} before it is passed to the user or displayed. The default
 * as with {@link the_title()}, is to display the title.
 *
 * @since 2.3.0
 *
 * @param string|array $args Optional. Override the defaults.
 * @return string|null Null on failure or display. String when echo is false.
 */
function the_title_attribute( $args = '' ) {
        $title = get_the_title();
        if ( strlen($title) == 0 )
                return;
        $defaults = array('before' => '', 'after' =>  '', 'echo' => true);
        $r = wp_parse_args($args, $defaults);
        extract( $r, EXTR_SKIP );
        $title = $before . $title . $after;
        $title = esc_attr(strip_tags($title));
        if ( $echo )
                echo $title;
        else
                return $title;
}

這個函式也使用了 get_the_title() 函式來取回文章的標題,但是最後返回的資料卻與 the_title() 函式不同。這裡過濾掉了許多跳脫字元與 html 標籤,能夠更加安全的在元素屬性裡進行使用。

詳細例子:

假設你的 $post->post_title 是這樣的

<span > 這是有 span 標籤的標題</span>

當你使用 the_title() 函式,輸出將保持不變,還是如下

<span > 這是有 span 標籤的標題</span>

但是當你使用 the_title_attribute(),你的輸出是如下的

這是有 span 標籤的標題

注意這裡的 span 標籤已經被移除掉了.

又假如如果你的標題裡有雙引號, 如下

這是一個帶 "雙引號" 的標題

當你使用 the_title() 函式,輸出如下

這是一個帶 "雙引號" 的標題

但是當你使用 the_title_attrubute() 函式,輸出卻如下

這是一個帶 "雙引號" 的標題

注意到這裡自動把雙引號替換成跳脫字元了,這樣就保證了 html 標籤屬性的安全使用。

如果我們在 html 標籤屬性裡使用 the_title() 函式, 則會破壞掉屬性原有的形式

<span title="<?php the_title(); ?>"><?php the_title(); ?></span>

輸出將會如下:

<span title="這是一個帶 "雙引號" 的標題"> 這是一個帶」 雙引號」 的標題</span>

注意到了這裡的 title 屬性的引號,html 標籤對引號的使用是非常嚴格的,禁止這樣的形式出現,一旦出現將導致頁面嚴重的顯示問題.

經過以上的分析,希望開發者們在以後的開發過程中能注意到這些小細節,在 html 標籤屬性裡一定要使用 the_title_attribute() 函式而不是 the_title() 函式!

所以正確的用法應該是:

<a href="<?php%20the_permalink();%20?>" title="<?php the_title_attribute(); ?>"> 繼續閱讀 <?php the_title(); ?></a>