かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

WordPress REST API を無効化する

WordPress v6.1.1

rest_authentication_errors フィルターを使う

apply_filters( 'rest_authentication_errors', WP_Error|null|true $errors )
This is used to pass a WP_Error from an authentication method back to the API.

Authentication methods should check first if they’re being used, as multiple authentication methods can be enabled on a site (cookies, HTTP basic auth, OAuth). If the authentication method hooked in is not actually being attempted, null should be returned to indicate another authentication method should check instead.
$errors
WP_Error if authentication error, null if authentication method wasn't used, true if authentication succeeded.
cf. rest_authentication_errors | Hook | WordPress Developer Resources

  • null … 認証のチェックがまだされていない
  • boolean … 認証のチェック済み
    • true … 認証に成功
    • false … 認証に失敗
  • WP_Error … エラーが発生

WordPressREST API で認証を確認するために通過する箇所へのフィルター
この箇所で WP_Error を返すことで全ての API をエラーにすることができるという事っぽい

<?php
function disable_rest_api() {
  return new WP_Error(
    'disabled',
    'REST API is disabled.',
    array( 'status' => rest_authorization_required_code() )
  );
}
add_filter( 'rest_authentication_errors', 'disable_rest_api' );

API にアクセスするとエラーメッセージが返ってくる

/wp-json/wp/v2/posts

{"code":"disabled","message":"REST API is disabled.","data":{"status":403}}

/wp-json/wp/v2/users

{"code":"disabled!","message":"REST API is disabled.","data":{"status":403}}

できた ( ᐢ˙꒳​˙ᐢ )

📝 Tips: WordPress v4.7.0 から rest_enabled を使う方法は非推奨になっている

<?php
add_filter( 'rest_enabled', '__return_false' );

上記のコードは下記の notice が表示される

Deprecated: フック rest_enabled は、バージョン 4.7.0 から非推奨になりました ! 代わりに rest_authentication_errors を使用してください。 REST API を完全に無効化することはできなくなりました。代わりに rest_authentication_errors フィルターを使って API へのアクセスを制限できます。

📝 Tips: rest_endpoints フィルターで API をカスタマイズする方法

rest_endpoints フィルターで REST API のエンドポイントをカスタマイズできる。その中で API を無効化にする方法

<?php
function filter_rest_endpoints() {
  if ( isset( $endpoints['/wp/v2/users'] ) ) {
    unset( $endpoints['/wp/v2/users'] );
  }
  if ( isset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] ) ) {
    unset( $endpoints['/wp/v2/users/(?P<id>[\d]+)'] );
  }
  return $endpoints;
}
add_filter( 'rest_endpoints', 'filter_rest_endpoints', 10, 1 );

とりあえずまるっと無効化してしまうなら rest_authentication_errors フィルターで良さそう

おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]

PHP class プロパティ定義で Constant expression contains invalid operations

PHP の class を定義してたら PHP Fatal error: Constant expression contains invalid operations in … というエラーが発生してなんでや!となったのでメモ

環境

Constant expression contains invalid operations エラーになった例

<?php
class MyClass {
  private static $resourcePath = get_template_directory() . '/resources';
  public static setResourcePath(string $path) {
     if ( !is_dir($path) ) {
      throw new \InvalidArgumentException('Invalid resource path');
    }
    self::$resourcePath = $path;
  }  
  
  public function __construct() {}
}

プロパティに wordpress のテーマへのパスを持ったクラスを作っていた所 private static $resourcePath = の箇所で上記の PHP Fatal error: Constant expression contains invalid operations in … エラーが発生しました

PHP のクラスのプロパティの初期値は定数しか取れない

宣言時に初期値を設定することもできますが、 初期値は 定数 値でなければなりません。
cf. PHP: プロパティ - Manual

つまりプロパティに関数の実行が入っているのが良くなかった。と言うことっぽい

1. 定数にすればOK

定数にしてしまえば問題はない。(class 内でプロパティが定義される前に定数になっているからだと思われる)

<?php
define('RESOURCES_DIR', get_template_directory() . '/resources');
class MyClass {
  private static $resourcePath = RESOURCES_DIR;
  // ...
  
  public function __construct() {}
}

2. コンストラクタで初期値を設定する

そもそも class プロパティの初期値を設定しなければ問題にならない
static プロパティの場合インスタンス化しないと初期値が設定されないのが問題にはなるけれど…

<?php
class MyClass {
  private static $resourcePath;
  // ...
  
  public function __construct() {
    if ( empty(self::$resourcePath) ) {
      self::$resourcePath = get_template_directory() . '/resources';
    }
    // … 
  }
}

🙅 変数は class プロパティに設定できない

define で定義した定数はOKだが、変数は エラーが発生になる

<?php
class MyClass {
  private static $resourcePath = $resource_dir;
  // ...
  public function __construct() {}
}

=> Constant expression contains invalid operations
(そもそも変数のスコープの問題があるのが…)

 
三畳紀ぶりに PHP を触っているので全てを忘れている…
ドキュメントの探し方のコツも忘れているので、これじゃない情報が検索で出てきすぎて PHP つらい…

おわり₍ ᐢ. ̫ .ᐢ ₎


[参考]

最近疲れが全然取れなくて困ってる…

WordPress 多言語化対応 Bogo で locale の投稿だけ取得したい

WordPress の多言語化対応プラグイン Bogo を使っている時に get_postsWP_Query を使って投稿を取得すると全ての言語の投稿が取得されるので、現在の locale (言語) に合うものだけ取得したいのメモ

'suppress_filters' => false パラメーターを使う

get_posts のデフォルトのパラメタでは 'suppress_filters' => true が指定されているためです。これを false に指定することで Bogo のフィルタが働き、特定の(デフォルトでは現在の)言語の投稿のみ取得できるようになります。
cf. Bogoプラグイン使用時、get_postsで投稿を取得すると全部の言語が対象になる | WordPress.org 日本語

<?php
$args = [
  'post_type' => $post_type,
  'posts_per_page' => -1, // 全件取得
  // …
  'suppress_filters' => false, // ← これを追加
];
get_posts( $args );

これで現在の言語の投稿だけが取得できるようになりました!

特定の言語で取得したい時は lang パラメーターを合わせて使う

<?php
$args = [
  'post_type' => $post_type,
  'posts_per_page' => -1, // 全件取得
  // …
  'suppress_filters' => false,
  'lang' => 'ja', // get_locale()
];
get_posts( $args );

📝 get_postsWP_Query のラッパー

get_posts は内部で WP_Query を呼び出している

get_posts()WP_Query クラスを利用して投稿を取得します。この関数で使えるパラメータについては、WP_Query ドキュメンテーションthe parameters section をごらんください。
cf. テンプレートタグ/get posts - WordPress Codex 日本語版

<?php
function get_posts( $args = null ) {
  // …
  $get_posts = new WP_Query();
  return $get_posts->query( $parsed_args );
}

cf. WordPress/post.php at 9c56cf2cf70093a0c5a75c95440c7c4c2351f775 · WordPress/WordPress · GitHub

所管

get_posts を使うとデフォルトでは言語に関わらず全ての投稿が取得されてどうやるんだ?ってなってたらフォーラムに作者の Takayki Miyoshi (@takayukister) さんが回答していて 助かりました。
Bogoプラグイン使用時、get_postsで投稿を取得すると全部の言語が対象になる | WordPress.org 日本語

WordPress 関連検索に出てきまくるので欲しい情報に辿り着く && 取捨選択がむずすぎる…


[参考]

ヴィンランド・サガ時代の言語関係ってどうなってるんだろう?イングランドゲール語???