Contact Info

  • aniuma OÜ Harju maakond, Tallinn, Lasnamäe linnaosa, Sepapaja tn 6, 15551

Smart Custom Fieldsを利用したときのオプション取得関数 SCF::GETが重かった

前々から利用している Smart Custom Fileds (略称SCF)で、こんなループをいつもどおり利用していました。

Before

<?php
 $args = array(
	 'post_type' => 'geo',
	 'posts_per_page' =>300',
 );

 $fudo_query = new WP_Query($args);
 if ($fudo_query->have_posts()) :
	 while ($fudo_query->have_posts()) : $fudo_query->the_post(); ?>
				 name: '<?php the_title(); ?>',
				 lat: <?php echo SCF::get( 'ido' ); ?>,
				 lng: <?php echo SCF::get( 'keido' ); ?>,
	 <?php
	 }
	 endwhile;
 endif;
 wp_reset_postdata();
 ?>

このコードの前後で処理時間を計測したら約10sかかっていました。(ループ1件あたり0.03s)

After

<?php
 $args = array(
	 'post_type' => 'geo',
	 'posts_per_page' =>300',
 );

 $fudo_query = new WP_Query($args);
 if ($fudo_query->have_posts()) :
	 while ($fudo_query->have_posts()) : $fudo_query->the_post(); ?>
				 name: '<?php the_title(); ?>',
				 lat: <?php echo get_post_meta( $post->ID, 'ido' ,true); ?>,
				 lng: <?php echo get_post_meta( $post->ID, 'keido' ,true); ?>,
	 <?php
	 }
	 endwhile;
 endif;
 wp_reset_postdata();
 ?>

標準関数の get_post_meta に変更したら、なんと約0.3sで処理が終わりました(30倍の処理速度!?)

※関数の中の処理までは調査はしていません

検証環境
WordPress 5.7.2
Smart Custom Fields 4.1.5

Cloudflare でページキャッシュを利用した時のデバイス判定(wp_is_mobile)

Cloudflare や Cloud Front といったCDNや、キャッシュ系プラグインを使ってHTMLキャッシュをおこなう時は、wp_is_mobile関数などのデバイス判定が効かなくなります。

Cloud Front であれば CloudFront 配下での User-Agent の判定 | Amimoto Help Center で記載されているとおり、Nginx Mobile Theme プラグイン を導入し User-Agent を判定することで対応できるようです。

https://support.amimoto-ami.com/en/articles/1361104-cloudfront-%E9%85%8D%E4%B8%8B%E3%81%A7%E3%81%AE-user-agent-%E3%81%AE%E5%88%A4%E5%AE%9A

Cloudflare でも上記のように対応することは可能かもれしれませんが Understand Cache by Device Type (Enterprise plans only) – Cloudflare Help Center に書かれているとおり、公式の機能でデバイスタイプを切り分けてキャッシュするにはエンタープライズプランにアップグレードしなければいけません。(費用は見積もり)

https://support.cloudflare.com/hc/en-us/articles/229373388-Understand-Cache-by-Device-Type-Enterprise-plans-only-

解決方法としては WordPressの wp_is_mobile 関数でモバイル判定 | work.log で記載されているように要素であればメディアクエリーを用いたCSSでの表示・非表示切り替え、JavaScript であれば Googleタグマネージャー を利用してスクリプトの読み込みトリガーを設定するとよいでしょう。

https://satori.marketing/marketing-blog/what-is-marketing/gtm-advanced-trigger/

その他にもいい方法があればコメントをいただけると嬉しいです。

ポストタイプで特定のポストタイプだけ許可 allowed_block_types

ポストタイプのブロックをホワイトリスト形式で有効化するフックです。


function wpdocs_allowed_block_types( $allowed_block_types, $post ) {
    if ( $post->post_type !== 'post' ) {
        return $allowed_block_types;
    }
 
    return array( 'core/paragraph' );
}
 
add_filter( 'allowed_block_types', 'wpdocs_allowed_block_types', 10, 2 );

上記のコードで投稿のブロックエディタでは段落ブロックだけが有効になります。

ブロックエディタでカスタムフィールド対応のブロックを作成する方法

ブロックエディタが実装されるまでにオリジナルで WordPress のテーマを作成していた人にはおなじみのカスタムフィールド(ポストメタ)ですが、ブロックエディタを使って同じような実装ができないか探していたところ、メタブロック対応のカスタムブロックを作成することで対応できるため調べたソースをまとめます。


カスタムブロックをまだ作ったことがない人は、まず下記のチュートリアルをすすめて作ってみることをおすすめします。

npm が使える人は npm i @wordpress/scripts を使うのが推奨されますが、WP-CLI が入っている場合は wp scaffold block でもブロックの作成をすることができます(こちらは非推奨)。

https://twitter.com/susumu1127/status/1324645354076295168

ブロックエディタのカテゴリーを追加する

ブロックエディタに新しいカテゴリーを追加するには、funcitons.phpなどで下記の記述を追加する。

// Register block category
function anm_register_block_category( $categories, $post ) {
	return array_merge(
		array(
			array(
				'slug'  => 'aniuma',
				'title' => __( 'アニューマ', 'aniuma' ),
			),
		),
		$categories
	);
}

add_filter( 'block_categories', 'anm_register_block_category', 10, 2 );

上記のコードでは先頭に新しいカテゴリーが追加される。カテゴリーの順番はおそらく、$categoriesの順番のため最初か最後に追加するには比較的簡単に追加することができる。

カテゴリーの最後に新しいカテゴリーを追加したい場合は、下記のようにarray_mergeの記述を逆にすることで対応可能。

// Register block category
function anm_register_block_category( $categories, $post ) {
	return array_merge(
		array(
		        $categories,
			array(
				'slug'  => 'aniuma',
				'title' => __( 'アニューマ', 'aniuma' ),
			),
		)
	);
}

add_filter( 'block_categories', 'anm_register_block_category', 10, 2 );
https://www.loomo.ca/gutenberg-creating-custom-block-categories/

shell_exec を使ってGitの自動デプロイでうまくいかない時の解決方法 [WordPress]

開発するときにリポジトリからwebhookでPOSTをリクエストして自動でデプロイしたいのですがうまくいかなかったので、詰まったポイントと解決策を記していきたいと思います。

まずは前提です。

  1. WordPress のテーマをGitHubからpull
  2. VPSでCentos7系、apache
  3. deploy.phpにshell_execでシェルを実行

今回詰まったポイントは権限がどういう風に動いてるのかいまいちちゃんと理解していなかったので、どこが問題なのかと言う切り分けに時間がかかりました。WordPress のテーマを開発してGitにプッシュが来たらwebhookでリクエストしてPHPファイルからシェルコマンドを実行するといった流れでデプロイしていきます。

解決方法

  1. リポジトリとdeploy.phpの実行権限をapache:apacheにする(CentOS 6系だとwwwらしい)
  2. git which で Git の絶対パスを探して直実行する
  3. git status 2>&1 のようにしてエラーログを確認する

解決方法は以下の3.2箇条書きでまとめました。まずはリポジトリとデプロイ用のPHPファイルの権限をapache:apacheにします。今回はリライトの問題で404が出てしまうため、ディレクトリ直下にdeploy.phpを置いています。

chown -R apache:apache [ここにテーマのパス]
chown -R apache:apache [ここにdeloy.phpのパス]

次にGitの絶対パスを取得してコマンドが必ず実行されるようにしましょう。

git which

下記の例のように表示されたパスとGitコマンド合わせると通常通り実行することがわかると思います。

/usr/bin/git status

次はdeploy.phpにデプロイ用のコマンドをshell_execを使って書きます。最後に記載されている 2>&1 は失敗や成功した時のメッセージを受け取るためのものなので動かない時のデバックのためにも記載しておきましょう。

<?php
echo shell_exec("cd [リポジトリまでのパス] && /usr/bin/git pull 2>&1");

僕の場合はここでうまくpullができなく「Could not create directory ‘/usr/share/httpd/.ssh’. Host key verification failed. fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.」とエラーメッセージが表示されました。Root権限ではsshキーが共有されていたので、そのsshキーを/usr/share/httpd/.sshに設置することで無事自動でデプロイできる環境が整いました。

参考記事

https://stackoverflow.com/questions/37752962/git-pull-command-work-from-terminal-but-not-with-php-shell-exec-via-git-repo
https://jondavidjohn.com/git-pull-from-a-php-script-not-so-simple/

WordPress + AWS + KUSANAGI 「データベース接続確立エラー」MarieDBが起動できない問題の解決方法

AWSでKUSANAGIを使っている環境で502エラーが出て、サーバ容量がいっぱいだったの追加したのですが「データベース接続確立エラー」が表示されてしまいデータベースにアクセスできない状態になりました。

結論としては、DBが起動しなくなっていたので/ var / lib / musql の中の tc.log と ib_logfile1 と ib_logfile2 を削除したら無事起動しました。

tc.log とib_logfile* のどちらかが問題を起こしていたもしくは両者が問題をおこしていたかは検証中ですが両者ともログファイルであることと、以前もログの肥大化でMySQLが起動できない問題があったので、上記の問題で解決しなくMySQLやMariaDBが起動せずに WordPress が「データベース接続確立エラー」と表示する場合はログデータの削除(復帰しなければいけない可能性があるのでリネーム)をすると解決するかもしれません。

問題の現象と特定した方法

systemctl status mariadb.service の結果

前述の画像のように Active : failed と表示されMariaDBが動いてないことが確認できたので、下記の記事を参考にDBのエラーログの場所を特定しエラーログを参照します。

https://qiita.com/sugasaki/items/2085611ca6ccc9b95859

上記のよう Can’t init tc log というログをもとにソースを探し、下記の記事にたどり着いたため tc.log に問題があると判断しリネーム(削除)しました。

https://www.digitalocean.com/community/questions/mysql-server-stop-working-suddenly

WordPress の記事埋め込み oEmbed がうまく表示されない件

WordPress の埋め込みブロックコレクションにある WordPress 埋め込みブロックが特定の記事の場合、うまくブロックが表示されないという問題がおこりました。現象としては WordPress の記事埋め込みブロックを使ってURLを入力しても違うURLの記事がiframeで読み込まれてしまい、引用ブロックの見た目だけが表示されるといった状態です。

原因は埋め込みを司る oEmbed という機能のキャッシュが WordPress の投稿のメタ情報として格納されているため、そのキャッシュ自体が不具合をおこしていました。

WordPress の埋め込みブロックのキャッシュをpost_metaから削除する時に探した情報は以下のとおりです。

https://bulkwp.com/support-forums/topic/deleting-_oembed_-postmeta/
https://blog.z0i.net/2015/09/oembed-unknown.html
https://seo-gold.com/understanding-wordpress-oembed-and-unknown-postmeta-entries/?cid=4429
https://core.trac.wordpress.org/ticket/17210

ワードプレスが急に重くなった時の調査フローと、一時キャッシュ(Trasient Cache)の削除方法

KUSANAGI 環境で弊社がホスティングしているWebメディアへダッシュボードも一般公開ページもアクセスしにくい状況発生しました。その後に Jetpack 経由でサイトがダウン通知が届いたので状況を把握することはできたので、その後にどのような手順をおって解決したかを解説します。 結論は、今回の僕の状況ではAMPプラグインのエラーをDBの一時キャッシュ(Trasient Cache)として保存しており、よってDBが肥大化し公開しているページやダッシュボードにつながりにくくなったという状況でした。 まずはサイトダウンしたことを知るところからはじまります。現在利用しているホスティング会社のサービスなどを利用して、サイトダウンの通知をうけるのもいいですし社内にインフラエンジニアさんがいてセルフホスティングしている場合も同様にサイトがダウンした通知を受ける導線を確保しましょう。 前述の方法が難しい場合は Automattic社 の Jetpack というプラグインを利用すると簡単にダウンしたときと復帰した時の通知をメールで受け取ることができます。
WordPress がダウンした時の通知メール
WordPress が復帰した時の通知メール
このように WordPress.com に登録し Jetpack 連携することで、サイトをモニターして異変が起きたときには通知をしてくれます。 通知が来た時に問題が一時的なもの、もしくは継続的なものかを判断します。今回は復帰した後もサイト自体にアクセスしようとするとローディングが途中で終わり表示されなかったり、表示されても数十秒以上続くという状態でした。 ここで考えられる問題は、多くの場合は下記のどちらかです。
  1. ハッキングもしくは攻撃されている
  2. 潜在的な問題が顕在化した
この問題を見つけることが特定と修復の第一歩なので、まずはダウンする寸前に誰かがなにかしたかということを明確にしなければいけません。 Jetpack にもアクティビティ機能がありますが、無料では制限があるため予算があわなければ プラグインの Simple History を利用するとよいでしょう。
Simple Historyの管理画面のスクリーンショット
前述のとおり、サイトダウンが発生した時に誰が何をしていたかを特定すればなにかヒントがあるので、その問題を潰すことができます。例えば特定の記事に画像をアップロードした、特定の設定をおこなったもしくは変更した、などお使いの WordPress のすべてのユーザの行動履歴を追えるため「なにもしてないのに止まった」というあるあるの証言を回避することもできます。 今回の僕の事例では新たに記事を投稿してからサイトがダウンしたため、投稿をしたことをフックになにかしらが起きたということが想定できます。 次に確認したのがサーバのエラーログです。 KUSANAGIの場合は配置(プロビジョニング)された各サイトの直下にlogディレクトリがあるのでその中身を確認し、特定の時間に何がおきたのかをさらに詳しく見ていきます。
https://column.prime-strategy.co.jp/archives/column_1179
KUSANAGIで困っと時の解決手引
それ以外の環境でもホスティングサービスによってはコントロールパネルでエラーログが見れるものもあるため、原因の特定をするためにエラーログからヒントを探すと良いでしょう。 また問題の原因がわかってもすぐに修正せずにいつでも現状に戻れるようにデータベースと公開ディレクトリのすべてのファイル(特にwp-contentの中はすべて)のバックアップをとっておきましょう。 KUSANAGIの場合はすでにコマンドラインから WordPress を操作できるツール WP-CLI がインストールされているため下記のコードでDBのバックアップファイルを作成することができます。
wp db export
WP-CLI のDBをエクスポートファイルを生成するコマンドの詳細
バックアップが完了したら原因と思われるところの対応をすすめていきましょう。 前述のとおり、今回はAMPプラグインが生成した一時キャッシュによりDBが肥大化してしまい2.1GBになっていたので、不要な列を削除することによって解決しました。
https://wp-doctor.jp/blog/2018/01/09/%E3%83%AF%E3%83%BC%E3%83%89%E3%83%97%E3%83%AC%E3%82%B9%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E8%82%A5%E5%A4%A7%E5%8C%96%E3%81%AE%E8%A7%A3%E6%B6%88%E6%96%B9%E6%B3%95/
WordPress データベースの肥大化を解消するための記事
また、wp db export をする前に一度データベースのサイズを見ておくとDB内の問題かどうかもわかるので下記のコマンドを実行して確認するとよいでしょう。
wp db size --tables
WP-CLI のDBを見るためのコマンドの詳細
次に肥大化している箇所を発見したら中身を確認し、不要なDBの列を削除していきます。今回の場合は下記のようにwp_optionsが2GBをこえる状態だったので中を見て該当の項目を削除しました。
wp db size –tables の表示
一時キャッシュの列を手動で消していくのも大変なので WP-CLI にあるwp transient を利用して一括で削除していきます。
WP-CLI で一時キャッシュを削除するコマンドの詳細
wp transient delete --all
上記の結果、DBは通常のサイズに戻りサイトのレスポンスも正常に戻りました。