店舗の緯度は距離を計算してページごとに並べ替えます


経緯度によって距離を計算し、距離によって並べ替えたり、店舗販売量によって並べ替えたりします
コードは次のとおりです.
 ['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;
    }


}