PHP-ParseGeoPoint上的Parse SDK查询无法正常运行

时间:2019-01-17 14:36:24

标签: javascript php google-maps-api-3 parse-platform

我遇到了一个无法解决的问题,已经尝试了好几个星期,但我只是无法弄清楚自己做错了什么,或者Parse PHP中是否有什么问题SDK。

我建立了一个以 Parse Server 作为后端的网站,这是一个具有位置检测功能的列表网站,而且我正在使用Chrome(我也尝试过Firefox和Safari,相同的问题)。

我的步骤:

  1. 进入首页后,浏览器会要求您允许位置检测。
  2. 如果单击“位置”按钮,则可以将Google地图打开为模态,然后将图钉固定在所需的位置,也可以通过移动滑块来设置距离范围。我选择英国伦敦
  3. 我在Chrome中获得了正确的控制台消息:

    距离:87公里
    MARKER LAT:51.522497992110246-MARKER LNG:-0.12863733794108612

问题出在这里,网站仅显示一些已发布的广告,那些是我通过移动应用发布的广告(我自己的源代码,还有Parse iOS和Android SDK),它没有展示我通过网站提交的那些广告。奇怪的是,如果我从网站上发布广告并且打开我的移动应用程序,那么我可以看到它们!

如果我检查数据库,则无论我是通过网站还是通过移动应用程序提交广告,都可以正确存储广告的GeoPoint坐标。

最后,如果我使用页面顶部的搜索栏按关键字进行搜索,则可以找到我在网站上发布的那些广告。因此,基本上没有关键字,没有通过网站发布的广告...

这是我用于查询广告的PHP代码(注意;以$ADS_开头的变量是在另一个文件中声明的简单字符串,例如$ADS_LOCATION = "ads_location"等):

/*--- variables ---*/
$isFollowing = $_GET['isFollowing'];
$option = $_GET['option'];
$upObjID = $_GET['upObjID'];
$latitude = $_GET['lat'];   // 51.522497992110246
$longitude = $_GET['lng'];  // -0.12863733794108612
$dist = $_GET['distance'];
$distance = (int)$dist;     // 50
$category = $_GET['category'];
$sortBy = str_replace(' ', '', $_GET['sortBy']);
$keywords = preg_split('/\s+/', $_GET['keywords']);

// query Ads
try {
   $query = new ParseQuery($ADS_CLASS_NAME);
   $query->equalTo($ADS_IS_REPORTED, false);

   // it's following.php
   if ($isFollowing == true) {
      $currentUser = ParseUser::getCurrentUser();
      $cuObjIdArr = array(); 
      array_push($cuObjIdArr, $currentUser->getObjectId());
      $query->containedIn($ADS_FOLLOWED_BY, $cuObjIdArr);

   // it's User profile page
   } else if ($upObjID != null) {
      $userPointer = new ParseUser($USER_CLASS_NAME, $upObjID);
      $userPointer->fetch();
      $query->equalTo($ADS_SELLER_POINTER, $userPointer);

      if ($option == 'selling'){ $query->equalTo($ADS_IS_SOLD, false);
      } else if ($option == 'sold'){ $query->equalTo($ADS_IS_SOLD, true); 
      } else if ($option == 'liked'){ $query->containedIn($ADS_LIKED_BY, array($userPointer->getObjectId())); }

   // it's index.php
   } else {

      // nearby Ads
      if ($latitude != null  &&  $longitude != null) {
         $currentLocation = new ParseGeoPoint($latitude, $longitude);

         $query->withinKilometers("location", $currentLocation, $distance);


      // nearby DEFAULT LOCATION COORDINATES
      } else { 
         $defaultLocation = new ParseGeoPoint($DEFAULT_LOCATION_LATITUDE, $DEFAULT_LOCATION_LONGITUDE);

         $query->withinKilometers($ADS_LOCATION, $defaultLocation, $DISTANCE_IN_KM); 

      }

      // keywords
      if (count($keywords) != 0) { $query->containedIn($ADS_KEYWORDS, $keywords); }

      // category
      if ($category != "All") { $query->equalTo($ADS_CATEGORY, $category); }

      // sort by
      switch ($sortBy) {
         case 'Newest': $query->descending("createdAt");
            break;
         case 'Price:lowtohigh': $query->ascending($ADS_PRICE);
            break;
         case 'Price:hightolow': $query->descending($ADS_PRICE);
            break;
         case 'MostLiked': $query->descending($ADS_LIKES);
            break;

         default: break;
      }// ./ sort by

   }// ./ If


   // perform query
   $adsArray = $query->find(); 
   if (count($adsArray) != 0) {
      for ($i = 0;  $i < count($adsArray); $i++) {
         // Parse Obj
         $adObj = $adsArray[$i];

         // image 1
         $adImg = $adObj->get($ADS_IMAGE1);
         // title
         $adTitle = substr ($adObj->get($ADS_TITLE), 0, 24).'...';
         // currency
         $adCurrency = $adObj->get($ADS_CURRENCY);
         // price
         $adPrice = $adObj->get($ADS_PRICE);

         echo '
            <!-- Ad card -->
            <div class="col-lg-3 col-md-5 portfolio-item">
               <div class="card">
         ';

         // Sold badge
         $isSold = $adObj->get($ADS_IS_SOLD);
         if ($isSold) { echo '<div class="card-sold-badge"><img src="assets/images/sold-badge.png"></div>'; }
         echo '
            <a href="ad-info.php?adObjID='.$adObj->getObjectId().'"><img src="'.$adImg->getURL().'"></a>
            <div class="card-body">
               <p class="card-title"><a href="ad-info.php?adObjID='.$adObj->getObjectId().'">'.$adTitle.'</a></p>
               <p class="card-price">'.$adCurrency.' '.$adPrice.'</p>
            </div>
            </div>
            </div>
         ';
      }// ./ For

   // no ads
   } else {
      echo '
         <div class="col-lg-12 col-md-12">
            <div class="text-center" style="margin-top: 40px; font-weight: 600">No Ads found.</div>
         </div>
      ';
   }

// error
} catch (ParseException $e){ echo $e->getMessage(); }

以上代码来自名为query-ads.php的单独文件,并显示在div中:

<div class="row" id="adsGrid"></div>

我执行AJAX函数来调用query-ads.php

function queryAds(catName, keywords) {
        // category
        if (catName == null) { catName = "All"; }
        document.getElementById("categoryName").innerHTML = '<h5 id="categoryName"><strong>' + catName + '</strong></h5>';
        // keywords
        if (keywords == null) { keywords = ''; }

        // console.log('KEYWORDS: ' + keywords);
        // console.log('LAT: ' + latitude + ' -- LNG: ' + longitude);
        console.log('DISTANCE: ' + distance + ' Km');
        // console.log('SORT BY: ' + sortBy);

        $.ajax({
            url:'query-ads.php',
            data: 'lat=' + latitude + '&lng=' + longitude + '&distance=' + distance + '&category=' + catName + '&keywords=' + keywords + '&sortBy=' + sortBy,
            type: 'GET',
            success:function(data) {
                document.getElementById("adsGrid").innerHTML = data;
            }, 
            // error
            error: function(xhr, status, error) {
                var err = eval("(" + xhr.responseText + ")");
                swal(err.Message);
        }});
    }

这也是我的JavaScript代码:

         var cityStateButton = document.getElementById(“ cityState”);

/*--- variables --*/
// localStorage.clear();

var latitude = localStorage.getItem('latitude');
var longitude = localStorage.getItem('longitude');
var distance = localStorage.getItem('distance');
if (distance == null) { distance = 50; }
var map;
var markers = [];
var geocoder;
var sortBy = document.getElementById('sortByBtn').innerHTML;
console.log("1st LATITUDE: " + latitude + " -- 1st LONGITUDE: " + longitude + ' -- 1st DISTANCE: ' + distance + ' -- 1st SORT BY: ' + sortBy);


// Call functions
if (latitude == null) { getCurrentLocation();
} else { getAddress(); }



// ------------------------------------------------
// MARK: - GET CURRENT LOCATION
// ------------------------------------------------
function getCurrentLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(getPosition, showError);

    } else { 
        swal("Geolocation is not supported by this browser.");

        // set default location coordinates
        latitude =  <?php echo $DEFAULT_LOCATION_LATITUDE ?>;
        longitude = <?php echo $DEFAULT_LOCATION_LONGITUDE ?>;
        getAddress();
    }
}

function getPosition(position) {
    latitude = position.coords.latitude;
    longitude = position.coords.longitude;
    getAddress();
}

function showError(error) {
    switch(error.code) {
        case error.PERMISSION_DENIED:
            swal("You have denied your current Location detection.");
            break;
        case error.POSITION_UNAVAILABLE:
            swal("Location information is unavailable.");
            break;            
        case error.TIMEOUT:
            swal("The request to get your current location timed out.");
            break;
        case error.UNKNOWN_ERROR:
            swal("An unknown error occurred.");
            break;
    }

    // set default location
    latitude = <?php echo $DEFAULT_LOCATION_LATITUDE ?>;
    longitude = <?php echo $DEFAULT_LOCATION_LONGITUDE ?>;
    getAddress();
}

function getAddress () {   
    // geocoding API
    var geocodingAPI = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + latitude + "," + longitude + "&key=<?php echo $GOOGLE_MAP_API_KEY ?>";
    $.getJSON(geocodingAPI, function (json) {
        if (json.status == "OK") {
            var result = json.results[0];
            var city = "";
            var state = "";
            for (var i = 0, len = result.address_components.length; i < len; i++) {
                var ac = result.address_components[i];
                if (ac.types.indexOf("locality") >= 0) { city = ac.short_name; }
                if (ac.types.indexOf("country") >= 0) { state = ac.short_name; }
            }// ./ For

            // show city, state
            cityStateButton.innerHTML = '<i class="fas fa-location-arrow"></i> &nbsp;' + city + ', ' + state;

            // call query
            queryAds();

            // save gps coordinates
            localStorage.setItem('latitude', latitude);
            localStorage.setItem('longitude', longitude);
            // console.log("LAT (getAddress): " + latitude + " -- LNG (getAddress): " + longitude);

            // call function
            initMap();

        }// ./ If
    });
}



//---------------------------------
// MARK - INIT GOOGLE MAP
//---------------------------------
var mapZoom = 12;
function initMap() {  
    var location = new google.maps.LatLng(latitude, longitude);
    map = new google.maps.Map(document.getElementById('map'), {
        zoom: mapZoom,
        center: location,
        mapTypeId: 'roadmap',
        disableDefaultUI: true,
        mapTypeControl: false,
        scaleControl: false,
        zoomControl: false
    });

    // call addMarker() when the map is clicked.
    map.addListener('click', function(event) {
        addMarker(event.latLng);
    });

    // Add a marker in the center of the map.
    addMarker(location);
}


function addMarker(location) {
    clearMarkers();
    var marker = new google.maps.Marker({
        position: location,
        map: map
    });
    markers.push(marker);

    // set lat & lng based on marker's coordinates
    latitude = marker.getPosition().lat();
    longitude = marker.getPosition().lng();
    console.log("MARKER LAT: " + latitude + " - MARKER LNG: " + longitude);

    // zoom & center map based on pin
    metersPerPx = 156543.03392 * Math.cos(latitude * Math.PI / 180) / Math.pow(2, mapZoom)
    map.setZoom(metersPerPx/2.6);
    map.setCenter(marker.getPosition());        
}

function setMapOnAll(map) {
    for (var i = 0; i < markers.length; i++) {
        markers[i].setMap(map);
    }// ./ For
}

// Removes the markers from the map, but keeps them in the array.
function clearMarkers() { 
    setMapOnAll(null);
    markers = [];
}



//---------------------------------
// MARK - GET GPS COORDS FROM ADDRESS
//---------------------------------
function getCoordsFromAddress(address) {   
    geocoder = new google.maps.Geocoder();
    geocoder.geocode( { 'address': address}, function(results, status) {
        if (status == 'OK') {
            map.setCenter(results[0].geometry.location);
            var marker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
            });
            markers.push(marker);

            // set coordinates
            latitude = results[0].geometry.location.lat();
            longitude = results[0].geometry.location.lng();

            // save gps coordinates
            localStorage.setItem('latitude', latitude);
            localStorage.setItem('longitude', longitude);

            // console.log("SEARCH LOCATION LAT: " + latitude + " - SEARCH LOCATION LNG: " + longitude);

            initMap();

        // error
        } else { swal('Geocode was not successful for the following reason: ' + status); 
    }});
}

我认为这是ParseGeoPoint的问题,但这不是问题,因为如果我对关键字进行文本搜索,就可以找到广告。

1 个答案:

答案 0 :(得分:0)

找到了解决方案,我将其发布,以防其他人在Parse PHP SDK上遇到此类问题,因为自2018年初以来就存在。

在将广告保存到数据库的脚本中,我根据提交项目的描述和标题存储了小写关键字:

$kStr = $description. " " .$title. " " .$currentUser->getUsername();
$keywords = explode( " ", strtolower($kStr) );

哪个工作正常,但是由于带有关键字过滤器的PHP ParseQuery至少需要在关键字数组中包含一个空项目,因此我不得不在上面的代码下方添加以下简单行:

array_push($keywords, "");

通过这种方式,数据库存储所有正确的关键字+一个空关键字:“” ,这是关键字Arrat-type字段在数据库中的样子的示例:

[
  "lorem",
  "ad",
  "ipsum",
  "johndoe",
  "" <-- this is the empty item that the SDK needs to properly perform a query in case of additional filters (in my case, a ParseGeopoint one)
]

在Parse Server的开发人员将解决此问题之前,这可能只是一个临时技巧。它有效,所以为什么不;)