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

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

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

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

Q&A

解決済

2回答

2887閲覧

【PHP】APIで変数をjson方式に変換したい

tajix_japan

総合スコア132

PHP

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

0グッド

1クリップ

投稿2017/01/04 13:04

編集2017/01/04 21:02

もとのページは下記のようになっています。

http://example.com/moto.html?fm=woman

【no】1【name】Yamada【】<BR>
【no】2【name】Tanaka【】<BR>

これと同列の位置にphp (http://example.com/api_1.php) を置き、上記の文字をアプリに渡すAPIとしたいと考えています。

まずは、moto.html のデータをjson方式に変換するため、str_replaceを利用して変換します。

【PHP その1】

PHP

1<?php 2 3$crawler="http://example.com/moto.html?fm=woman"; 4 5$homepage = file_get_contents($crawler); 6 7$moto = array("【no】", "【name】", "【】<BR>"); 8$api_1 = array("['no'=>'", "','name'=>'", "'],"); 9 10$newphrase = str_replace($moto, $api_1, $homepage); 11 12echo $newphrase; 13 14?> 15

これで無事 echo $newphrase; の部分が
['no'=>'1','name'=>'Yamada'],['no'=>'2','name'=>'Tanaka'],
とHTML上で表示されました。

一方、下記のようなjson方式で吐き出すPHPがあります。

【PHP その2】

PHP

1<?php 2 3function returnJson($resultArray){ 4 if(array_key_exists('callback', $_GET)){ 5 $json = $_GET['callback'] . "(" . json_encode($resultArray) . ");"; 6 }else{ 7 $json = json_encode($resultArray); 8 } 9 header('Content-Type: text/html; charset=utf-8'); 10 echo $json; 11 exit(0); 12} 13 14$type = $_REQUEST['user_type']; 15 16// ユーザリストの初期化 17$user_list = []; 18// 返却値の初期化 19$result = []; 20 21try { 22 // 値の検証 23 if (empty($type)) { 24 throw new Exception("no type..."); 25 } 26 27 // ユーザリストの作成 28 switch ($type) { 29 case 'a': 30 $user_list = 31[ 32['no'=>'10','name'=>'Yoshida'], 33['no'=>'11','name'=>'Mori'] 34 ]; 35 break; 36 37 default: 38 // 不正な値 39 throw new Exception("Invalid value..."); 40 break; 41 } 42 43 // 返却値の作成 44 $result = [ 45 'result' => 'OK', 46 'users' => $user_list 47 ]; 48} catch (Exception $e) { 49 $result = [ 50 'result' => 'NG', 51 'message' => $e->getMessage() 52 ]; 53} 54 55// JSONでレスポンスを返す 56returnJson($result); 57?>

上記のwebAPIを$type=aで叩くと

[{"no":"11","name":"Yoshida"},{"no":"12","name":"Mori"}]

が返ってきます。

【やりたいこと】

上記の2つを組み合わせて、

http://example.com/moto.html?fm=woman" にある

【no】1【name】Yamada【】<BR>
【no】2【name】Tanaka【】<BR>

[{"no":"1","name":"Yamada"},{"no":"2","name":"Tanaka"}]
のJSON方式で吐き出させたいと考えました。

【やってみたこと】

【PHPその2】にある
['no'=>'10','name'=>'Yoshida'],
['no'=>'11','name'=>'Mori']

の部分を
【PHPその1】にある
$newphrase に差し替えるだけで出来そうに感じました。
そこでPHPその1とその2を下記のように合体させました。

PHP

1<?php 2 3$crawler="http://example.com/moto.html"; 4 5$homepage = file_get_contents($crawler); 6 7$moto = array("【no】", "【name】", "【】<BR>"); 8$api_1 = array("['no'=>'", "','name'=>'", "'],"); 9 10$newphrase = str_replace($moto, $api_1, $homepage); 11 12 13function returnJson($resultArray){ 14 if(array_key_exists('callback', $_GET)){ 15 $json = $_GET['callback'] . "(" . json_encode($resultArray) . ");"; 16 }else{ 17 $json = json_encode($resultArray); 18 } 19 header('Content-Type: text/html; charset=utf-8'); 20 echo $json; 21 exit(0); 22} 23 24$type = $_REQUEST['user_type']; 25 26// ユーザリストの初期化 27$user_list = []; 28// 返却値の初期化 29$result = []; 30 31try { 32 // 値の検証 33 if (empty($type)) { 34 throw new Exception("no type..."); 35 } 36 37 // ユーザリストの作成 38 switch ($type) { 39 case 'a': 40 $user_list = 41[ 42$newphrase 43 ]; 44 break; 45 46 default: 47 // 不正な値 48 throw new Exception("Invalid value..."); 49 break; 50 } 51 52 // 返却値の作成 53 $result = [ 54 'result' => 'OK', 55 'users' => $user_list 56 ]; 57} catch (Exception $e) { 58 $result = [ 59 'result' => 'NG', 60 'message' => $e->getMessage() 61 ]; 62} 63 64// JSONでレスポンスを返す 65returnJson($result); 66?>

結果

{"result":"OK","users":[[""]]}
と、"result":"OK"は出るものの中身が吐き出されません。

echo $newphraseだとHTML上に吐き出すことができるのにです。
何が問題なのでしょうか?

どうすれば、$newphrase を 変数
['no'=>'1','name'=>'Yamada'],['no'=>'2','name'=>'Tanaka'],
として読んでくれるようになりますでしょうか?

よろしくお願いいたします。

追記

$newphrase に代入したすぐ後の var_dump を採って追記いただけますか?

kei344様
有難うございます。

$_REQUEST['user_type']の部分を$type = 'a';とリクエストを受け取った形に変形してテストしました。

php

1 2//$type = $_REQUEST['user_type']; 3 4$type = 'a'; 5 6// ユーザリストの初期化 7$user_list = []; 8// 返却値の初期化 9$result = []; 10 11try { 12 // 値の検証 13 if (empty($type)) { 14 throw new Exception("no type..."); 15 } 16 17 18 19 // ユーザリストの作成 20 switch ($type) { 21 case 'a': 22 case 'admin': 23 $user_list = 24 25[ 26$newphrase 27 ]; 28 break; 29 30var_dump($newphrase); 31 32以下同文 33

と記載してみました。

結果
{"result":"OK","users":[{"no":"1","name":"Yamada"},{"no":"2","name":"Tanaka"}]}

となるべきところが

{"result":"OK","users":["\ufeff[{"no":"1","name":"Yamada"},{"no":"2","name":"Tanaka"],"]}

と ["\ufeff 及び "] のへんてこな文字が混じっていることがわかりました。

\ufeffをググるとBOM付でこれが出ると書かれていたのですが、確認したところBOM付で記載してはいません。改行コードも自動判定からLFに変更しましたがやはり変化がありません。

(遅くなりましたが環境はCent OS 6.8です)

当方は今回初めてAPIを作ることになるため、下記をベースに開発しています。
http://qiita.com/busyoumono99/items/9b5ffd35dd521bafce47
ここのサンプルの標準で用意されている下記のcace 'g'を追記し
$_REQUEST['user_type']の部分を$type = 'g';としてテストしました。

php

1 case 'g': 2 case 'guest': 3 $user_list = [ 4 ['name'=>'香取','age'=>14], 5 ['name'=>'草薙','age'=>15], 6 ['name'=>'稲垣','age'=>15], 7 ['name'=>'岡田','age'=>15], 8 ['name'=>'森田','age'=>15], 9 ['name'=>'三宅','age'=>15], 10 ['name'=>'長野','age'=>15], 11 ['name'=>'坂本','age'=>15], 12 ['name'=>'井ノ原','age'=>15] 13 ]; 14 break; 15 default: 16 17

結果

{"result":"OK","users":[{"name":"\u9999\u53d6","age":14},{"name":"\u8349\u8599","age":15},{"name":"\u7a32\u57a3","age":15},{"name":"\u5ca1\u7530","age":15},{"name":"\u68ee\u7530","age":15},{"name":"\u4e09\u5b85","age":15},{"name":"\u9577\u91ce","age":15},{"name":"\u5742\u672c","age":15},{"name":"\u4e95\u30ce\u539f","age":15}]}

と普通にdump出来ます。

上記のテストから$newphraseを代入するとゴミ文字が入ってくることで表示出来なくなっていることがわかりました。

もう一歩だと思いますので何かアドバイスできることがございましたらよろしくお願いいたします。

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

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

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

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

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

kei344

2017/01/04 14:55

$newphrase に代入したすぐ後の var_dump を採って追記いただけますか?
guest

回答2

0

ちょっと何をやろうとしているのか分かりません。
ので、一般的なJSONデータの返信の仕方の説明のあるリンクを参考まで。
ググって出てきたサイトなので、コード検証等してませんが、シンプルな記述なのでわかりやすいかと。

JSON形式のデータを返すAPI

今回、なぜかhttp://example.com/moto.html?fm=womanfile_get_contentsしてますが、普通は読み込んでいるサイトのデータはDB内の情報を元に表現しているので、参考サイトのコードの$valueを読み込んでいるサイトのDBデータで記載できれば、http://example.com/moto.html?fm=womanの情報を提供するAPIができるかと思います。

投稿2017/01/04 13:29

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

tajix_japan

2017/01/04 13:42

有難うございます。 データべースには入ることができません。 外注業者が管理しているデータベース&ホームページへのタッチとなるため別コストが継続的に掛かります。今回はお金は掛けたくありませんので、表面の文字ベースを拾って対応したいと考えています。
退会済みユーザー

退会済みユーザー

2017/01/04 13:53

外注の業者さんが管理しているのであれば、APIも作ってもらったほうが良いと思いますよ。 正直、APIが作れる技術レベルに無いようですし。。。 自サイトをスクレイピングして回答するAPIなんて、レスポンスも悪くなるし、リソースも倍必要になるので、メリットが見いだせません。 また、業者さんの管理するディレクトリにスクリプトを置くことになると思うので、アクセス権の問題も発生するように思います。 APIもセキュリティ観点での注意点や、リソースをどのように管理するか、考慮しなければならない点があります。 十分な学習なしに運営できる仕組みではないので、予算をひねり出す工夫をされたほうが良いと思います。
tajix_japan

2017/01/04 14:07

有難うございます。勉強になります。 使用頻度が少ないAPIですので、お金を掛けられません。 スクレイピングで対応できるならそれが一番と思っています。 作ろうとしているのは、単なる「必要事項のビュアー」であり、このAPIが継続的に利益を生み出すわけではありません。利益を生まないものに予算が付きません。 もう少しジタバタしてみたいと思います。
退会済みユーザー

退会済みユーザー

2017/01/04 23:15 編集

ツギハギのスクリプトは、本来やりたいことが伝わりにくいので読みたくないのですが、読んでみました。 以下の点を修正して下さい。 ・$newphrase は str_replace で全体の一部を置換するのではなく、"【no】1【name】Yamada【】"である行を検出し、それを"['no'=>'1','name'=>'Yamada']"と加工する。preg_match_all でよいかと。 ただ、やはり、ご自身のスクリプトを管理業者のいるディレクトリに置くことはおすすめしません。 ざっと考えても、以下のような弊害があります。 ・業者の理解できないアクセスが発生する。 ・逆に、おかしなアクセスが発生しても、業者側で判別できなくなる。 ・"moto.html?fm=woman"の変更をご自身が追いかけなくてはならなくなる。 ・業者管理ディレクトリ内に業者未管理ファイルが置かれる状態が正となると、おかしなスクリプトが置かれても業者側で気がつけなくなる。 ・今回のスクリプトが動かない場合の切り分けをご自身で行わなくてはならなくなる。 ・その際、アクセスログの取得は誰の作業? ・無いとは思いますが、"$_REQUEST"関連のセキュリティ情報を気にしなくてはいけなくなる。 スクリプト書くだけなら業者のコストは1人日分もかからないと思います。会社としての発生しているコストは、すでにそれを超過しているかと。。。 更に追加で、コストが掛かり続ける事になります。早めの判断が必要だと思いますよ。 私の感覚だと、上司からストップがかからないことが不思議なくらいです。
tajix_japan

2017/01/05 00:38

有難うございます。 正規表現であればゴミ文字が排除できるかもしれません。 本日明日と手が付けられないため、対応結果については土曜日のご報告となります。 有難うございました。 補足 いろいろご心配をおかけしているようなので補足しますと example.com は私の管理サーバー(単にHTMLのホームページがあるだけ) design.example.com が開発部門の管理サーバー(データベース対応)です。 出先でdesign.example.comの情報を見ることが多いのですが、特定情報だけを見るのにログイン後に奥深いところまで毎回同じ内容の情報を手入力の上クリックしていく必要があります。スマホ対応出来ていない割に1ページあたりの情報が多すぎ、その毎回の反応の遅さもあり大変手間なのです。僅か数行の情報を取り出すのに5分くらい掛ります。 そこで、example.com(私の管理サーバー)を経由してdesign.example.comにログインさせた後はすぐにその情報を見れるものを作りたいと思っています。 とりあえず、example.com(私の管理サーバー)のフォームからdesign.example.comにログインすると、直後にmoto.htmlでその必要な情報を表示することまでは出来ました。 あとは、このmoto.htmlの情報をAPIを通してスマホに投げれば出来上がりのところまで来ています。 このアプリは営業部門の人間には喜ばれますが開発部門にとっては無用のアプリのため、開発部門の開発費(データベース開発費)で作ってもらうことは出来ません。人脈もありません。また10年以上経過しているもので、数年後に更新予定です。 ということで、スクレイピングでしか対応できないのです。 また、仕事として与えられているわけではなく、殆ど私の趣味で作っております。 私の本来の仕事は商品企画です。文系出身でITは素人です。与えられている仕事はIT関係は0%です。たまたま一部のコンテンツ更新用にホームページのアクセス権を持っているに過ぎません。 今回のアプリも、営業部門の人間が喜んでくれるのが楽しくてやってます。誰に頼まれたわけでもなく趣味の一環です。趣味なので全ての開発はアフター5か早朝、休日にやっています。上司は仕事に影響ない範囲で遊ぶことは多目に見てくれています。こんなアプリがあったら自分も助かるし、フルオーダーをタダで出来るので(笑) ということで、私の技術力が低いのは素人故、お許し願えますでしょうか? 何度もお手数をお掛けし申し訳ありませんが宜しくお願い致します。
退会済みユーザー

退会済みユーザー

2017/01/05 01:09

マッシュアップ用のAPIということですね。質問内容にあるディレクトリ構成とも違うこと、理解しました。 イントラでの使用のようなので、セキュリティ的にも性善説で乗り切れそうですね。 design.example.com のアクセスログは、機械アクセスが汚すことになるので、開発部門とはきちんと連携したほうが良いと思います。 利用者のできたアプリは、趣味でやっていても対応が必要になります。大変だと思いますががんばってください。そして、更新時には業務として開発部門になすりつけるべく事前に調整しておいて下さい。
tajix_japan

2017/01/05 01:35

アドバイス戴き有難うございます。完成したら開発部門には連絡させて戴きます。 preg_match_all での対応結果については、土曜日にご報告させて戴きます。 宜しくお願い致します。
tajix_japan

2017/01/07 05:13

有難うございます。 ゴミ文字問題は  $user_list = json_decode( '['.$json.']' ); で解決できました。 まだ最終完成には至りませんが、PHP部分についての問題は解決いたしました。 有難うございました。
退会済みユーザー

退会済みユーザー

2017/01/07 06:53

json_decode を利用するにしても、 preg_match_all で置換/整理した方がいいですよ。 (ん?preg_match_all での置換なら配列に入っているか。) まぁ、意図した出力になったのであれば、次の課題に進んだほうがイイですね。 がんばってください。
tajix_japan

2017/01/07 06:56

了解です。有難うございました。
guest

0

ベストアンサー

下記のように $newphrase を扱っておられますが、str_replace から返ってきているのはテキストです。なので、$user_list にはテキストが1要素入った配列が入ることになると思います。

PHP

1$newphrase = str_replace($moto, $api_1, $homepage); 2// (中略) 3 $user_list = 4[ 5$newphrase 6 ];

PHP

1// こうなってしまうはず 2$str="['no'=>'1','name'=>'Yamada'],['no'=>'2','name'=>'Tanaka'], "; 3$ar=[$str]; 4var_dump($ar); 5/* 6array(1) { 7 [0]=>; 8 string(59) "['no'=>;'1','name'=>;'Yamada'],['no'=>;'2','name'=>;'Tanaka'], " 9} 10*/

なので、
['no'=>'1','name'=>'Yamada'],['no'=>'2','name'=>'Tanaka'], ではなく
{"no":"1","name":"Yamada"},{"no":"2","name":"Tanaka"}, となるように置換した上で最後のカンマを取り、json_decode して配列として扱ったほうが良いような。

PHP

1$json='{"no":"1","name":"Yamada"},{"no":"2","name":"Tanaka"}'; // 最後のカンマが有るとデコードに失敗してNULLが返る 2$user_list = json_decode( '['.$json.']' ); 3var_dump($user_list); 4/* 5array(2) { 6 [0]=>; 7 object(stdClass)#1 (2) { 8 ["no"]=>; 9 string(1) "1" 10 ["name"]=>; 11 string(6) "Yamada" 12 } 13 [1]=>; 14 object(stdClass)#2 (2) { 15 ["no"]=>; 16 string(1) "2" 17 ["name"]=>; 18 string(6) "Tanaka" 19 } 20} 21 */

【JSON】
http://www.json.org/json-ja.html

【非エンジニアに贈る「具体例でさらっと学ぶJSON」 | Developers.IO】
http://dev.classmethod.jp/etc/concrete-example-of-json/

投稿2017/01/05 18:08

kei344

総合スコア69398

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

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

tajix_japan

2017/01/07 05:12

有難うございます。 ゴミ文字問題は  $user_list = json_decode( '['.$json.']' ); で解決できました。 深く御礼申し上げます。 助かりました。まだ最終完成には至りませんが、PHP部分についての問題は解決いたしました。 有難うございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問