TwitterカードやYouTubeの動画など、WordPressの記事内にコンテンツ埋め込み(oEmbed)をする仕組みがありますが、これが約1日で普通のURLの文字列になってしまう、つまり記事作成時にはoEmbedが動くけど、翌日、動かなくなる事象に遭遇しました。
ちなみに、下記がYouTubeをoEmbedで挿入した例です。これが、1日後にURLの文字列になってしまいます。
ネットで調べましたが、該当の不具合に対する情報が探せなく、、、困ったときは、WordPressのソースを見れば、ということで、見たら1発でわかりました!
$attr['discover'] = apply_filters( 'embed_oembed_discover', true ); // Use oEmbed to get the HTML. $html = wp_oembed_get( $url, $attr ); if ( $post_ID ) { if ( $html ) { update_post_meta( $post_ID, $cachekey, $html ); update_post_meta( $post_ID, $cachekey_time, time() ); } elseif ( ! $cache ) { update_post_meta( $post_ID, $cachekey, '{{unknown}}' ); }
該当する箇所は、上記の309行目で、
なんと、oEmbedの規格に従い関数wp_oembed_getで取得したHTML(←これが埋め込まれる)をpost_metaにキャッシュしてるではありませんか!
しかも、これは、同一のメソッド内「public function shortcode」の上部で、「DAY_IN_SECONDS」(=1日)間はキャッシュされ、それが再利用されるというものです。
なんらプログラムに問題がないように思われますが、実は、utf8なMySQLに、4バイトのutf8の入ったデータをupdate_post_metaで保存できないんですよ。なので、今回の事象は、wp_oembed_getで取得した埋め込まれるHTML内に4バイトのutf8、つまり絵文字が含まれてると発動します(特にTwitterカードとかでは絵文字が使われる率が高いので高確率で発動します)。初回は、なんとかこのキャッシュが迂回されてoEmbedが動いているように見えますが、「DAY_IN_SECONDS」(=1日)後に、保存されてるはずのキャッシュが保存されてなく、oEmbedが動作しなくなるといった具合です。
という訳で、問題の起こったWordPressサイトを調べると、MySQLは「utf8」「utf8mb4」どちらも使えるバージョンですが、たしかにWordPressで使っているMySQLのデータベースが「utf8mb4」ではなく「utf8」だったんですよ。これをMySQLのコマンドで「utf8mb4」に変更したら直りました。
たしかWordPress4.3あたりから、絵文字対応とかいって、データベースが「utf8mb4」が標準になったんですが、このサイトはそれ以前からバージョンアップ、バージョンアップでやってきたWordPressだったんですね。
たしかに今でもWordPressは、MySQLの文字コード「utf8」で動きますが、いろいろな問題を引き起こしますので、「utf8mb4」が必須と考えといた方がよいかもです。