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

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

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

Schemeは、Lispから派生したプログラミング言語の一つであり、仕様または実装を指す場合もあります。言語自体の仕様はシンプルで、関数型言語として理解しやすいことから記号処理などで主に用いられている言語です。

PHP

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

1回答

1196閲覧

[php] 配列の追加について 思うようなスキーマ設計ができない

DaisukeMori

総合スコア217

Scheme

Schemeは、Lispから派生したプログラミング言語の一つであり、仕様または実装を指す場合もあります。言語自体の仕様はシンプルで、関数型言語として理解しやすいことから記号処理などで主に用いられている言語です。

PHP

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

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2021/08/04 01:50

結論からいうと
以下のようなAPIを自作しようとしています。

駅検索APIサービス
heart express API

自作したコード(全文)
※phpビルトインサーバーで動きます

php

1<?php 2header('Content-Type: application/json; charset=UTF-8'); 3 4// データリソース(モックアップ) 5$db['db'] = array( 6 'station' => array( 7 array ( 8 'name' => '三ノ宮', 9 'prefecture' => '兵庫県', 10 'line' => 'JR神戸線', 11 'x' => 135.1952558, 12 'y' => 34.6945454, 13 'postal' => '6770039', 14 'distance' => '100m', 15 'prev' => '', 16 'next' => '' 17 ), 18 array ( 19 'name' => '神戸三宮', 20 'prefecture' => '兵庫県', 21 'line' => '阪神', 22 'x' => 135.1952558, 23 'y' => 34.6945454, 24 'postal' => '6770039', 25 'distance' => '100m', 26 'prev' => '', 27 'next' => '' 28 ), 29 array ( 30 'name' => '東京', 31 'prefecture' => '東京都', 32 'line' => 'JR山手線', 33 'x' => 139.7673068, 34 'y' => 35.6809591, 35 'postal' => '6770039', 36 'distance' => '150m', 37 'prev' => '', 38 'next' => '' 39 ), 40 array ( 41 'name' => '神田', 42 'prefecture' => '東京都', 43 'line' => 'JR山手線', 44 'x' => 139.7709, 45 'y' => 35.6918, 46 'postal' => '6770039', 47 'distance' => '150m', 48 'prev' => '', 49 'next' => '' 50 ), 51 ), 52); 53 54if(isset($_GET['method'])) { // methodでGET送信 55 $getX = htmlspecialchars($_GET['x']); // xでGET送信 56 $getY = htmlspecialchars($_GET['y']); // yでGET送信 57 58 foreach ($db as $val) { 59 foreach ($val['station'] as $val) { 60 $name = $val['name']; 61 $prefecture = $val['prefecture']; 62 $line = $val['line']; 63 $longitude = floatval($val['x']); 64 $latitude = floatval($val['y']); 65 $postal = $val['postal']; 66 $distance = $val['distance']; 67 $prev = $val['prev']; 68 $next = $val['next']; 69 70 // GETパラメーターによって整合するもの表示 71 if ($longitude+1 >= $getX && $getX >= $longitude-1 72 && $latitude+1 >= $getY && $getY >= $latitude-1) { 73 $arr['response'][] = array( 74 'station' => array( 75 array ( 76 'name' => $name, 77 'prefecture' => $prefecture, 78 'line' => $line, 79 'x' => $longitude, 80 'y' => $latitude, 81 'postal' => $postal, 82 'distance' => $distance, 83 'prev' => $prev, 84 'next' => $next, 85 ), 86 ), 87 ); 88 } 89 } 90 } 91} else { 92 $arr['status'] = 'no request'; 93} 94 95print json_encode($arr, JSON_PRETTY_PRINT);

http://localhost:8000/?method=get&x=135&y=35
でアクセスすると以下のようなJsonデータが吐き出される。

json

1{ 2 response: [ 3 { 4 station: [ 5 { 6 name: "三ノ宮", 7 prefecture: "兵庫県", 8 line: "JR神戸線", 9 x: 135.1952558, 10 y: 34.6945454, 11 postal: "6770039", 12 distance: "100m", 13 prev: "元町", 14 next: "灘" 15 } 16 ] 17 }, 18 { 19 station: [ 20 { 21 name: "神戸三宮", 22 prefecture: "兵庫県", 23 line: "阪神", 24 x: 135.1952558, 25 y: 34.6945454, 26 postal: "6770039", 27 distance: "100m", 28 prev: "", 29 next: "" 30 } 31 ] 32 } 33 ] 34}

一見すると要件を満たしてるように見えるが、
微妙にheart express APIとスキーマが違っています。
heart express APIではstation内に要素が追加されているのに対し、
自作したAPIではresponse直下に配列があり、しかもstationキーが複数出てしまっています。

かといって
$arr['response'][] = array(の部分を$arr['response'] = array(にすると
スキーマは同じになるのですが、配列は追加されず、上書きされてしまいます。

最終的に以下のようなJsonデータを作るにはどうすればいいのでしょうか?

json

1 2{ 3 response: { 4 station: [ 5 { 6 name: "神戸三宮", 7 prefecture: "兵庫県", 8 line: "阪神", 9 x: 135.1952558, 10 y: 34.6945454, 11 postal: "6770039", 12 distance: "100m", 13 prev: "", 14 next: "" 15 }, 16 { 17 ... stationの中に追加する方法が知りたい 18 } 19 , 20 { 21 ... stationの中に追加する方法が知りたい 22 } 23 ] 24 } 25}

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

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

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

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

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

guest

回答1

0

ベストアンサー

質問以外で致命的な部分

PHP

1 foreach ($db as $val) { 2 foreach ($val['station'] as $val) 3

で親ループと子ループ$valが重複しているのは大きな問題です。
大抵の場合、意図しない結果が意図しないところで発生します。

PHP

1 foreach ($db as $val) { 2 foreach ($val['station'] as $station_detail) 3

とかそういう感じで重複しない様にするか、関数等でスコープを区切る様にするのが安全です。

また、これは致命的では無く既存コードやプロジェクトとの兼ね合いもあるとは思いますが、
PHP5.4以降のコードを書く場合、配列の定義はarray()よりもの方がすっきりします。
(array()で書いていると、教科書が相当古いとか、元になっているコードが相当古いという印象を受けるので、特に理由が無ければ[]で記述されることをお勧めします。)

原因

前半部分

PHP

1 2$db['db'] = array( 3 'station' => array( 4 array ( 5 'name' => '三ノ宮', 6 'prefecture' => '兵庫県', 7 'line' => 'JR神戸線', 8 'x' => 135.1952558, 9 'y' => 34.6945454, 10 'postal' => '6770039', 11 'distance' => '100m', 12 'prev' => '', 13 'next' => '' 14 ), 15 array ( 16 'name' => '神戸三宮', 17 'prefecture' => '兵庫県', 18 'line' => '阪神', 19 'x' => 135.1952558, 20 'y' => 34.6945454, 21 'postal' => '6770039', 22 'distance' => '100m', 23 'prev' => '', 24 'next' => '' 25 ), 26 array ( 27 'name' => '東京', 28 'prefecture' => '東京都', 29 'line' => 'JR山手線', 30 'x' => 139.7673068, 31 'y' => 35.6809591, 32 'postal' => '6770039', 33 'distance' => '150m', 34 'prev' => '', 35 'next' => '' 36 ), 37 array ( 38 'name' => '神田', 39 'prefecture' => '東京都', 40 'line' => 'JR山手線', 41 'x' => 139.7709, 42 'y' => 35.6918, 43 'postal' => '6770039', 44 'distance' => '150m', 45 'prev' => '', 46 'next' => '' 47 ), 48 ), 49); 50 51

は理想的な形になっている様に思います。

一方で、以下のコード中の定義部分

PHP

1 $arr['response'][] = array( 2 'station' => array( 3 array ( 4 'name' => $name, 5 'prefecture' => $prefecture, 6 'line' => $line, 7 'x' => $longitude, 8 'y' => $latitude, 9 'postal' => $postal, 10 'distance' => $distance, 11 'prev' => $prev, 12 'next' => $next, 13 ), 14 ), 15 ); 16

を同じように静的に定義した場合、以下の様に書いているのと同じです。

PHP

1 2$db['db'][] = array( 3 'station' => array( 4 array ( 5 'name' => '三ノ宮', 6 'prefecture' => '兵庫県', 7 'line' => 'JR神戸線', 8 'x' => 135.1952558, 9 'y' => 34.6945454, 10 'postal' => '6770039', 11 'distance' => '100m', 12 'prev' => '', 13 'next' => '') 14 ) 15 ); 16$db['db'][] = array( 17 'station' => array( 18 array ( 19 'name' => '三ノ宮', 20 'prefecture' => '兵庫県', 21 'line' => 'JR神戸線', 22 'x' => 135.1952558, 23 'y' => 34.6945454, 24 'postal' => '6770039', 25 'distance' => '100m', 26 'prev' => '', 27 'next' => '') 28 ) 29 ); 30$db['db'][] = array( 31 'station' => array( 32 array ( 33 'name' => '三ノ宮', 34 'prefecture' => '兵庫県', 35 'line' => 'JR神戸線', 36 'x' => 135.1952558, 37 'y' => 34.6945454, 38 'postal' => '6770039', 39 'distance' => '100m', 40 'prev' => '', 41 'next' => '') 42 ) 43 ); 44 45 46

これの解決方法として、試したこと
$arr['response'][] = array(の部分を$arr['response'] = array(にすると
とされていると思うのですが、子ループの中でやってしまっているので上書きされてしまうため、上書きされるという結果になっています。

解決方法

解決方法としては、各データを$arr['response']['station']の要素として追加していきましょう。

初期データで同じように書いた場合はこんな感じ

PHP

1$db['db']['station'][] = [ 2 'name' => '三ノ宮', 3 'prefecture' => '兵庫県', 4 'line' => 'JR神戸線', 5 'x' => 135.1952558, 6 'y' => 34.6945454, 7 'postal' => '6770039', 8 'distance' => '100m', 9 'prev' => '', 10 'next' => '' 11 ]; 12$db['db']['station'][] = [ 13 'name' => '神戸三宮', 14 'prefecture' => '兵庫県', 15 'line' => '阪神', 16 'x' => 135.1952558, 17 'y' => 34.6945454, 18 'postal' => '6770039', 19 'distance' => '100m', 20 'prev' => '', 21 'next' => '' 22 ]; 23//以下駅の数だけ続く

$arrに適用する場合の全体はこんな感じ
*各ifは条件を満たすのがめんどくさかったので条件を変更しています。

PHP

1 2<?php 3 4header('Content-Type: application/json; charset=UTF-8'); 5 6// データリソース(モックアップ) 7$db['db'] = array( 8 'station' => array( 9 array ( 10 'name' => '三ノ宮', 11 'prefecture' => '兵庫県', 12 'line' => 'JR神戸線', 13 'x' => 135.1952558, 14 'y' => 34.6945454, 15 'postal' => '6770039', 16 'distance' => '100m', 17 'prev' => '', 18 'next' => '' 19 ), 20 array ( 21 'name' => '神戸三宮', 22 'prefecture' => '兵庫県', 23 'line' => '阪神', 24 'x' => 135.1952558, 25 'y' => 34.6945454, 26 'postal' => '6770039', 27 'distance' => '100m', 28 'prev' => '', 29 'next' => '' 30 ), 31 array ( 32 'name' => '東京', 33 'prefecture' => '東京都', 34 'line' => 'JR山手線', 35 'x' => 139.7673068, 36 'y' => 35.6809591, 37 'postal' => '6770039', 38 'distance' => '150m', 39 'prev' => '', 40 'next' => '' 41 ), 42 array ( 43 'name' => '神田', 44 'prefecture' => '東京都', 45 'line' => 'JR山手線', 46 'x' => 139.7709, 47 'y' => 35.6918, 48 'postal' => '6770039', 49 'distance' => '150m', 50 'prev' => '', 51 'next' => '' 52 ), 53 ), 54); 55 56$arr = []; 57 58if(true) { // methodでGET送信 59 $getX = 0;//htmlspecialchars($_GET['x']); // xでGET送信 60 $getY = 0;//htmlspecialchars($_GET['y']); // yでGET送信 61 foreach ($db as $val) { 62 foreach ($val['station'] as $station_detail) { 63 $name = $station_detail['name']; 64 $prefecture = $station_detail['prefecture']; 65 $line = $station_detail['line']; 66 $longitude = floatval($station_detail['x']); 67 $latitude = floatval($station_detail['y']); 68 $postal = $station_detail['postal']; 69 $distance = $station_detail['distance']; 70 $prev = $station_detail['prev']; 71 $next = $station_detail['next']; 72 if(true){ 73 $arr['response']['station'][] = array( 74 'name' => $name, 75 'prefecture' => $prefecture, 76 'line' => $line, 77 'x' => $longitude, 78 'y' => $latitude, 79 'postal' => $postal, 80 'distance' => $distance, 81 'prev' => $prev, 82 'next' => $next); 83 } 84 } 85 } 86} else { 87 $arr['status'] = 'no request'; 88} 89 90print json_encode($arr, JSON_PRETTY_PRINT);

ポイントはこの辺

PHP

1 2 $arr['response']['station'][] = array( 3 'name' => $name, 4 'prefecture' => $prefecture, 5 'line' => $line, 6 'x' => $longitude, 7 'y' => $latitude, 8 'postal' => $postal, 9 'distance' => $distance, 10 'prev' => $prev, 11 'next' => $next); 12

投稿2021/08/04 06:37

編集2021/08/04 06:47
tanat

総合スコア18709

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

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

DaisukeMori

2021/08/05 01:43

ご丁寧にありがとうございます。 無事解決しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問