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

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

ただいまの
回答率

90.35%

  • PHP

    21269questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 785

tajix_japan

score 68

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

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

$crawler="http://example.com/moto.html?fm=woman";

$homepage = file_get_contents($crawler);

$moto = array("【no】", "【name】", "【】<BR>");
$api_1   = array("['no'=>'", "','name'=>'", "'],");

$newphrase = str_replace($moto, $api_1, $homepage);

echo $newphrase;

?>

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

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

【PHP その2】

<?php

function returnJson($resultArray){
  if(array_key_exists('callback', $_GET)){
    $json = $_GET['callback'] . "(" . json_encode($resultArray) . ");";
  }else{
    $json = json_encode($resultArray);
  }
  header('Content-Type: text/html; charset=utf-8');
  echo  $json;
  exit(0);
}

$type = $_REQUEST['user_type'];

//  ユーザリストの初期化
$user_list = [];
//  返却値の初期化
$result = [];

try {
  //  値の検証
  if (empty($type)) {
    throw new Exception("no type...");
  }

  //  ユーザリストの作成
  switch ($type) {
    case 'a':
      $user_list = 
[
['no'=>'10','name'=>'Yoshida'],
['no'=>'11','name'=>'Mori']
      ];
      break;

    default:
      //  不正な値
      throw new Exception("Invalid value...");
      break;
  }

  //  返却値の作成
  $result = [
    'result' => 'OK',
    'users' => $user_list
  ];
} catch (Exception $e) {
  $result = [
    'result' => 'NG',
    'message' => $e->getMessage()
  ];
}

//  JSONでレスポンスを返す
returnJson($result);
?>

上記の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

$crawler="http://example.com/moto.html";

$homepage = file_get_contents($crawler);

$moto = array("【no】", "【name】", "【】<BR>");
$api_1   = array("['no'=>'", "','name'=>'", "'],");

$newphrase = str_replace($moto, $api_1, $homepage);


function returnJson($resultArray){
  if(array_key_exists('callback', $_GET)){
    $json = $_GET['callback'] . "(" . json_encode($resultArray) . ");";
  }else{
    $json = json_encode($resultArray);
  }
  header('Content-Type: text/html; charset=utf-8');
  echo  $json;
  exit(0);
}

$type = $_REQUEST['user_type'];

//  ユーザリストの初期化
$user_list = [];
//  返却値の初期化
$result = [];

try {
  //  値の検証
  if (empty($type)) {
    throw new Exception("no type...");
  }

  //  ユーザリストの作成
  switch ($type) {
    case 'a':
      $user_list = 
[
$newphrase
      ];
      break;

    default:
      //  不正な値
      throw new Exception("Invalid value...");
      break;
  }

  //  返却値の作成
  $result = [
    'result' => 'OK',
    'users' => $user_list
  ];
} catch (Exception $e) {
  $result = [
    'result' => 'NG',
    'message' => $e->getMessage()
  ];
}

//  JSONでレスポンスを返す
returnJson($result);
?>

結果

{"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';とリクエストを受け取った形に変形してテストしました。

//$type = $_REQUEST['user_type'];

$type = 'a';

//  ユーザリストの初期化
$user_list = [];
//  返却値の初期化
$result = [];

try {
  //  値の検証
  if (empty($type)) {
    throw new Exception("no type...");
  }



  //  ユーザリストの作成
  switch ($type) {
    case 'a':
    case 'admin':
      $user_list = 

[
$newphrase
      ];
      break;

var_dump($newphrase);

以下同文

と記載してみました。

結果
{"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';としてテストしました。

    case 'g':
    case 'guest':
      $user_list = [
        ['name'=>'香取','age'=>14],
        ['name'=>'草薙','age'=>15],
        ['name'=>'稲垣','age'=>15],
        ['name'=>'岡田','age'=>15],
        ['name'=>'森田','age'=>15],
        ['name'=>'三宅','age'=>15],
       ['name'=>'長野','age'=>15],
        ['name'=>'坂本','age'=>15],
        ['name'=>'井ノ原','age'=>15]
      ];
      break;
    default:


結果

{"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を代入するとゴミ文字が入ってくることで表示出来なくなっていることがわかりました。

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2017/01/04 23:55

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

    キャンセル

回答 2

+3

ちょっと何をやろうとしているのか分かりません。
ので、一般的な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 22:42

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



    キャンセル

  • 2017/01/04 22:53

    外注の業者さんが管理しているのであれば、APIも作ってもらったほうが良いと思いますよ。
    正直、APIが作れる技術レベルに無いようですし。。。

    自サイトをスクレイピングして回答するAPIなんて、レスポンスも悪くなるし、リソースも倍必要になるので、メリットが見いだせません。
    また、業者さんの管理するディレクトリにスクリプトを置くことになると思うので、アクセス権の問題も発生するように思います。

    APIもセキュリティ観点での注意点や、リソースをどのように管理するか、考慮しなければならない点があります。
    十分な学習なしに運営できる仕組みではないので、予算をひねり出す工夫をされたほうが良いと思います。

    キャンセル

  • 2017/01/04 23:07

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

    キャンセル

  • 2017/01/05 08:14 編集

    ツギハギのスクリプトは、本来やりたいことが伝わりにくいので読みたくないのですが、読んでみました。

    以下の点を修正して下さい。
    ・$newphrase は str_replace で全体の一部を置換するのではなく、"【no】1【name】Yamada【】"である行を検出し、それを"['no'=>'1','name'=>'Yamada']"と加工する。preg_match_all でよいかと。

    ただ、やはり、ご自身のスクリプトを管理業者のいるディレクトリに置くことはおすすめしません。

    ざっと考えても、以下のような弊害があります。
    ・業者の理解できないアクセスが発生する。
    ・逆に、おかしなアクセスが発生しても、業者側で判別できなくなる。
    ・"moto.html?fm=woman"の変更をご自身が追いかけなくてはならなくなる。
    ・業者管理ディレクトリ内に業者未管理ファイルが置かれる状態が正となると、おかしなスクリプトが置かれても業者側で気がつけなくなる。
    ・今回のスクリプトが動かない場合の切り分けをご自身で行わなくてはならなくなる。
    ・その際、アクセスログの取得は誰の作業?
    ・無いとは思いますが、"$_REQUEST"関連のセキュリティ情報を気にしなくてはいけなくなる。

    スクリプト書くだけなら業者のコストは1人日分もかからないと思います。会社としての発生しているコストは、すでにそれを超過しているかと。。。
    更に追加で、コストが掛かり続ける事になります。早めの判断が必要だと思いますよ。
    私の感覚だと、上司からストップがかからないことが不思議なくらいです。

    キャンセル

  • 2017/01/05 09: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 10:09

    マッシュアップ用のAPIということですね。質問内容にあるディレクトリ構成とも違うこと、理解しました。

    イントラでの使用のようなので、セキュリティ的にも性善説で乗り切れそうですね。

    design.example.com のアクセスログは、機械アクセスが汚すことになるので、開発部門とはきちんと連携したほうが良いと思います。

    利用者のできたアプリは、趣味でやっていても対応が必要になります。大変だと思いますががんばってください。そして、更新時には業務として開発部門になすりつけるべく事前に調整しておいて下さい。

    キャンセル

  • 2017/01/05 10:35

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

    キャンセル

  • 2017/01/07 14:13

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

    キャンセル

  • 2017/01/07 15:53

    json_decode を利用するにしても、
    preg_match_all で置換/整理した方がいいですよ。

    (ん?preg_match_all での置換なら配列に入っているか。)

    まぁ、意図した出力になったのであれば、次の課題に進んだほうがイイですね。
    がんばってください。

    キャンセル

  • 2017/01/07 15:56

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

    キャンセル

checkベストアンサー

0

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

$newphrase = str_replace($moto, $api_1, $homepage);
// (中略)
      $user_list = 
[
$newphrase
      ];
// こうなってしまうはず
$str="['no'=>'1','name'=>'Yamada'],['no'=>'2','name'=>'Tanaka'], ";
$ar=[$str];
var_dump($ar);
/*
array(1) {
  [0]=>;
  string(59) "['no'=>;'1','name'=>;'Yamada'],['no'=>;'2','name'=>;'Tanaka'], "
}
*/

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

$json='{"no":"1","name":"Yamada"},{"no":"2","name":"Tanaka"}'; // 最後のカンマが有るとデコードに失敗してNULLが返る
$user_list = json_decode( '['.$json.']' );
var_dump($user_list);
/*
array(2) {
  [0]=>;
  object(stdClass)#1 (2) {
    ["no"]=>;
    string(1) "1"
    ["name"]=>;
    string(6) "Yamada"
  }
  [1]=>;
  object(stdClass)#2 (2) {
    ["no"]=>;
    string(1) "2"
    ["name"]=>;
    string(6) "Tanaka"
  }
}
 */

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/07 14:12

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

    キャンセル

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

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • PHP

    21269questions

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