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

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

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

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

Q&A

解決済

1回答

933閲覧

PHPで配列を連結したいが、条件によって連結が実現できない

anpanmama

総合スコア8

PHP

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

0グッド

0クリップ

投稿2020/01/21 09:08

編集2020/01/21 09:10

前提・実現したいこと

PHPで配列を連結するシステムを作っています。

$new_post_info_wrapperと$leave_post_info_wrapperという配列があり、いずれも'insert_name'というキーを持っています。

これらを以下の条件で連結したいのですが、2の条件が実現できません。

1.同じ'insert_name'で、get_result_post_info_wrapper()の第一引数が'infinity'なら、同じところに追加する。

2.違う'insert_name'なら新しく追加する。

発生している問題

以下のように、いずれの配列も'insert_name'が'julia'と'ally'なら実現できるのですが、'julia'と'smith'などになるとできなくなってしまいます。

該当のソースコード

以下のように、いずれの配列も'julia'と'ally'なら問題なく連結できて$resultを作ることができます。

PHP

1// データベースにある配列 2$leave_post_info_wrapper= [ 3 [ 4 'insert_name' => 'julia', 5 'present_info_arr' => [ ['id'=>1,'present_type'=>'a'] ], 6 ], 7 [ 8 'insert_name' => 'ally', 9 'present_info_arr' => [ ['id'=>2,'area'=>'kanagawa','present_type'=>'b'], ['id'=>3,'area'=>'chiba','present_type'=>'c'] ], 10 ], 11]; 12 13// 新しく追加する配列 14$new_present_info_wrapper = [ 15 [ 16 'insert_name' => 'julia', 17 'present_info_arr' => [ ['id'=>4,'area'=>'saitama','present_type'=>'d'] ], 18 ], 19 [ 20 'insert_name' => 'ally', 21 'present_info_arr' => [ ['id'=>5,'area'=>'gunma','present_type'=>'e'] ], 22 ], 23]; 24 25// 最終的な配列 26$result = [ 27 [ 28 'insert_name' => 'julia', 29 'present_info_arr' => [ ['id'=>1,'present_type'=>'a'], ['id'=>4,'present_type'=>'d'] ], 30 ], 31 [ 32 'insert_name' => 'ally', 33 'present_info_arr' => [ ['id'=>2,'area'=>'kanagawa','present_type'=>'b'], ['id'=>3,'area'=>'chiba','present_type'=>'c'], ['id'=>5,'area'=>'gunma','present_type'=>'e'] ], 34 ], 35]; 36

試したこと

こちらはいずれの配列も'julia'と'ally'なので実行すると連結できます。(実行サンプル)

しかし、get_leave_post_info_wrapper()で取得される配列を'ally'から'smith'など別の名前にすると連結できなくなるという問題が生じることがご確認いただけるかと思います。

php

1<?php 2// 新しく追加する配列 3$new_post_info_wrapper = [ 4 [ 5 'insert_name' => 'julia', 6 'post_info_arr' => [ ['id'=>4,'area'=>'saitama','post_type'=>'d'] ], 7 ], 8 [ 9 'insert_name' => 'ally', 10 'post_info_arr' => [ ['id'=>5,'area'=>'gunma','post_type'=>'e'] ], 11 ], 12]; 13 14// infinityで、かつ同じinsert_nameの場合に連結したい 15$result = get_result_post_info_wrapper( 'infinity', $new_post_info_wrapper ); 16var_dump( $result ); 17 18// 最終的な配列 19function get_result_post_info_wrapper( $process, $new_post_info_wrapper ){ 20 $result = []; 21 22 // データベースから現在値を取得 23 $leave_post_info_wrapper = get_leave_post_info_wrapper(); 24 25 // 現在値がなければ 26 if( empty($leave_post_info_wrapper) ){ 27 $result = ext_post_info_wrapper_for_leave( $new_post_info_wrapper ); 28 } 29 30 // 現在値があれば 31 else{ 32 foreach( $leave_post_info_wrapper as &$leave_wrapper ){ 33 $leave_insert_name = $leave_wrapper['insert_name']; 34 $leave_post_info_arr = $leave_wrapper['post_info_arr']; 35 36 foreach( $new_post_info_wrapper as $new_wrapper ){ 37 $new_insert_name = $new_wrapper['insert_name']; 38 $new_post_info_arr = $new_wrapper['post_info_arr']; 39 40 // 必要な情報だけ抽出 41 foreach( $new_post_info_arr as &$new_post_info ){ 42 $exted_post_info = ext_post_info( $new_post_info ); 43 } 44 45 // insert_nameが同じものがある場合 46 if( $new_insert_name == $leave_insert_name ){ 47 48 // 無限ロードなら追加 49 if( $process == 'infinity' ){ 50 if( $leave_wrapper['insert_name'] == $new_insert_name ){ 51 $leave_wrapper['post_info_arr'][] = $exted_post_info; 52 $result = $leave_post_info_wrapper; 53 } 54 } 55 } 56 57 // 新しい insert_name の場合 58 else{ 59 $result = ext_post_info_wrapper( $new_post_info_wrapper ); 60 } 61 } 62 } 63 } 64 65 return $result; 66} 67 68// データベースにある配列 69function get_leave_post_info_wrapper(){ 70 return [ 71 [ 72 'insert_name' => 'julia', 73 'post_info_arr' => [ ['id'=>1,'post_type'=>'a'] ], 74 ], 75 [ 76 'insert_name' => 'ally', 77 'post_info_arr' => [ ['id'=>2,'area'=>'kanagawa','post_type'=>'b'], ['id'=>3,'area'=>'chiba','post_type'=>'c'] ], 78 ], 79 ]; 80} 81 82// post_info_wrapper から必要な値を抽出 83function ext_post_info_wrapper( $post_info_wrapper ){ 84 foreach( $post_info_wrapper as &$wrapper ){ 85 $new_post_info_arr = $wrapper['post_info_arr']; 86 87 foreach( $new_post_info_arr as &$new_post_info ){ 88 $wrapper['post_info_arr'] = []; 89 $wrapper['post_info_arr'][] = ext_post_info( $new_post_info ); 90 } 91 } 92 return $post_info_wrapper; 93} 94 95// post_info から必要な値を抽出 96function ext_post_info( $post_info ){ 97 98 $exted_post_info = []; 99 $post_type = $post_info['post_type']; 100 101 // 抽出したい情報を指定 102 if( $post_type == 'a' ){ 103 $key_arr = ['post_type','id']; 104 } 105 else{ 106 $key_arr = ['post_type','area']; 107 } 108 109 // 抽出 110 foreach( $key_arr as $key ){ 111 $exted_post_info[$key] = $post_info[$key]; 112 } 113 114 return $exted_post_info; 115} 116 117

補足情報

post_info_wrapperを対象としたext_post_info_wrapper()があり、post_infoを対象としたext_post_info()がある。という流れは変えたくないと思っています。(それぞれ別の場所でも実行したいためです。)

つまりget_result_post_info_wrapper()の調整だけで実現できれば、というのが理想です。

どうぞ宜しくお願い致します。

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

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

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

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

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

guest

回答1

0

ベストアンサー

実装してわかったんですが、質問者様のおっしゃる最終的な配列は得られないですよね。実行サンプルも確認しましたがやはり最終的な配列とは違うすがたでした。理由は ext_post_info をしているからです。自分で書いたコードは理解したほうがやりたいことの実現に近づきますよ。

どうしても欲しいということだったので ext_post_info を作りましたが、この部分の処理では全く不要です。
ext_post_info_wrapper も post_info も質問者様提示の引数と同じ構造の配列を渡して動くので、「他のところでも動かしたいから~」というのは質問サイトの回答としての基準は満たしていると考えています。

php

1<?php 2class post { 3 private $insert_name; 4 private $post_infos; 5 public function __construct($name = "") { 6 $this->insert_name = $name; 7 $this->post_infos = []; 8 } 9 public function pick($arrs) { 10 foreach($arrs as $arr) { 11 if($arr["insert_name"] !== $this->insert_name) continue; 12 foreach($arr["post_info_arr"] as $post) { 13 $this->post_infos[] = new post_info($post); 14 } 15 } 16 } 17 public function toArray() { 18 return [ "insert_name" => $this->insert_name, "post_info_arr" => array_map(function($e) {return $e->toArray();}, $this->post_infos) ]; 19 } 20} 21class post_info { 22 private $id; 23 private $area; 24 private $post_type; 25 public function __construct($assoc) { 26 $this->id = isset($assoc["id"]) ? $assoc["id"] : 0; 27 $this->area = isset($assoc["area"]) ? $assoc["area"] : ""; 28 $this->post_type = isset($assoc["post_type"]) ? $assoc["post_type"] : "a"; 29 } 30 public function toArray() { 31 if($this->post_type === "a") return [$this->post_type, $this->id]; 32 return [$this->post_type, $this->area]; 33 } 34} 35// 新しく追加する配列 36$new_post_info_wrapper = [ 37 [ 38 'insert_name' => 'julia', 39 'post_info_arr' => [ ['id'=>4,'area'=>'saitama','post_type'=>'d'] ], 40 ], 41 [ 42 'insert_name' => 'ally', 43 'post_info_arr' => [ ['id'=>5,'area'=>'gunma','post_type'=>'e'] ], 44 ], 45]; 46 47// infinityで、かつ同じinsert_nameの場合に連結したい 48$result = get_result_post_info_wrapper( 'infinity', $new_post_info_wrapper ); 49var_dump( $result ); 50 51// 最終的な配列 52function get_result_post_info_wrapper( $process, $new_post_info_wrapper ){ 53 // データベースから現在値を取得 54 $leave_post_info_wrapper = get_leave_post_info_wrapper(); 55 56 // 現在値がなければ 57 if( empty($leave_post_info_wrapper) ){ 58 return ext_post_info_wrapper( $new_post_info_wrapper ); 59 } 60 if( $process !== "infinity") { 61 return ext_post_info_wrapper( $leave_post_info_wrapper ); 62 } 63 return ext_post_info_wrapper( array_merge($leave_post_info_wrapper,$new_post_info_wrapper) ); 64} 65 66// データベースにある配列 67function get_leave_post_info_wrapper(){ 68 return [ 69 [ 70 'insert_name' => 'julia', 71 'post_info_arr' => [ ['id'=>1,'post_type'=>'a'] ], 72 ], 73 [ 74 'insert_name' => 'ally', 75 'post_info_arr' => [ ['id'=>2,'area'=>'kanagawa','post_type'=>'b'], ['id'=>3,'area'=>'chiba','post_type'=>'c'] ], 76 ], 77 ]; 78} 79function builder($arr) { 80 $posts = array_map(function($e){ return new post($e);},array_unique(array_column($arr, "insert_name"))); 81 array_walk($posts, function($e)use($arr) { $e->pick($arr);}); 82 return $posts; 83} 84// post_info_wrapper から必要な値を抽出 85function ext_post_info_wrapper($arr) { 86 return array_map(function ($e) { return $e->toArray();}, builder($arr)); 87} 88// post_info から必要な値を抽出 89function ext_post_info( $post_info ){ 90 $obj = new post_info($post_info); 91 return $obj->toArray(); 92}

以下の出力サンプルは、データベースから得た配列のモックで提示されている ally が smith だったときにこうなる、という例です。

txt

1array(3) { 2 [0]=> 3 array(2) { 4 ["insert_name"]=> 5 string(5) "julia" 6 ["post_info_arr"]=> 7 array(2) { 8 [0]=> 9 array(2) { 10 [0]=> 11 string(1) "a" 12 [1]=> 13 int(1) 14 } 15 [1]=> 16 array(2) { 17 [0]=> 18 string(1) "d" 19 [1]=> 20 string(7) "saitama" 21 } 22 } 23 } 24 [1]=> 25 array(2) { 26 ["insert_name"]=> 27 string(5) "smith" 28 ["post_info_arr"]=> 29 array(2) { 30 [0]=> 31 array(2) { 32 [0]=> 33 string(1) "b" 34 [1]=> 35 string(8) "kanagawa" 36 } 37 [1]=> 38 array(2) { 39 [0]=> 40 string(1) "c" 41 [1]=> 42 string(5) "chiba" 43 } 44 } 45 } 46 [3]=> 47 array(2) { 48 ["insert_name"]=> 49 string(4) "ally" 50 ["post_info_arr"]=> 51 array(1) { 52 [0]=> 53 array(2) { 54 [0]=> 55 string(1) "e" 56 [1]=> 57 string(5) "gunma" 58 } 59 } 60 } 61}

投稿2020/01/21 16:30

papinianus

総合スコア12705

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

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

anpanmama

2020/01/21 22:47

class?$this?と驚きました。このような書き方を知らなかったので大変勉強になりました。そして post_info の方も、そのようにまとめて頂きありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問