質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • PHP

    21341questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • WordPress

    7668questions

    WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

[WordPress] Advanced Custom Fieldsでget_field使用時に上手く値が取れない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 990

Yashichi

score 26

追記2

DB未保存のカスタムフィールドの値を取得するのに、
$_POST["fields"]["フィールドキー"](フィールドキーは$_POST["fields"]をvar_dumpすると取れます)を使うことが分かりました。これを使えば投稿の新規作成時でもカスタムフィールドの値が取れます。

しかし、これを使うと、下記のように全ての値が
新規作成時の投稿のカスタムフィールドのものと同じになってしまいます。

array(2) {
  ["field_5a50f527cbddc"]=>
  string(3) "yes"
  ["field_5a52618c69f7f"]=>
  string(0) ""
}
array(2) {
  ["field_5a50f527cbddc"]=>
  string(3) "yes"
  ["field_5a52618c69f7f"]=>
  string(0) ""
}
array(2) {
  ["field_5a50f527cbddc"]=>
  string(3) "yes"
  ["field_5a52618c69f7f"]=>
  string(0) ""
}
array(2) {
  ["field_5a50f527cbddc"]=>
  string(3) "yes"
  ["field_5a52618c69f7f"]=>
  string(0) ""
}
array(2) {
  ["field_5a50f527cbddc"]=>
  string(3) "yes"
  ["field_5a52618c69f7f"]=>
  string(0) ""
}

追記

mizさんに教えていただきましたこちらのページ(そのページに載ってたリンクも含む)を見て、
カスタムフィールドの値を取得するタイミングとアクションを起こすタイミングが上手くいっていないということまでは分かりました。
(そこからが分かりません..)
■ACF | acf/save_post
https://www.advancedcustomfields.com/resources/acf-save_post/
■Why isn't acf/save_post firing? - ACF Support
https://support.advancedcustomfields.com/forums/topic/why-isnt-acfsave_post-firing/

前提・実現したいこと

WordPressで投稿を新規作成したタイミング(投稿を更新したりしたタイミングも含む)で、
その投稿のタイトルや投稿時間をJSONファイルに突っ込むという実装をおこなっています。

投稿の新規作成時に
その内容にACFで作成したラジオボタンの値も含めたいというのが実現したいことです。

発生している問題・エラーメッセージ

投稿を新規作成したタイミングだと、ラジオボタンの値が反映されません。
しかし、投稿を更新したりすると値が反映されるようになります。

JSONの値(正しい形)
{
"title":"test",
"start":"2018-01-08 03:53:31",
"url":"http:test.jp/static_directory/archive/123",
"value":ok
}


値の一番下"value"にACFのget_fieldで取得した値が入ります。
ラジオボタンにはokとnoを設定しているのでそのどちらかが入るはずです。

JSONの値(現状)
{
"title":"test",
"start":"2018-01-08 03:53:31",
"url":"http:test.jp/static_directory/archive/123",
"value":false
}


現状はfalseになっています。

該当のソースコード

<?php

/**
 * 投稿が行なわれたタイミングでJSONファイルを生成するフック
 *
 * @param string $new_status 新しいステータス
 * @param string $old_status 以前のステータス
 * @param object $post 該当する投稿オブジェクト
 */
function makes_json($new_status, $old_status, $post) {


if (function_exists('xdebug_disable')) {
    xdebug_disable();
}

    if($new_status == 'publish') {
        switch($old_status) {
            case 'draft':
            case 'pending':
            case 'auto-draft':
            case 'future':
            case 'publish':
            case 'inherit':
                // Get ALL Posts
                $args = array(
                    'numberposts' => -1,
                    'orderby' => 'post_date',
                    'order' => 'DESC',
                );
                $posts = get_posts($args);
                $homeUrl = 'http:test.jp/static_directory';
                if (count($posts) == 0) { return; }
                foreach ($posts as $post) {
                        $cal_fields = get_field("switch", $post->ID);                
                        $output_json[date('Ym', strtotime($post->post_date))][] = array(
                            'title' => $post->post_title,
                            'start' => $post->post_date,
                            'url' => $homeUrl . '/archives/' . $post->ID,
                            'value' => $cal_fields,
                        );
                }

                // Get Upload Directory
                $upload_dir = wp_upload_dir();
                $upload_dir = $upload_dir['basedir'].'/json';

                // Create Directory
                if (file_exists($upload_dir) == FALSE) {
                    mkdir($upload_dir, 0777);
                }

                // Delete All JSON Files
                array_map('unlink', glob($upload_dir.'/*.json'));

                // Create JSON Files
                foreach ($output_json as $key => $value) {
                    file_put_contents($upload_dir . '/'.$key.'.json', json_encode($value));
                }
                break;
        }
    }
}
add_action('transition_post_status', 'makes_json', 10, 3);

試したこと

この自作関数内のコードの一部分(file_put_contentsなどファイルやディレクトリの作成を除く)を投稿一覧ページのPHPファイルに移してみると、
投稿の新規作成時の段階で、ラジオボタンの値をちゃんと取ることができました。

デバッグとして、get_field()でラジオボタンの値を取得するタイミングをズラすために
sleep()を指定しましたが、効果はありませんでした。

その他var_dump()を使って投稿一覧ページでテストしたときの
$postの値と比較をしたりしましたが、
比較して異なる大きな部分としては、get_field()が、
投稿の新規作成時に働くか否かという部分でした。

補足情報(言語/FW/ツール等のバージョンなど)

PHP 7.1.9
WordPress 4.9

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miz

    2018/01/08 07:03

    ACFで作成したカスタムフィールドの値が保存されるタイミングと使用したいアクション実行のタイミングの順番の問題かと思われます。参考になりそうなページがあったので、よろしければどうぞ。 https://support.advancedcustomfields.com/forums/topic/why-isnt-acfsave_post-firing/

    キャンセル

  • Yashichi

    2018/01/08 13:00 編集

    @miz さん
    ありがとうございます。このページによれば、"transition_post_status"を使うのは良いけど、投稿新規作成時の投稿取得の方法が通常のget_fieldではないんだよってことが書いてあるんですかね...。
    カスタムフィールドの値が保存されるタイミングというのがイマイチ分かりませんでした..(´;ω;`) get_fieldだと$_POSTに値が登録された後のものが取得できて、$_POST['acf']['fields_01234']を使うと値が登録される前のものが取得できるってことなんでしょうか?
    (そこに関しても違いがわからないのですが(´;ω;`))

    キャンセル

回答 2

checkベストアンサー

+1

save_postを使ったらどうでしょうか。
https://codex.wordpress.org/Plugin_API/Action_Reference/save_post

追記

無視?
何か反応あってもよくない?

get_fieldやとDBに保存したものしか取れんのが原因。
だからこう。

$cal_fields = get_field("switch", $post->ID);
↓
$cal_fields = $_POST['fields']['フィールドキー'];

これでもええんちゃうかと思うけど?

function makes_json( $post_id, $post, $update ) {
if (function_exists('xdebug_disable')) {
   xdebug_disable();
}
if( $post->post_status === 'publish' ) {
                // Get ALL Posts
                $args = array(
                    'numberposts' => -1,
                    'orderby' => 'post_date',
                    'order' => 'DESC',
                );
                $posts = get_posts($args);
                $homeUrl = 'http:test.jp/static_directory';
                if (count($posts) == 0) { return; }
                foreach ($posts as $post) {
                        $cal_fields = get_field("switch", $post->ID);                
                        $output_json[date('Ym', strtotime($post->post_date))][] = array(
                            'title' => $post->post_title,
                            'start' => $post->post_date,
                            'url' => $homeUrl . '/archives/' . $post->ID,
                            'value' => $cal_fields,
                        );
                }

                // Get Upload Directory
                $upload_dir = wp_upload_dir();
                $upload_dir = $upload_dir['basedir'].'/json';

                // Create Directory
                if (file_exists($upload_dir) == FALSE) {
                    mkdir($upload_dir, 0777);
                }

                // Delete All JSON Files
                array_map('unlink', glob($upload_dir.'/*.json'));

                // Create JSON Files
                foreach ($output_json as $key => $value) {
                    file_put_contents($upload_dir . '/'.$key.'.json', json_encode($value));
                }
       }
}
add_action('save_post', 'makes_json', 99, 3);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/08 14:14 編集

    このsave_post関数と現在使ってるtransition_post_statusの違いがイマイチ分かりません(´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥`)

    キャンセル

  • 2018/01/08 14:37

    コーデックス読めば解ると思うけど?
    カスタムフィールドの中身の有無による結果の違い

    save_postはDBに保存した後に実行するからget_fieldで値が取れる

    transition_post_statusは未保存の場合、値が無い所へget_fieldを実行するので何も取れない

    保存前にカスタムフィールドの値を取りたいなら$_POSTから取る。
    だから
    $cal_fields = get_field("switch", $post->ID);

    $cal_fields = $_POST['fields']['フィールドキー'];

    save_postでもどっちでも好きな方でどうぞ。

    キャンセル

  • 2018/01/08 14:55

    ありがとうございます。
    $_POST['fields']['フィールドキー']を使うと保存前のカスタムフィールドの値が取得できることは確認できました。しかしながら、$_POST['fields']でvar_dumpしてみると、
    あらゆるカスタムフィールドの値が、新規投稿したときのカスタムフィールドの値と同じになってしまいます。

    これは、DB未保存の値の取得($_POST["fields"]["フィールドキー"])だけでは足りないということなのでしょうか。。

    キャンセル

  • 2018/01/08 15:22 編集

    じゃあ有無を確認したら?
    if( ! empty( get_field("switch", $post->ID) ) ) {
    $cal_fields = get_field("switch", $post->ID);
    } else {
    $cal_fields = $_POST['fields']['フィールドキー'];
    }
    get_fieldで何か取れればそれにして何も取れなければ$_POSTから。

    キャンセル

  • 2018/01/08 16:30

    ありがとうございます。
    最終的に、今度は投稿の更新時に値が反映されなくなってしまって、二回更新したらそれができるという状態になりました。一旦save_postを使ったコードに書き換えてみようと思います。

    キャンセル

  • 2018/01/08 16:57

    >今度は投稿の更新時に値が反映されなくなってしまって

    『今度は』じゃなくてそれは最初からでは?

    キャンセル

  • 2018/01/08 17:02

    最初は投稿の「新規作成時のみ」値が反映されなかったので、という意味ですね

    キャンセル

  • 2018/01/08 17:12

    提示されたコードだと記事の更新時も更新前の値を持って来るから『今度は』ではなく最初から。
    一度更新すると値を書き換えるがその時は取得できず、その後の更新で書き換えた値を取得する。
    自分が示した改善策が悪いのではなく、貴方の書いたコードがそうさせているだけ。
    だから『今度は』ではない。

    キャンセル

  • 2018/01/08 17:23

    switch文に'publish'も入れてるからってことですよね。

    現状、そもそもswitch文が、コード全体を囲んでいるから、
    その範囲をカスタムフィールドの値取得部分にまで縮めた上で、
    switchの分岐を"publish"とそれ以外に分けてみます。

    ありがとうございます。

    キャンセル

  • 2018/01/08 17:37

    >switch文に'publish'も入れてるからってことですよね
    多分関係ないと思うけど

    キャンセル

  • 2018/01/08 18:02

    すみません、記事の更新時も更新前の値を持ってくるというのは、foreachの終わりにreset_postdataを使ってないからってことなんでしょうか..

    キャンセル

  • 2018/01/08 18:54

    2つ前のコメントに書いてますが?

    そもそも新規投稿でget_fieldで値が取れないのは【DBに保存する前】だから。
    更新の場合も更新した値を【保存する前】にget_fieldを実行して取得しているからファイルの中身に変化が無い。
    その次に更新を押した時に【現在保存されている値】を取得してファイルを生成するするから二回更新したら反映したように感じるだけ。

    キャンセル

  • 2018/01/08 20:00

    こうすれば?
    if( get_the_ID() === $post->ID ) {
    $cal_fields = $_POST['fields']['フィールドキー'];
    } else {
    $cal_fields = get_field("switch", $post->ID);
    }
    get_the_ID()の結果と$post->IDが同じ場合は$_POSTからカスタムフィールドを取ってそれ以外は保存された値を取る。

    キャンセル

  • 2018/01/08 20:41

    うまくいきました...

    get_the_ID()が取得するIDは現在の投稿のものだから、つまり最新の投稿で
    $post->IDで取得できるIDはまさしく自分が今編集・投稿したもののIDだから、

    これが一致する場合ってのは新規作成の投稿で
    一致しない場合ってのはそれ以外の例えば更新とかになるってことですね

    すみません、ありがとうございます...

    キャンセル

  • 2018/01/08 20:58

    新規作成だけではなく現在更新中のポストも含む意味ですが。
    現在開いている記事入力画面の記事のポストIDを取って一致する記事は$_POSTからカスタムフィールドを取る、そうではない記事はDBから取る。
    だから古い記事でもポストIDが一致したら$_POSTから取る、これで更新時も対応可能ってこと。

    キャンセル

0

回答ではない補足です。

https://support.advancedcustomfields.com/forums/topic/why-isnt-acfsave_post-firing/

こちらのURLで言及のある「field key of your custom field」の管理画面からの確認方法です。

  1. 管理画面 > カスタムフィールド > 「フィールドグループを編集」画面を開く
  2. 「表示オプション」を開いて、「フィールド Show Field Key:」で「はい」を選択

これで各フィールドのフィールドキーが一覧に表示されるようになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/08 20:43

    関数で確認してました... ありがとうございます

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • PHP

    21341questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • WordPress

    7668questions

    WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。