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

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

ただいまの
回答率

89.72%

ボタンクリックでPHPのデータをJavaScriptに渡す

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 4,517

tarofess

score 125

現在画面に複数のリストが表示されており、それぞれのリストのボタンが押されたらそのリストに紐づいている値をJavaScriptに渡して処理をさせたいのですが、うまくできません。
コードは以下のようになっています。

<div class="contents">
  <ul>
    <?php foreach ($list as $data) { ?>
      <li class="contents_li">
        <img class="contents_image" src="<?php echo $data->image ?>"/>
        <p class="contents_title"><?php echo $data->title; ?></p>
        <a onclick="buy()" href="#"><input type="button" value="購入"></a>
        <input type="hidden" name="name" value=<?php echo $data->name ?>>
      </li>
    <?php } ?>
  </ul>
</div>
function buy() {
    // 受け取ったデータに合わせた処理
}


例えば<input type="hidden">のvalueの値をJavaScriptのbuy関数内でアラートで表示させるようにするにはどうやって書けばいいでしょうか?
onclickのbuy()に引数を持たせようとしてもうまくいきません。
jqueryは使わない方向で実現したいのですが、どうすればボタンクリックでPHPのデータをJavaScriptに渡すことができるでしょうか?
どなたか分かる方がいれば教えていただきです。よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+3

どうすればボタンクリックでPHPのデータをJavaScriptに渡すことができるでしょうか?

基本的な考え方として覚えておいてもらいたいのが、「そんなことはできません」です。
PHPはあくまでHTMLなり何なりWebブラウザで見るための情報を出力するだけだからです。
なので、どちらかというと「PHPでDBから取得した情報をHTMLに表示し、その情報をボタンクリックなどのイベントをもってjavascriptで受け取る」という考え方になります(表現の違いですが意味合いや理解が大きく違ってきます)

で、今回は$dataそれぞれにbuyがついているのでhiddenも必要なく、data->nameを渡すだけであれば下記で十分と思います。

<input type="button" value="購入" onclick="buy('<?php echo $data->name ?>')">
function buy(name) {
    // 受け取ったデータに合わせた処理
    alert(name);
}

追記:
おそらくbuyの引数でうまくいかなかったのは、単なる文字列を引数とするのに''で囲っていなかったからではないかと思います。
Webブラウザで表示後「ソースを表示」などして実際に出力されたHTMLを見てみると気づけるかもしれませんね。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/03/09 16:28

    ご回答ありがとうございます。
    PHPとJavaScriptの意味合い理解しました。
    ご指摘の通り''で囲っていなかったため引数で渡せていなかったようです。
    現在渡している引数がnameだけなのですが、これが5個となった場合もbuyの引数に5個分渡していけばいいでしょうか?
    「ソースを表示」で確認はあまりしていないので、「ソースを表示」で確認するクセをつけようと思います。

    キャンセル

  • 2018/03/09 16:45

    > 現在渡している引数がnameだけなのですが、これが5個となった場合もbuyの引数に5個分渡していけばいいでしょうか?

    ひとまず分かりやすいのであれば、それでも実現可能です。
    oncliclk="buy('a','b','c','d','e')"

    function buy(a,b,c,d,e){

    }

    ただ、これが本当に効率的かどうかは別問題です。
    渡したい項目が増えればその分、両方に追記していかなければならないからです。
    例えば現在のようにhiddenに対して一定のclassを与えておき、buyからはidを渡すだけにしておき、そのクラスの情報を取得するようにするとか、そのほうが変更が少なくなるかもしれません。

    oncliclk="buy(1)"

    <input type=hidden name="name" value="a" class="data_1">
    <input type=hidden name="status" value="00" class="data_1">
    <input type=hidden name="price" value="1000" class="data_1">

    function buy(id){
    var elements = document.getElementsByClassName("data_"+id);
    for(i = 0;i<elements.length;i++){
    alert(elements[i].value);
    }
    }

    ※ラジオボタンやチェックボックスの場合は工夫が必要。
     あと未検証なのでイメージだけ持ってください。


    > 「ソースを表示」で確認はあまりしていないので、

    想定通りに出力されているかどうかは画面を見ただけでは分かりませんよね。hiddenはソース上にしか出ないわけですし。
    必ず見るようにしてください。

    キャンセル

  • 2018/03/09 17:01

    ご提示のコードのようにclassを設定し、getElementsByClassNameでそれぞれのリストに紐付いた値を取得することができました。
    確かにこれだと後々修正が入ってもやりやすそうです。
    大変参考になりました。ありがとうございました。

    キャンセル

+1

ボタンに直接設定すればaタグは要らないですね
こんな感じで

<script>
window.addEventListener('DOMContentLoaded', function(e){
  Array.prototype.forEach.call(document.querySelectorAll('.contents input[type=button][value=購入]'),function(x){
    x.addEventListener('click',function(e){
      var v=e.target.parentNode.querySelector('input[type=hidden][name=name]').value;
      console.log(v);
    });
  });
});
</script>
<?PHP

$list=json_decode('[
  {"image":"hoge1.jpg","title":"hoge1","name":"fuga1"},
  {"image":"hoge2.jpg","title":"hoge2","name":"fuga2"},
  {"image":"hoge3.jpg","title":"hoge3","name":"fuga3"}
]');
?>
<div class="contents">
<ul>
<?php foreach ($list as $data) { ?>
<li class="contents_li">
<img class="contents_image" src="<?php echo $data->image ?>"/>
<p class="contents_title"><?php echo $data->title; ?></p>
<input type="button" value="購入">
<input type="hidden" name="name" value="<?php echo $data->name ?>">
</li>
<?php } ?>
</ul>
</div>

 追記

hiddenをつかわないでdata-*の方が汎用性は高いですね

<script>
document.addEventListener('click',function(e){
  var t=e.target;
  if(t.nodeName=="INPUT" && t.type=="button" && t.value=="購入"){
    console.log(t.dataset["name"]);
  }
});
</script>
<?PHP

$list=[
  (Object) ["image"=>"hoge1.jpg","title"=>"hoge1","name"=>"fuga1"],
  (Object) ["image"=>"hoge2.jpg","title"=>"hoge2","name"=>"fuga2"],
  (Object) ["image"=>"hoge3.jpg","title"=>"hoge3","name"=>"fuga3"]
];
?>
<div class="contents">
<ul>
<?php foreach ($list as $data) { ?>
<li class="contents_li">
<img class="contents_image" src="<?php echo $data->image ?>"/>
<p class="contents_title"><?php echo $data->title; ?></p>
<input type="button" value="購入" data-name="<?php echo $data->name ?>">
</li>
<?php } ?>
</ul>
</div>


datasetが利用できないブラウザが対象の場合は
getAttribute("data-name")のような書き方をしてください

 複数のデータを渡す

ひとつはそれぞれdata-*形式で値をわたしてやること

<input type="button" value="購入" data-name="<?php echo $data->name; ?>" data-title="<?php echo $data->title; ?>">
console.log(t.dataset["name"]);
console.log(t.dataset["title"]);

もう一つは、JSON形式で渡してやること

  <input type="button" value="購入" data-list='<?php echo '{"name":"'.$data->name.'","title":"'.$data->title.'"}'; ?>'>
/* 改良版 */
  <input type="button" value="購入" data-list="<?php echo htmlspecialchars(json_encode(["name"=>$data->name,"title"=>$data->title]));?>"></li>


この場合受けとった側はパースしてやる必要があります

    console.log(JSON.parse(t.dataset["list"]));

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/03/09 16:31

    ご回答ありがとうございます。
    そういう風にボタンに直接設定できるんですね。
    JavaScriptは色々な表現ができてこんがらがります...。
    data-nameの設定の場合だと、ボタンに一つのデータが紐づいていますが、データが複数ある場合はどのように設定すればいいでしょうか?

    キャンセル

  • 2018/03/09 16:50

    追記しておきました

    キャンセル

  • 2018/03/09 17:04

    jsonでそのように指定することもできるのですね。
    jsonの方が個人的に見やすいのでこっちの方がいいですね。
    色々なやり方があって大変参考になりました。
    ありがとうございます。

    キャンセル

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

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