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

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

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

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

Q&A

1回答

957閲覧

PHP多次元連想配列の検証にあたって、「検証対象のどこがおかしいか」を示した結果を得たい

mickymouse

総合スコア3

PHP

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

0グッド

0クリップ

投稿2020/07/10 03:47

###実現したいこと
検証対象に対して、必須キー$requiredの指定通りであることを検証する関数を作りたいです。
(値の有無、値の型を検証したいです。)

###問題
検証対象は
・ドリンクのレスポンス$response_drink
・ケーキのレスポンス$response_drink
などいくつかのパターンがあります。

この検証対象を、valid_response( 'drink', $response_drink )のように渡して検証しています。

しかし「ドリンクのレスポンスを検証」はできるのに、「ケーキのレスポンスを検証」ができなくて行き詰っています。

###該当のソースコード

php

1/* 2 レスポンス 3----------------------*/ 4 5// ドリンクのレスポンス 6$response_drink = [ 7 [ 8 'titles' => [ 9 'name' => 'mojito' 10 ,'thumbnails' => 'http...' 11 ] 12 ,'data' => [ 13 'id' => [ 14 'a_id' => 0 15 ] 16 ] 17 ,'subs' => ['lime','mint'] 18 ], 19 [ 20 'titles' => [ 21 'name' => null // ここがnullなので、検証結果にそれが示されて問題なし 22 ,'thumbnails' => 'http...' 23 ] 24 ,'data' => [ 25 'id' => [ 26 'a_id' => 0 27 ] 28 ] 29 ] 30]; 31 32// ケーキのレスポンス 33$response_cake = [ 34 'cake' => [ 35 'items' => [ 36 [ 37 'name' => 'chocolate' 38 ,'images' => ['a','b'] 39 ,'genres' => ['c','d'] 40 ,'followers' => [ 41 'total' => 100 42 ] 43 ,'id' => 11 44 ], 45 [ 46 'name' => null // ここがnullなのに、検証結果にそれが示されない 47 ,'images' => [] 48 ,'followers' => [ 49 'total' => 200 50 ,'weekl' => 2 51 ] 52 ,'id' => 22 53 ] 54 ] 55 ] 56]; 57 58 59/* 60 検証実行 61----------------------*/ 62 63// ドリンクのレスポンスを検証 64// $response_drinkについて、[1]['titles']['name']がnullであることが示される 65$result_drink = valid_response( 'drink', $response_drink ); 66var_dump($result_drink); 67 68// ケーキのレスポンスを検証 69// $response_cakeについて、['cake']['items'][1]['name']がnullであることが示されない 70$result_cake = valid_response( 'cake', $response_cake ); 71var_dump($result_cake); 72 73 74/* 75 検証する関数 76----------------------*/ 77 78// $responseについて、$requiredで指定した値の型、キー有無を判定 79function valid_response( $kind, $response ){ 80 81 // 種類に応じて$requiredを指定 82 if ( $kind === 'cake' ) { 83 $required = [ 84 'cake' => [ 85 'items' => [ 86 [ 87 'name' => '' 88 ,'images' => [] 89 ,'followers' => [ 90 'total' => 0 91 ] 92 ,'id' => 0 93 ] 94 ] 95 ] 96 ]; 97 } 98 elseif ( $kind === 'drink' ) { 99 $required = [ 100 [ 101 'titles' => [ 102 'name' => 'x' 103 ,'thumbnails' => 'x' 104 ] 105 ,'data' => [ 106 'id' => [ 107 'a_id' => 0 108 ] 109 ] 110 ] 111 ]; 112 } 113 114 // 検証 115 $result = []; 116 foreach ( $response as $k1 => $res ) { 117 foreach ( $required as $k2 => $req ) { 118 $match = valid_type_arr( $res, $req ); 119 if( !empty($match) ){ 120 $result[$k1][] = $match; 121 } 122 } 123 } 124 return $result; 125} 126 127// 値の型、キー有無を判定する 128function valid_type_arr( $target_info, $base_info ){ 129 $result = []; 130 foreach( $base_info as $k => $v ){ 131 if( is_array($v) ){ 132 if( !isset($target_info[$k]) ){ 133 if( array_key_exists($k, $target_info) ){ 134 $result[$k] = null; 135 }else{ 136 $result[$k] = 'undefined'; 137 } 138 }else{ 139 $re = valid_type_arr( $target_info[$k], $v ); 140 if( !empty($re) ){ 141 $result[$k] = $re; 142 } 143 } 144 }else{ 145 if( !isset($target_info[$k]) ){ 146 if( array_key_exists($k, $target_info) ){ 147 $result[$k] = null; 148 }else{ 149 $result[$k] = 'undefined'; 150 } 151 }else{ 152 if ( gettype($target_info[$k]) !== gettype($v) ){ 153 $result[$k] = $target_info[$k]; 154 } 155 } 156 } 157 } 158 return $result; 159} 160

###求めている結果
上記ドリンクの方のvar_dump($result_drink);では以下を得られます。

php

1array(1) { 2 [1]=> 3 array(1) { 4 [0]=> 5 array(1) { 6 ["titles"]=> 7 array(1) { 8 ["name"]=> 9 NULL 10 } 11 } 12 } 13}

これは、$response_drinkについて
[1]['titles']['name']nullであること
を示しており問題ございません。

一方でケーキの方のvar_dump($result_cake);では以下を得てしまいます。

php

1array(0) { 2}

しかし本来は$response_cakeについて
['cake']['items'][1]['name']nullであること
を示したいので、求める結果は次のものです。

php

1array(1) { 2 ["cake"]=> 3 array(1) { 4 ["items"]=> 5 array(1) { 6 [1]=> 7 array(1) { 8 ["name"]=> 9 NULL 10 } 11 } 12 } 13} 14

###試したこと
解決策の一案として、valid_response()という一つの関数に頼らずに、ケーキとドリンクの場合それぞれで検証する関数を作る方法ならできるのですが、そうではなく合わせて汎用的な関数を作りたく思っています。

また$requiredの構造を変える方法でもできるのですが、そうではなく検証対象と同じ構造で書いたまま解決できないかと考えているのが現状です。

###PHPバージョン
PHPは7.2.0を使用です。

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

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

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

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

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

m.ts10806

2020/07/10 03:55

2つの配列の構造が違うのは本当にそれで問題ないのでしょうか。
mickymouse

2020/07/10 04:03

ご指摘ありがとうございます。通常は自ら統一すべきですから当然の疑問かと思います。 実はレスポンスを得る先が異なるために、構造の統一ができないという理由がございます。 もちろん、「統一ができないならば、レスポンスを得てから自ら構造を統一し、その上で同じ構造に対して検証すれば?」というご提案もあるかと思いますが、そうなりますと構造の統一に際しても検証を挟まねばなりません。 そのためにレスポンスを得た時点で、異なる構造に対する検証を考えており、質問のような処理を求めた次第でございます。 また何かございましたら宜しくお願い致します。
m.ts10806

2020/07/10 04:07

でしたら言うことはありません。 「異なる構造に対する検証」は余計な分岐や手順が増え、バグの元になりますので、「合わせる」以外にないと思ってます。 扱う情報が増えればその分また分岐が増え、テスト工数もかさみます。
guest

回答1

0

情報が古いですが、こんな方法があるようです。

https://www.slideshare.net/hinakano/json-schema

投稿2020/07/10 15:36

satokei

総合スコア1168

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

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

mickymouse

2020/07/10 15:42

ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問