###実現したいこと
検証対象に対して、必須キー$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を使用です。