iT邦幫忙

1

利用PHP將JSON 資料寫進mySQL資料庫

  • 分享至 

  • xImage

各位大大好:

我想將政府JSON資料寫進mySQL資料庫,
但其中一個 key 的名稱有小括號,例如:「效能(適應症)」,
結果顯示「Warning: Undefined property: stdClass::$效能」,
而資料庫相對應的 column 則被寫入「(適應症)」。
(其他資料都有正確寫進資料庫)

請問有大大能幫忙提點,這該如何解決嗎?
新手卡關好幾天了...感激不盡。

附上程式碼,這也是參考版上大大的程式修改而成的

        <?php
            $handle = fopen("https://data.coa.gov.tw/Service/OpenData/FromM/ADProData.aspx","rb");
            $content = "";
            while (!feof($handle)) {
                $content .= fread($handle, 100000);
            }
            fclose($handle);

            $servername = "servername";
            $username = "username";
            $password = "password";
            $dbname = "dbname";

            $conn = new mysqli($servername, $username, $password, $dbname);
            if ($conn->connect_error) {
                die("Connection failed: " . $conn->connect_error);
            }
            
            $content = json_decode($content);

            foreach ($content as $key => $value) {

                $sql = "INSERT INTO table_name (column1, column2, column3, column4, column5, column6, column7, column8, column9, column10, column11, column12, column13, column14) VALUES ('$value->許可證字號', '$value->動物用藥品中文名稱', '$value->動物用藥品英文名稱', '$value->業者名稱', '$value->業者地址', '$value->製造廠名稱', '$value->製造廠地址', '$value->劑型', '$value->包裝','$value->效能(適應症)','$value->成分','$value->核發日期','$value->有效期間', '$value->外銷專用')";

                if (mysqli_query($conn, $sql)) {
                        echo "New record created successfully";
                } else {
                        echo "Error: " . $sql . "<br>" . mysqli_error($conn);
                }
                
            } 
            mysqli_close($conn);
        ?>
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
淺水員
iT邦大師 6 級 ‧ 2021-08-11 16:38:15
最佳解答

要 INSERT 資料進去,一般不是會用 prepare 處理嗎?


後續補充:

  1. 我也跟樓上一樣比較習慣在 json_decode 的第二個參數加上 true,取值比較方便。
  2. 另外為了避免資料有特殊字元,造成 SQL 錯誤,建議使用 prepare 來處理資料,下面的程式是範例。
//$url="https://data.coa.gov.tw/Service/OpenData/FromM/ADProData.aspx";
//測試時預先抓下來的資料,避免一直跟對方伺服器要資料
$url = "tmp.json";

$handle = fopen($url, "rb");
$content = "";
while (!feof($handle)) {
    $content .= fread($handle, 100000);
}
fclose($handle);
$content = json_decode($content, true);

//連接資料庫
$servername = "servername";
$username = "username";
$password = "password";
$dbname = "dbname";

$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
mysqli_query($conn, 'SET NAMES utf8mb4');

//預先做 prepare,並與參數綁定
$sql = 'INSERT INTO table_name (
    column1, column2, column3, column4, column5, column6, column7,
    column8, column9, column10, column11, column12, column13, column14
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param(
    $stmt, 'ssssssssssssss',
    $col1, $col2, $col3, $col4, $col5, $col6, $col7,
    $col8, $col9, $col10, $col11, $col12, $col13, $col14
);

//把資料寫入資料庫
foreach ($content as $key => $value) {
    $col1 = $value['許可證字號'];
    $col2 = $value['動物用藥品中文名稱'];
    $col3 = $value['動物用藥品英文名稱'];
    $col4 = $value['業者名稱'];
    $col5 = $value['業者地址'];
    $col6 = $value['製造廠名稱'];
    $col7 = $value['製造廠地址'];
    $col8 = $value['劑型'];
    $col9 = $value['包裝'];
    $col10 = $value['效能(適應症)'];
    $col11 = $value['成分'];
    $col12 = $value['核發日期'];
    $col13 = $value['有效期間'];
    $col14 = $value['外銷專用'];
    if (mysqli_stmt_execute($stmt) === false) {
        echo mysqli_error($conn);
    }
}
mysqli_close($conn);
helloit iT邦新手 5 級 ‧ 2021-08-12 09:10:46 檢舉

prepare可順利寫入9999筆資料到mySQL,
謝謝淺水員大大指點迷津!

0
Hankz
iT邦新手 2 級 ‧ 2021-08-11 14:34:56

用大括號刮起來試試看

$value->{效能(適應症)}

-------------- 更新 ----------------

我剛剛實際跑了一下,的確不能用括號
改成用陣列處理就比較不會有這類的問題了

$content = json_decode($content, true);

foreach ($content as $key => $value) {
    echo "其他字串{$value['效能(適應症)']}其他字串";
}
看更多先前的回應...收起先前的回應...
helloit iT邦新手 5 級 ‧ 2021-08-11 14:39:51 檢舉

結果顯示「Fatal error: Uncaught Error: Object of class stdClass could not be converted to string」

這個問題就跟變數或函式規則一樣吧!
只允許中英文底線數字但不能有括號。
如果你非要解,給你個建議:base64_encode
取出來再用base64_decode
缺點大概就是會增加資料庫的資料量就是了。

補充:啊!如果你的key是對column名稱我剛剛就想錯了。
雖然用base64也不是不行。
不過要真的發生這種情況你可能就得自行做「欄位名稱代換」
比如說原本是括號改成前後底線。
或是用別的名稱暫時替代,取出來後再做代換。

Hankz iT邦新手 2 級 ‧ 2021-08-11 15:03:47 檢舉

我沒注意到是function的括號問題
感謝S大

helloit iT邦新手 5 級 ‧ 2021-08-11 16:16:57 檢舉

欄位名稱代換和改成陣列的方式可以順利取到值,
base64的部分我會再研究研究。
感謝Hankz大和Sam大!

4
japhenchen
iT邦超人 1 級 ‧ 2021-08-11 15:16:50

把json變成命名陣列(最後面加個,true)

$content = json_decode($content,true);

我有點不太能適應PHP的字串插補術

$sql = "INSERT INTO table_name (column1, column2, column3, column4, column5, column6, column7, column8, column9, column10, column11, column12, column13, column14) VALUES ('{$value['許可證字號']}', '{$value['動物用藥品中文名稱']}', '{$value['動物用藥品英文名稱']}', '{$value->['業者名稱']}', '{$value['業者地址']}', '{$value['製造廠名稱']}', '{$value['製造廠地址']}', '{$value['劑型']}', '{$value['包裝']}','{$value['效能(適應症)']}','{$value['成分']}','{$value['核發日期']}','{$value['有效期間']}', '{$value['外銷專用']}')";

看更多先前的回應...收起先前的回應...
Hankz iT邦新手 2 級 ‧ 2021-08-11 15:26:16 檢舉

我也不是很喜歡用雙引號做變數插入
大多都是用單引號做字串串接再做排版
畢竟效率比較好,要做調整也比較容易
不過看他變數那麼多...就算了WWW

要做成命名陣列的原因,只是因為要擺脫括號的折磨
$value->效能(適應症) 指的是 $value裡叫【效能】的函數,【適應症】是他的傳入值.....問題是$value裡沒有這個效能函數 .. 於是就出「Warning: Undefined property: stdClass::$效能」的錯了

對付中文及特殊符號,還是轉成命名陣列而不要用object,才不會出錯
$value["效能(適應症)"]

helloit iT邦新手 5 級 ‧ 2021-08-11 16:03:41 檢舉

感謝japhenchen大大解惑!
新手囫圇吞棗,參考許多程式碼東拼西湊,結果不知其所以然。
經過您的解說,終於理解了,真是感激不盡!

helloit iT邦新手 5 級 ‧ 2021-08-12 08:53:40 檢舉

請教japhenchen大大,
我用 count 計算有9999筆資料,但寫入資料庫的只有9976筆。可能是什麼原因呢?

重名...

helloit iT邦新手 5 級 ‧ 2021-08-12 09:19:48 檢舉

原來如此,謝謝japhenchen大大

我要發表回答

立即登入回答