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

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

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

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

Q&A

解決済

2回答

639閲覧

foreach( $array as $key => $value ) において、ループの最中に $array を変更したい

ikatako

総合スコア270

PHP

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

0グッド

1クリップ

投稿2020/11/11 03:11

編集2020/11/11 03:28

###実現したいこと
PHPのforeachで、一回目のループで取得した値を、二回目のループにねじ込みたいです。

###ソースコード・問題点
次の関数print_thread_datas()をご覧ください。
引数$arg_wrapperをループし、一回目のループで掲示板のレコードを取得し、二回目のループでコメントのレコードを取得するという関数です。

ここでコメントの取得に際して問題があります。
コメントの取得では、掲示板のレコードだけが持つ値top_comment_idが必要となっており、二回目のループにそれをねじ込みたいのですが、なぜかできません。

php

1$arg_wrapper = [ 2 // thread エリアに thread_id=1 の掲示板を出力するための引数 3 'thread' => [ 4 'process' => 'pjax', 5 'arg' => ['type'=>'thread', 'thread_id'=>1], 6 ], 7 // comments エリアにthread_id=1の掲示板へのコメントを出力するための引数 8 'comments' => [ 9 'process' => 'pjax', 10 'arg' => ['type'=>'comment', 'thread_id'=>1, 'limit'=>2, 'last_comment_id'=>20, 'order_by'=>'popular_order'], 11 ] 12]; 13$results = print_thread_datas( $arg_wrapper ); 14var_dump($results); 15 16// $arg_wrapperに応じてスレッドのタイトルとコメントリストを返す 17function print_thread_datas( $arg_wrapper ) { 18 $results = []; 19 foreach ( $arg_wrapper as $print_area => $info ) { 20 21 // レコードを取得 22 $arg = $info['arg']; 23 $rows = get_rows( $arg ); 24 if ( $print_area === 'thread' ) { 25 $results[$print_area] = $rows[0]; // thrread は一件だけ 26 } else { 27 $results[$print_area] = $rows; // comments は複数 28 } 29 30 // thread の場合 31 if ( $print_area === 'thread' ) { 32 // コメントリストの先頭に固定されるコメントを取得するための引数をねじ込む 33 $top_comment_id = $rows[0]['top_comment_id'] ?? ''; 34 if ( $top_comment_id ) { 35 $arg_wrapper['comments']['arg']['top_comment_id'] = $top_comment_id; 36 } 37 38 // ねじ込めたことを確認 39 var_dump($arg_wrapper); 40 } 41 } 42 return $results; 43} 44 45 46// $argに応じてデータベースからレコード($rows)を取得する例 47function get_rows( $arg ){ 48 $rows; 49 $type = $arg['type']; 50 if ( $type === 'thread' ) { 51 $rows = [ ['type'=>'thread', 'thread_id'=>1, 'title'=>'1の掲示板', 'author_id'=>100, 'author_name'=>'鈴木', 'top_comment_id'=>99] ]; 52 } elseif ( $type === 'comment' ) { 53 $rows = [ 54 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>30, 'content'=>'こんにちは', 'author_id'=>200, 'author_name'=>'佐藤'], 55 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>40, 'content'=>'さようなら', 'author_id'=>300, 'author_name'=>'山田'] 56 ]; 57 // コメントリストの先頭に固定されるコメントを取得 58 if ( isset( $arg['top_comment_id'] ) ) { 59 $top_comment = ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>99, 'content'=>'先頭に固定されるコメントです', 'author_id'=>400, 'author_name'=>'高橋']; 60 array_unshift( $rows, $top_comment ); 61 } 62 } 63 return $rows; 64} 65

###現状と目的
上記コードで得られる現状には、先頭に固定するコメント('comment_id'=>99)が追加されず以下となります。

php

1$results = [ 2 'thread' => ['type'=>'thread', 'thread_id'=>1, 'title'=>'1の掲示板', 'author_id'=>100, 'author_name'=>'鈴木', 'top_comment_id'=>99], 3 'comments' => [ 4 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>30, 'content'=>'こんにちは', 'author_id'=>200, 'author_name'=>'佐藤'], 5 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>40, 'content'=>'さようなら', 'author_id'=>300, 'author_name'=>'山田'] 6 ] 7];

目的はこうで、commentsの配列に先頭に固定するコメント('comment_id'=>99)を追加したものになります。

php

1$results = [ 2 'thread' => ['type'=>'thread', 'thread_id'=>1, 'title'=>'1の掲示板', 'author_id'=>100, 'author_name'=>'鈴木', 'top_comment_id'=>99], 3 'comments' => [ 4 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>99, 'content'=>'先頭に固定されるコメントです', 'author_id'=>400, 'author_name'=>'高橋'], 5 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>30, 'content'=>'こんにちは', 'author_id'=>200, 'author_name'=>'佐藤'], 6 ['type'=>'comment', 'thread_id'=>1, 'comment_id'=>40, 'content'=>'さようなら', 'author_id'=>300, 'author_name'=>'山田'] 7 ] 8];

###試したこと
上記ソースコードにございますが// ねじ込めたことを確認のダンプによって確認はとれていて、確かに先頭に固定するコメント('comment_id'=>99)が、$arg_wrapperにねじこめていると思うのですが、なぜ目的のような結果にできないのか…わかりません。

また以下ミニマムなarray_unshiftは問題なく追加できましたし、原因が特定できずにおります。

php

1$rows = [ ['comment_id'=>30], ['comment_id'=>40] ]; 2$top_comment = [ 'comment_id'=>99 ]; 3array_unshift($rows,$top_comment); 4var_dump($rows);

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

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

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

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

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

guest

回答2

0

解決策ではないのですが、 php では foreach のときに配列がコピーされるので、ループ中に取り出される $print_area や $info と var_dump している $arg_wrapper は別物です。

PHP 'foreach' の内部挙動について - スタック・オーバーフロー

ご提示のパターンだと、他の $print_area の $info を更新しないといけないのでやりかたが分からないです。

やるとしたら、foreach ( $arg_wrapper as $print_area => &$info ) のところを thread と comment に分離して(キーが他にもあったら厄介ですが)、thread を get_row, comment と 固定id の配列を連結した配列を作ってから get_row の 2 段構えにして、それらを結合して返す、といった作りにすると思います。

投稿2020/11/11 06:45

papinianus

総合スコア12705

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

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

ikatako

2020/11/12 19:48

別物になるのですね、どうりで… ループの外側の$arg_wrapperを変更はできないようですが、yambejp様が内側の$infoを変更する方法を伝授してくださいましたので今回はなんとかなりそうです。 ご回答ありがとうございます。
guest

0

ベストアンサー

質問の意図がわかりかねますが、以下でどうでしょう?

foreach ( $arg_wrapper as $print_area => $info ) {

↓↓↓

foreach ( $arg_wrapper as $print_area => &$info ) {

投稿2020/11/11 03:37

yambejp

総合スコア116724

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

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

ikatako

2020/11/12 19:49

おお、「&」で変えられるのですか。いつもありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問