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

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

新規登録して質問してみよう
ただいま回答率
85.48%
WordPress

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

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

4回答

11457閲覧

「Ajaxの中にAjax」は正しい処理ですか?

chacky

総合スコア16

WordPress

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

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

1グッド

3クリップ

投稿2019/02/11 22:33

編集2019/02/11 22:37

前提・実現したいこと

AjaxでのWordpress投稿システムの実装において、投稿後にその内容を表示させられないという問題が発生しました。

下記「該当のソースコード」にあるように、single.php を読むときに、投稿できている情報を使ってくれないという状況です。

自分なりの解決策として、下記「試したこと」にあるように、「Ajaxの中にAjax」という方法を考えたのですが、これは適切な方法ですか?

独学で不安なので、より適切な方法での実装を実現したいと思い質問させて頂きました。
宜しくお願いします。

該当のソースコード

まずこちらのPHPですが、
include locate_template( 'template-parts/single.php' );
と書いても、投稿後にその内容を表示させられないという問題が発生しました。(最後から12行目の部分です)

php

1/* nonceを出しておく */ 2add_action( 'wp_enqueue_scripts', 'my_enqueue_scripts' ); 3function my_enqueue_scripts() { 4 $handle_post_new = 'my_script_post_new'; 5 $jsFile_post_new= 'path/to/myscript_post_new.js'; 6 wp_register_script($handle_post_new, $jsFile_post_new, ['jquery']); 7 $action_post_new= 'my_ajax_action_post_new'; 8 wp_localize_script($handle_post_new, 'MY_AJAX_post_new', [ 9 'api' => admin_url( 'admin-ajax.php' ), 10 'action' => $action_post_new, 11 'nonce' => wp_create_nonce( $action_post_new ), 12 ]); 13 wp_enqueue_script($handle_post_new); 14} 15 16/* 投稿する */ 17add_action( 'wp_ajax_my_ajax_action_post_new', 'my_ajax_event_post_new' ); 18function my_ajax_event_post_new() { 19 20 $action_post_new = 'my_ajax_action_post_new'; 21 22 // nonceがただしい 23 if( check_ajax_referer($action_post_new, 'nonce', false) ) { 24 25 // データ受け取り 26 $post_new_title = esc_html( $_POST['post_new_title'] ); 27 $post_new_content = strip_tags( $_POST['post_new_content'], "<br>" ); 28 $post_new_meta_img = esc_html( $_POST['post_new_meta_img'] ); 29 30 // データ更新 31 $post_value = array( 32 'post_type' => 'post', 33 'post_author' => get_current_user_id(), 34 'post_title' => $post_new_title, 35 'post_content' => $post_new_content, 36 ); 37 $insert_id = wp_insert_post($post_value); // 投稿してそのIDを取得 38 if($insert_id) { 39 update_post_meta($insert_id, 'post_meta_img', $post_new_meta_img); 40 } else { 41 die('失敗しました。'); 42 } 43 44 // 出力 45 include locate_template( 'template-parts/single.php' ); 46 47 } 48 // nonceがおかしい 49 else { 50 51 die('失敗しました。'); 52 53 } 54 55 die(); 56}

ちなみにjQueryはこうです。
「.container」の中身を、新しい投稿内容を使った single.php に入れ替えることが目的でした。

jQuery

1$(document).on("click",".post_submit", function(){ 2 3 var post_new_area = $('.container'); 4 var post_new_title = $('#post_new_title').text(); 5 var post_new_content = $('#post_new_content').html(); 6 var post_new_meta_img = $('#post_new_meta_img').val(); 7 8 $.ajax({ 9 url: MY_AJAX_post_new.api, 10 type: 'POST', 11 data: { 12 action: MY_AJAX_post_new.action, 13 nonce: MY_AJAX_post_new.nonce, 14 post_new_title: post_new_title, 15 post_new_content: post_new_content, 16 post_new_meta_img: post_new_meta_img, 17 } 18 }) 19 // 成功したとき 20 .done(function( response_post_new ) { 21 var $articleOuter_post_new = post_new_area; 22 var $response_post_new = response_post_new; 23 $articleOuter_post_new.html(''); 24 $articleOuter_post_new.html( $response_post_new ); 25 }) 26 // 失敗したとき 27 .fail(function( response_post_new ) { 28 alert('失敗しました。'); 29 }); 30 31});

試したこと

上述のソースコードではできず、冒頭に書いたように「Ajaxの中にAjax」という方法を考えました。それがこちらの《変更➀》と《変更➁》です。

《変更➀》

PHP

1 // 出力 2 include locate_template( 'template-parts/single.php' );

↓次のように変更し、投稿されたslugを返すようにしました。

PHP

1 // 出力 2 $str = get_page($insert_id); 3 echo $str -> post_name;

《変更➁》

jQuery

1 // 成功したとき 2 .done(function( response_post_new ) { 3 var $articleOuter_post_new = post_new_area; 4 var $response_post_new = response_post_new; 5 $articleOuter_post_new.html(''); 6 $articleOuter_post_new.html( $response_post_new ); 7 })

↓次のように変更し、投稿されたslugからその記事にアクセスするようにしました。これが「Ajaxの中にAjax」という処理です。これは適切な方法ですか?

jQuery

1 // 成功したとき 2 .done(function( response_post_new ) { 3 $.ajax({ 4 type: 'GET', 5 url: 'http://example.com/post/'+response_post_new, 6 dataType: 'html' 7 }) 8 .done(function(data) { 9 var contentItems = $(data).find('.container'); 10 $('.container').html(contentItems); 11 }) 12 .fail(function () { 13 alert('失敗しました。'); 14 }); 15 })

こちらの「Ajaxの中にAjax」という方法でも、投稿後にその内容を表示できたことはできたのですが、、不安が残ります。

他にもおかしな点がございましたらご指摘頂けますと幸いです。(nonceのチェック方法や変数名など、とにかく独学で不安です。)

質問は以上です。

改めまして、どうぞ宜しくお願い致します。

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

使っているものは全て最新です。

Wordpress → 5.0.3
PHP → 7.3.2

ikedas👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kei344

2019/02/12 02:24

single.phpの内容によります。
chacky

2019/02/12 05:31

といいますと、逆にどんな内容だといけませんか? single.php は <?php the title();> のような普通の関数を使っているだけの内容ですが、この場合だといかがですか?Ajaxは2回やるべきではないでしょうか?
guest

回答4

0

とりあえず locate_template は引数で include をする設定があるのでやるならそっちで。
というかget_template_partで取得しましょう。

【locate_template – WordPress私的マニュアル】
https://elearn.jp/wpman/function/locate_template.html

【Wordpressでテンプレートファイルをロードする5つの方法とその違い - Qiita】
https://qiita.com/ironsand/items/7fce685abdbf18a98c71


で、single.phpは「single.phpを表示するときに既に実行されているはずの物」が実行されていなければ表示されません。

single.php は <?php the title();> のような普通の関数を使っているだけの内容ですが、この場合だといかがですか?

WP_Queryが実行されていて、グローバル変数$GLOBALS['post']に値が入っていなければ表示されません。$insert_idに入った値をどうにかして呼び出さないと表示されません。
get_template_partの前でsetup_postdata($post);するとか)

投稿2019/02/12 05:46

編集2019/02/12 06:00
kei344

総合スコア69400

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chacky

2019/02/12 06:34 編集

ありがとうございます。仰る通り get_template_part を使います。 そして確認事項として挙げて頂いたこちらですが、 ・WP_Queryが実行されているかどうか ・グローバル変数$GLOBALS['post']に値が入っているかどうか これらの確認方法と、これらがないときの対処方法としてはどうすべきでしょうか?(おそらく「setup_postdataを使え」が対処方法としてのアドバイスだと思うのですが、使いどころなどが理解できませんでした。 get_template_part の手前で使えばいいのかと思ったのですがそうではないようでしたし。)
guest

0

「Ajaxの中にAjax」は正しい処理ですか?

質問文を最後まで読めば何となく意味はわかりますが、
要するにAjax1で不足しているデータがあるから、続けてAjax2を発射したいと言ってるわけですね。

問題の本質はJavaScript名物の非同期処理のネストだと思うので
「Ajaxの中にAjax」だとちょっともやっとしますね。
コールバック関数の入れ子による「コールバック地獄」ですね。


さて、今回の質問は「これで動いているが、良い実装なのか悪い実装なのかわからん」といったところでしょうか。
動けばなんでもええねんと言ってる輩と比べれば好ましい思想です。

Aの結果を使ってBの結果を取得しにいくためには、
上の関数スコープで仮引数や変数を定義して、
その中で作った関数をコールバック関数として利用する設計にするのはよくある手口で、
決して悪くはない、普通といった感じです。

処理が増えると延々とそこの関数内でネストしていくことになるので、
ゆくゆくを考えると「コールバック地獄」に関する理解や知識、プログラミングテクニックが必要になってくるでしょう。

コードをネストせず同じラインで一撃で書くなら下記の記事はかなり良かったです。
(ただし、超難解であることと、Promise特有の値を持ち込む辺りをうまく書くには色々とリンク先からたどって勉強する必要があるでしょう。)
複数のAjaxタスクをシーケンシャルに実行するには?

投稿2019/02/12 06:05

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chacky

2019/02/12 06:45

高ランキングの方々にご指導頂き大変恐縮しております。ありがとうございます。 そうおっしゃって頂けますと少し安心できます。 改善方法についても具体的な参考ページをどうもありがとうございます。少し難しそうですが、お蔭さまであと一時間くらい粘ってみたいと思えました。
guest

0

「Ajaxの中にAjax」という方法を考えたのですが、これは適切な方法ですか?

コードきっちり見たわけではないですけど、「Ajaxで得た情報を使って次のAjaxで処理を行う」のはないわけではないです。
やりようによっては1回で済ませられるように考えた方がいいかな・・・くらいですね。

「最終的にどのような結果を返したいか」というところから考えると良いです。
もしかしたら重ねなくても1発で済ませられるかもしれませんし。

投稿2019/02/12 00:03

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chacky

2019/02/12 05:39

まぁおかしくはないんですね。ありがとうございます。 最終的な結果は投稿の内容の表示ですね。そんなに難しいものでもなさそうで、1発でできそうな感じがします。というか質問の「該当のソースコード」の方(1発でできると思って書いたんですが)で、なぜでできないのか理由も良く分かりません。
m.ts10806

2019/02/12 06:12 編集

「正しいかどうか」でいうと「想定通りに動かせているなら正しい」となります。 それが効率的か、適切か、現在主流の組み方に乗っているかは別の話です。今回は「正しいかどうか」という質問なので「動いてるなら問題ないのでは?強いてなら1発でできるように考慮した方がいいけど」くらいのものです。 きちんと想定したデータが取れているかどうかはJavaScript側でconsole.log()して確認されたほうがいいですね。
chacky

2019/02/12 06:45 編集

なるほど、console.log() してみたところ、大丈夫なようでした。どうもありがとうございます。 ひとまずAjaxを2回行う方法については問題なさそうで一安心です。 あとは1発でできそうな方法をkei344様やmiyabi-sun様がアドバイスして下さったので、そちらの方でもう少し調べてみたいと思います。
m.ts10806

2019/02/12 06:40

そうですね。そこは回答の後半に書いた「最終的にどのような結果を返したいか」から考えて調整してください。
chacky

2019/02/12 06:42

ありがとうございます。頑張ってみます。
guest

0

Ajaxで得た情報を使って次のAjaxで処理を行う場合は遅延処理が必要です。要はAjaxを入れ子にすると
通常のPHPのように変数を受け渡しで処理してくれませんので、受け取るまで実行を手動で遅らせらないと
空っぽのデータで処理を始めることになったりと、想定外のバグに遭遇します。

はじめてajaxを使うときに知りたかったこと https://qiita.com/nekoneko-wanwan/items/bedc0e826c0842ca0b11
Ajaxが順序通り実行できない https://teratail.com/questions/128352

投稿2019/02/12 00:46

FKM

総合スコア3633

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chacky

2019/02/12 05:37

必要な情報は投稿の内容です。 投稿についてのdoneの中に2回目のAjaxを書いてそこで投稿の内容を取得しているのですけど、遅延は必要でしょうか? 内容の取得では、リンク先にあるような「ajax()で返ってきたデータをそのまま使いたい」(https://qiita.com/nekoneko-wanwan/items/bedc0e826c0842ca0b11#ajax%E3%81%A7%E8%BF%94%E3%81%A3%E3%81%A6%E3%81%8D%E3%81%9F%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E3%81%9D%E3%81%AE%E3%81%BE%E3%81%BE%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84)をやっているつもりなのですが、いかがでしょうか。 というのは、 done(function( response_post_new ) の response_post_new の部分です。
FKM

2019/02/12 05:49 編集

自分もその記事を読み返してテスト環境で試してみたのですが、$.Ajaxだと自動で遅延処理を行ってくれるみたいですね。なので、既に遅延処理はされている状態です。 試しに、$.postや$.getに書き換えるとレスポンスを受け取る前に、次のAjaxを実行してしまうはずです(自分の業務でそのバグやらかしてました…)。
chacky

2019/02/12 06:33

そうでしたか。ではAjaxを2回やるという方法については、特に心配はなさそうですね。 参考になる情報ばかりでした。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問