店铺经纬度计算距离然后分页排序

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/ahaotata/article/details/88105342

根据经纬度计算距离,根据距离排序或者是根据店铺销量排序

代码如下

<?php
/**
 * topapi
 *
 * -- user.shop.list
 * -- 店铺分页距离排序
 */
class topapi_api_v2_user_app_userShop implements topapi_interface_api{

    /**
     * 接口作用说明
     */
    public $apiDescription = '店铺列表';

    /**
     * 定义API传入的应用级参数
     * @desc 用于在调用接口前,根据定义的参数,过滤必填参数是否已经参入,并且定义参数的数据类型,参数是否必填,参数的描述
     * @return array 返回传入参数
     */
    public function setParams()
    {
        return [
            'cat_id'      => ['type'=>'string', 'valid'=>'', 'default'=>'', 'msg'=>'分类', 'example'=>'', 'description'=>''],
            'search'      => ['type'=>'string', 'valid'=>'', 'default'=>'', 'msg'=>'', 'example'=>'', 'description'=>''],
            'fans'      => ['type'=>'string', 'valid'=>'', 'default'=>'', 'msg'=>'', 'example'=>'', 'description'=>''],
            'sort'      => ['type'=>'string', 'valid'=>'', 'default'=>'', 'msg'=>'', 'example'=>'', 'description'=>''],
            'page_no'      => ['type'=>'string', 'valid'=>'', 'default'=>'', 'msg'=>'', 'example'=>'', 'description'=>''],
            'page_size'      => ['type'=>'string', 'valid'=>'', 'default'=>'', 'msg'=>'', 'example'=>'', 'description'=>''],
            'longitude'      => ['type'=>'string', 'valid'=>'required', 'default'=>'', 'msg'=>'经度必传', 'example'=>'', 'description'=>''],
            'latitude'      => ['type'=>'string', 'valid'=>'required', 'default'=>'', 'msg'=>'纬度必传', 'example'=>'', 'description'=>''],
        ];
    }

    public function handle($params)
    {

        //分页使用
        $pageSize = $params['page_size'] ? $params['page_size'] : 10;
        $pageNo = $params['page_no'] ? $params['page_no'] : 1;
        $start =  ($pageNo-1) * $pageSize;


        ##搜索
        $where = "status = 'active'";
        if(!empty($params['search'])){
            $where = $where . " and (shop_name like '%".$params['search']."%' or mobile like '".$params['search']."%')" ;
        }

        ##分类
        if($params['cat_id']){
            $params['cat_id'] = intval($params['cat_id']);
            $setting = app::get('sysshop')->model('shop_rel_lv1cat')->getList("*",['cat_id'=>$params['cat_id']]);

            if(empty($setting)){
                $data['shop_list'] = array();
                return $data;
            }
            $select_shop = array_column($setting,'shop_id');
            $ids = implode(',',$select_shop);
            $where = $where. " and shop_id in ($ids)";
        }

        ##排序
        if($params['sort'] == 0){
            ##降序
            $order = 'fansnum';
            $by = 'desc';

        }elseif($params['sort'] == 1){
            ##升序
            $order = 'distance';
            $by = 'asc';
        }else{
            $order = 'shop_id';
            $by = 'desc';
        }


        ##看看是否可以在sql语句中计算距离然后排序分页,但是有一个问题
        ##即,那些没有经纬度的店铺总是排序到最前面
        ##待解决 数据库经纬度字段默认为0
        $qb = app::get('sysshop')->database()->createQueryBuilder();
        $data['shop_list'] = $qb->select("shop_id,shop_name,seller_id,shop_logo,shop_area,shop_addr,goodsnum,fansnum,longitude,latitude,is_recommend,
            (round(6367000 * 2 * asin(sqrt(pow(sin(((latitude * pi()) / 180 - ({$params['latitude']} * pi()) / 180) / 2), 
            2) + cos(({$params['latitude']} * pi()) / 180) * cos((latitude * pi()) / 180) * pow(sin(((longitude * pi()) / 180 - ({$params['longitude']} * pi()) / 180) / 2),
             2))))) AS distance
            ")
            ->from('sysshop_shop')
            ->where("{$where}")
            ->setFirstResult($start)->setMaxResults($pageSize)
            ->orderBy($order,$by)
            ->execute()
            ->fetchAll();


        foreach ($data['shop_list'] as $key=>$value){
            if($value['longitude'] == 0 &&  $value['latitude'] == 0){
                $data['shop_list'][$key]['distance'] = '';
            }

        }

        return $data;


    }



    /*
    * 1.纬度1,经度1,纬度2,经度2
    * 2.返回结果是单位是KM。
    * 3.保留一位小数
    */
    function getDistance($lat1,$lng1,$lat2,$lng2)
    {
        //将角度转为狐度
        $radLat1 = deg2rad($lat1);//deg2rad()函数将角度转换为弧度
        $radLat2 = deg2rad($lat2);
        $radLng1 = deg2rad($lng1);
        $radLng2 = deg2rad($lng2);
        $a = $radLat1 - $radLat2;
        $b = $radLng1 - $radLng2;
        $s = 2*asin(sqrt(pow(sin($a/2),2)+cos($radLat1)*cos($radLat2)*pow(sin($b/2),2)))*6371;
        return round($s,1);
    }




    ##另外一种距离分页计算排序
    public  function otherDistance($where,$params,$start,$pageSize){

        $qb = app::get('sysshop')->database()->createQueryBuilder();
        $data['shop_list'] = $qb->select("shop_id,shop_name,seller_id,shop_logo,shop_area,shop_addr,goodsnum,fansnum,longitude,latitude,is_recommend ")
            ->from('sysshop_shop')
            ->where("{$where}")
            ->execute()
            ->fetchAll();

        ##距离计算
        if($params['sort'] ==1  && $params['longitude']){
            foreach ($data['shop_list'] as $key=>$value){
                if($value['longitude']){

                    $data['shop_list'][$key]['distance'] = $this->getDistance($params['latitude'],$params['longitude'],$value['latitude'],$value['longitude']);
                }else{
                    ##为了没有经纬度的时候排序到最后
                    $data['shop_list'][$key]['distance'] = 1000000000;
                }
            }
        }

        ##排序
        if($params['sort'] == 0){
            ##降序
            $order = 'fansnum';
            $key = array_column($data['shop_list'],$order);
            array_multisort($key,SORT_DESC,$data['shop_list']);

        }elseif($params['sort'] == 1){
            ##升序
            $order = 'distance';
            $key = array_column($data['shop_list'],$order);
            array_multisort($key,SORT_ASC,$data['shop_list']);
        }

        ##把之前的添加数据置为空
        foreach ($data['shop_list'] as $key=>$value){
            if($value['distance'] == 1000000000){
                $data['shop_list'][$key]['distance'] = '';
            }
        }


        ##分页
        $data['shop_list'] = array_slice($data['shop_list'], $start, $pageSize);


        return $data;
    }


}



猜你喜欢

转载自blog.csdn.net/ahaotata/article/details/88105342