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

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

ただいまの
回答率

88.92%

Google mapで取得した位置データをmysqlのgeometryフィールドに挿入できない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 294

hiro-chan

score 18

phpファイルにajaxを記述して、取得したユーザ名と現在位置をset_latlng_test.phpに送り、そのユーザの位置情報を格納したmysqlにupdateする実装をしております。

漠然とですが、updateが実施されなく困っております。
何かヒントがございましたらご教示いただけると幸いです。

database.php

<?php

/**
 * database_test.php
 * @since 2018/09/18
 */
function h($string)
{
    return htmlspecialchars($string, ENT_QUOTES, 'utf-8');
}

function connect()
{
    $dsn = 'mysql:host=localhost;dbname=test_login;charset=utf8mb4;';
    $username = 'root';
    $password = '';
    $options = [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ];
    $pdo = new PDO($dsn, $username, $password, $options);
    return $pdo;
}

main_test.php

<?php
/**
 * main_test.php
 *
 * @since 2018/09/18
 */
session_start();

require 'database_test.php';
$login_user = $_SESSION['login_user'];
?>
・
・
・
    <script>

        $(function() {
            $('#btn1').click(function(){
                var form = document.forms.myform;
                navigator.geolocation.getCurrentPosition(initMap, error);//成功と失敗を判断
                var hoge = `<?php echo h($login_user[user_name]); ?>`;

                //緯度経度をDBに格納
                function initMap(position) {
                    var latitude  = position.coords.latitude;//緯度
                    var longitude = position.coords.longitude;//経度
                    var latlng = new google.maps.LatLng( latitude, longitude );
                    var map = new google.maps.Map(document.getElementById('map'), {
                        zoom: 14,
                        center: latlng
                    });  
                    //マーカーの設定
           var marker = new google.maps.Marker({
                        position: latlng,
                        map: map,
                        icon: {
                            //url: sailboat_image, 
                            scaledSize: new google.maps.Size(60, 60)
                        }
                    });
                    function insert_latlng(){
                        $.ajax({
                            url: "set_latlng_test.php",
                            type: "POST",
                            datatype: "text",
                            data: {
                                "login_user" : hoge,
                                "latitude" : latitude,
                                "longitude" : longitude
                            },
                        }).done(function(data){
                            console.log(data);
                            console.log(hoge);
                            console.log("DB通信完了");
                        }).fail(function(data){
                            console.log("DB通信失敗");
                            console.log(data);
                        });
                    };
                    insert_latlng();  
                };
                function error() {
                    console.log("map表示でエラー発生")
                };
            });
        });
    </script>
・
・


set_latlng_test.php

<?php
/**
 * main_test.php
 *
 * @since 2018/09/18
 */

//print_r($_POST['ary']);


ini_set('display_errors',1); //これ重要

session_start();

require 'database_test.php';
//$login_user = $_SESSION['login_user'];
$login_user = $_POST['login_user'];
$latitude = $_POST['latitude'];
$longitude = $_POST['longitude'];

$geometry = "ST_GeomFromText('POINT(" + (string)$longitude + " " + (string)$latitude + ")')";

$pdo = connect();
$stmt2 = $pdo->prepare("UPDATE User3 SET latlng = ? WHERE user_name = ?");
$params_add_latlng = [];
$params_add_latlng[] = $geometry;
$params_add_latlng[] = $login_user;
// SQL実行
$stmt2->execute($params_add_latlng);

?>


mysqlのデータベース test_login
尚、latlngフィールドはユーザでログインした際に、適当な位置情報を格納しております。

mysql> select * from User3;
+----+------------+--------------------------------------------------------------+---------------------------+
| id | user_name  | password                                                     | latlng                    |
+----+------------+--------------------------------------------------------------+---------------------------+
|  1 | ashial.Ltd | pass                                                         |        `?    fxa@伀{摶攸@       |
|  2 | minase     | $2y$10$Yui/2sBgOTAKO9O3Qr/n2e2U69z9mopEu73iNAx0RYSuolEPIp9Om |        `?    fxa@伀{摶攸@       |
|  3 | uchida     | $2y$10$.lb2b7InyUYQ2yzfCr1AD.8aKb9y5rN2dRQQFb2jEEjSiXC4vhL8y |        `?    fxa@伀{摶攸@       |
|  4 | yamada     | $2y$10$easFTwRXddoVepx4ojct8u.7Fdzljv47XfDBWXZAFA1Mj1/VUvbVq |        `?    fxa@伀{摶攸@       |
+----+------------+--------------------------------------------------------------+---------------------------+
4 rows in set (0.00 sec)
mysql> SELECT id, user_name, ST_X(latlng) as lng, ST_Y(latlng) as lat, ST_AsText(latlng) as geomtext FROM User3;
+----+------------+------------+-----------+-----------------------------+
| id | user_name  | lng        | lat       | geomtext                    |
+----+------------+------------+-----------+-----------------------------+
|  1 | ashial.Ltd | 139.762522 | 35.706752 | POINT(139.762522 35.706752) |
|  2 | minase     | 139.762522 | 35.706752 | POINT(139.762522 35.706752) |
|  3 | uchida     | 139.762522 | 35.706752 | POINT(139.762522 35.706752) |
|  4 | yamada     | 139.762522 | 35.706752 | POINT(139.762522 35.706752) |
+----+------------+------------+-----------+-----------------------------+
4 rows in set (0.01 sec)


イメージ説明
おそらく以下の箇所が怪しそうです。

$geometry = "ST_GeomFromText('POINT(" + (string)$longitude + " " + (string)$latitude + ")')";
$stmt2 = $pdo->prepare("UPDATE User3 SET latlng = ? WHERE user_name = ?");


■仕様説明
main_test.phpの
$login_user = $_SESSION['login_user'];
から、ログインユーザ名を取得し、
var hoge = <?php echo h($login_user[user_name]); ?>;
でhogeに格納しております。
ボタン「btn1」をクリックすると、latitudeとlongitudeが取得され、hogeと共に
insert_latlng()でset_latlng_test.phpへPOSTされます。
set_latlng_test.phpで受け取ったhogeのユーザ名のレコードの位置情報をupdateするようにしています。
chromeのデバッグツールで、POSTによりset_latlng_test.phpへhoge、latitude、longitudeが
送信されたことは確認済です。

尚、tableはこのように作りました。

CREATE TABLE User3 (
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'AI',
user_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT '氏名',
password VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'パスワード',
latlng geometry NOT NULL,
PRIMARY KEY  (id),
UNIQUE KEY user_name (user_name),
SPATIAL KEY spot_latlng_index (latlng)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

長文で読みづらいかと思いますが、何卒ご協力くださいますようよろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

$geometry = "ST_GeomFromText('POINT(" . (string)$longitude . " " . (string)$latitude . ")')";


って話だったりしない?


もしかすると

$pdo = connect();
$stmt2 = $pdo->prepare("UPDATE User3 SET latlng = ST_GeomFromText('POINT(:lng :lan)') WHERE user_name = :user");
$stmt2->bindValue(':lng', $longitude, PDO::PARAM_INT);
$stmt2->bindValue(':lan', $latitude, PDO::PARAM_INT);
$stmt2->bindValue(':user', $login_user, PDO::PARAM_STR);
// SQL実行
$stmt2->execute();


こうなんじゃないかなぁ。
(名前付きプレースホルダーに改めてみました。)

SQL文に直接POSTやGET由来の変数を展開してしまうと、
SQLインジェクション攻撃の標的になりかねないため、
上記のようなプレースホルダーを駆使した書き方を身に着けたいものです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/01/28 18:33

    execute()で乱暴にプレースホルダー用のデータを与えずに、
    bindValue()で一つ一つ丁寧に与える書き方をしているため、
    execute()の引数は不要になっています。

    キャンセル

  • 2020/01/29 10:10

    ご回答ありがとうございます。
    $stmt2 = $pdo->prepare("UPDATE User3 SET latlng = ST_GeomFromText('POINT($longitude $latitude)') WHERE user_name = '$login_user'");
    $stmt2->execute();
    にすると無事にDBのupdateができました

    キャンセル

  • 2020/01/29 10:34

    prepare()で与えるSQL文で、変数を直接置くのは本末転倒です。
    bindValue()でプレースホルダーを駆使しないと、POST受信したデータに意図的なものが仕込まれたら太刀打ちできません。SQLインジェクションっていうんですけどね。
    セキュリティ対策の意識がお有りであれば、もうちょっと踏ん張って、プレースホルダーを駆使した方法での実現ができるようになることを望みます。

    キャンセル

0

set_latlng_test.phpを以下のように変更するとDBのupdateができました。

$stmt2 = $pdo->prepare("UPDATE User3 SET latlng = ST_GeomFromText('POINT($longitude $latitude)') WHERE user_name = '$login_user'");
$stmt2->execute();

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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