php 如何查询出距离前车多远能开出最近的点?看例子,求解

原文地址:http://phalcon.5iunix.net/reference/di.html
下面要讲的这个例子有点长,但可以很好的解释为什么使用Service Container以及DI。首先,我们假设,我们要开发一个组件命名为SomeComponent。这个组件中现在将要注入一个数据库连接。
在这个例子中,数据库连接在component中被创建,这种方法是不切实际的,这样做的话,我们将不能改变数据库连接参数及数据库类型等一些参数。
class SomeComponent
* The instantiation of the connection is hardcoded inside
* the component so is difficult to replace it externally
* or change its behavior
public function someDbTask()
$connection = new Connection(array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "invo"
$some = new SomeComponent();
$some-&someDbTask();
为了解决上面所说的问题,我们需要在使用前创建一个外部连接,并注入到容器中。就目前而言,这看起来是一个很好的解决方案:
class SomeComponent
protected $_
* Sets the connection externally
public function setConnection($connection)
$this-&_connection = $
public function someDbTask()
$connection = $this-&_
$some = new SomeComponent();
//Create the connection
$connection = new Connection(array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "invo"
//Inject the connection in the component
$some-&setConnection($connection);
$some-&someDbTask();
现在我们来考虑一个问题,我们在应用程序中的不同地方使用此组件,将多次创建数据库连接。使用一种类似全局注册表的方式,从这获得一个数据库连接实例,而不是使用一次就创建一次。
class Registry
* Returns the connection
public static function getConnection()
return new Connection(array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "invo"
class SomeComponent
protected $_
* Sets the connection externally
public function setConnection($connection){
$this-&_connection = $
public function someDbTask()
$connection = $this-&_
$some = new SomeComponent();
//Pass the connection defined in the registry
$some-&setConnection(Registry::getConnection());
$some-&someDbTask();
现在,让我们来想像一下,我们必须在组件中实现两个方法,首先需要创建一个新的数据库连接,第二个总是获得一个共享连接:
class Registry
protected static $_
* Creates a connection
protected static function _createConnection()
return new Connection(array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "invo"
* Creates a connection only once and returns it
public static function getSharedConnection()
if (self::$_connection===null){
$connection = self::_createConnection();
self::$_connection = $
return self::$_
* Always returns a new connection
public static function getNewConnection()
return self::_createConnection();
class SomeComponent
protected $_
* Sets the connection externally
public function setConnection($connection){
$this-&_connection = $
* This method always needs the shared connection
public function someDbTask()
$connection = $this-&_
* This method always needs a new connection
public function someOtherDbTask($connection)
$some = new SomeComponent();
//This injects the shared connection
$some-&setConnection(Registry::getSharedConnection());
$some-&someDbTask();
//Here, we always pass a new connection as parameter
$some-&someOtherDbTask(Registry::getConnection());
到此为止,我们已经看到了如何使用依赖注入解决我们的问题。不是在代码内部创建依赖关系,而是让其作为一个参数传递,这使得我们的程序更容易维护,降低程序代码的耦合度,实现一种松耦合。但是从长远来看,这种形式的依赖注入也有一些缺点。
例如,如果组件中有较多的依赖关系,我们需要创建多个setter方法传递,或创建构造函数进行传递。另外,每次使用组件时,都需要创建依赖组件,使代码维护不太易,我们编写的代码可能像这样:
//Create the dependencies or retrieve them from the registry
$connection = new Connection();
$session = new Session();
$fileSystem = new FileSystem();
$filter = new Filter();
$selector = new Selector();
//Pass them as constructor parameters
$some = new SomeComponent($connection, $session, $fileSystem, $filter, $selector);
// ... or using setters
$some-&setConnection($connection);
$some-&setSession($session);
$some-&setFileSystem($fileSystem);
$some-&setFilter($filter);
$some-&setSelector($selector);
我想,我们不得不在应用程序的许多地方创建这个对象。如果你不需要依赖的组件后,我们又要去代码注入部分移除构造函数中的参数或者是setter方法。为了解决这个问题,我们再次返回去使用一个全局注册表来创建组件。但是,在创建对象之前,它增加了一个新的抽象层:
class SomeComponent
* Define a factory method to create SomeComponent instances injecting its dependencies
public static function factory()
$connection = new Connection();
$session = new Session();
$fileSystem = new FileSystem();
$filter = new Filter();
$selector = new Selector();
return new self($connection, $session, $fileSystem, $filter, $selector);
这一刻,我们好像回到了问题的开始,我们正在创建组件内部的依赖,我们每次都在修改以及找寻一种解决问题的办法,但这都不是很好的做法。
一种实用和优雅的来解决这些问题,是使用容器的依赖注入,像我们在前面看到的,容器作为全局注册表,使用容器的依赖注入做为一种桥梁来解决依赖可以使我们的代码耦合度更低,很好的降低了组件的复杂性:
class SomeComponent
protected $_
public function __construct($di)
$this-&_di = $
public function someDbTask()
// Get the connection service
// Always returns a new connection
$connection = $this-&_di-&get('db');
public function someOtherDbTask()
// Get a shared connection service,
// this will return the same connection everytime
$connection = $this-&_di-&getShared('db');
//This method also requires a input filtering service
$filter = $this-&_db-&get('filter');
$di = new Phalcon\DI();
//Register a "db" service in the container
$di-&set('db', function(){
return new Connection(array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "invo"
//Register a "filter" service in the container
$di-&set('filter', function(){
return new Filter();
//Register a "session" service in the container
$di-&set('session', function(){
return new Session();
//Pass the service container as unique parameter
$some = new SomeComponent($di);
$some-&someTask();
现在,该组件只有访问某种service的时候才需要它,如果它不需要,它甚至不初始化,以节约资源。该组件是高度解耦。他们的行为,或者说他们的任何其他方面都不会影响到组件本身。
=============分割线,下面的部分从phalcon框架本身说明了什么是容器=======
Phalcon\DI 是一个实现了服务的依赖注入功能的组件,它本身也是一个容器。
由于Phalcon高度解耦,Phalcon\DI 是框架用来集成其他组件的必不可少的部分,开发人员也可以使用这个组件依赖注入和管理应用程序中不同类文件的实例。
基本上,这个组件实现了&&模式。基于此,对象不再以构造函数接收参数或者使用setter的方式来实现注入,而是直接请求服务的依赖注入。这就大大降低了整体程序的复杂性,因为只有一个方法用以获得所需要的一个组件的依赖关系。
此外,这种模式增强了代码的可测试性,从而使它不容易出错。
在容器中注册服务
框架本身或开发人员都可以注册服务。当一个组件A要求调用组件B(或它的类的一个实例),可以从容器中请求调用组件B,而不是创建组件B的一个实例。
这种工作方式为我们提供了许多优点:
我们可以更换一个组件,从他们本身或者第三方轻松创建。
在组件发布之前,我们可以充分的控制对象的初始化,并对对象进行各种设置。
我们可以使用统一的方式从组件得到一个结构化的全局实例
服务可以通过以下几种方式注入到容器:
//Create the Dependency Injector Container
$di = new Phalcon\DI();
//By its class name
$di-&set("request", 'Phalcon\Http\Request');
//Using an anonymous function, the instance will lazy loaded
$di-&set("request", function(){
return new Phalcon\Http\Request();
//Registering directly an instance
$di-&set("request", new Phalcon\Http\Request());
//Using an array definition
$di-&set("request", array(
"className" =& 'Phalcon\Http\Request'
在上面的例子中,当向框架请求访问一个请求数据时,它将首先确定容器中是否存在这个”reqeust”名称的服务。
容器会反回一个请求数据的实例,开发人员最终得到他们想要的组件。
在上面示例中的每一种方法都有优缺点,具体使用哪一种,由开发过程中的特定场景来决定的。
用一个字符串来设定一个服务非常简单,但缺少灵活性。设置服务时,使用数组则提供了更多的灵活性,而且可以使用较复杂的代码。lambda函数是两者之间一个很好的平衡,但也可能导致更多的维护管理成本。
Phalcon\DI 提供服务的延迟加载。除非开发人员在注入服务的时候直接实例化一个对象,然后存存储到容器中。在容器中,通过数组,字符串等方式存储的服务都将被延迟加载,即只有在请求对象的时候才被初始化。
//Register a service "db" with a class name and its parameters
$di-&set("db", array(
"className" =& "Phalcon\Db\Adapter\Pdo\Mysql",
"parameters" =& array(
"parameter" =& array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "blog"
//Using an anonymous function
$di-&set("db", function(){
return new Phalcon\Db\Adapter\Pdo\Mysql(array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret",
"dbname" =& "blog"
以上这两种服务的注册方式产生相同的结果。然后,通过数组定义的,在后面需要的时候,你可以修改服务参数:
$di-&setParameter("db", 0, array(
"host" =& "localhost",
"username" =& "root",
"password" =& "secret"
从容器中获得服务的最简单方式就是使用”get”方法,它将从容器中返回一个新的实例:
&?php $request = $di-&get("request");
或者通过下面这种魔术方法的形式调用:
&?php $request = $di-&getRequest();
Phalcon\DI 同时允许服务重用,为了得到一个已经实例化过的服务,可以使用 getShared() 方法的形式来获得服务。
具体的 Phalcon\Http\Request 请求示例:
&?php $request = $di-&getShared("request");
参数还可以在请求的时候通过将一个数组参数传递给构造函数的方式:
&?php $component = $di-&get("MyComponent", array("some-parameter", "other"))
到这里差不多就说清楚了,其实楼主一开始无法想明白传统的工厂方法和依赖注入的区别到底在哪里,看了这篇文章以后豁然开朗,这是一种视角的转变,怎么说呢,又进步了一点吧。
& 著作权归作者所有
人打赏支持
码字总数 89585
后端工程师
去年在做Magento二开的时候,看到过很多组件就是这样形式的,当时可能不理解这是什么东西,经楼主这么一说,倒是明白了。new一个对象之后,要set很多东西。还有看到楼主例子中有一个new self(),应该还有一个new static(),这些都是5.3之后新加的特性,我也是看了laravel框架之后,才发现php还可以写出如此优雅的代码……
评论删除后,数据将无法恢复
想理解php依赖注入和控制反转两个概念,就必须搞清楚如下的问题: DI——Dependency Injection 依赖注入 IoC——Inversion of Control 控制反转 1、参与者都有谁?  IOC/DI容器就是一个全局...
最近一段时间在研究laravel的底层源码,既然这样那得从开头说起,于是去了laravel学院看看别人写的关于laravel的核心分析,链接如下: Laravel 服务容器实例教程 —— 深入理解控制反转(IoC...
IOC 和DI,这两个在Java中指的是控制反转和依赖注入;熟悉struts2 , spring的人对于这两个名词都很不陌生; 最近在学习的过程中,又不断的碰到这两个词;而网络上,更多的是对依赖注入的方式...
最近研究php的框架,知道了依赖注入容器。但是一直弄不清楚怎么回事。依赖注入和控制反转,看代码我的理解是主要用来解耦的,简单说是把关联对象的接口或父抽象类在外部创立,以参数形式注入到...
manbudezhu
只为成功找方法,不为失败找借口! 谈谈对Spring IOC的理解   学习过Spring框架的人一定都会听过Spring的IoC(控制反转) 、DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC 、D...
没有更多内容
加载失败,请刷新页面
var map = {}; // Map map = new HashMap(); map[key] = // map.put(key, value); var value = map[key]; // Object value = map.get(key); var has = // boolean has = ......
SuperDabai
public static void main(String[] args) {String hex = "0xdbf3accc00";BigInteger amount = new BigInteger(hex.substring(2), 16);System.out.println(amount);......
Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @真Skr小机灵鬼儿:8.13分享Jocelyn Pook/Russian Red的单曲《Loving Strangers》 《Loving Strangers》- Jocelyn Pook/Russian Red 手机党少...
转载 TypeScript基础入门 - 函数 - 剩余参数 项目实践仓库 https://github.com/durban89/typescript_demo.gittag: 1.2.1 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都能...
1. 拉普拉斯算子 原理:是一种基于图像导数运算的高通线性滤波器。它通过二阶导数来度量图像函数的曲率。 拉普拉斯算子是最简单的各向同性微分算子,它具有旋转不变性。一个二维图像函数的拉...
没有更多内容
加载失败,请刷新页面
文章删除后无法恢复,确定取消删除此文章吗?
亲,自荐的博客将通过私信方式通知管理员,优秀的博客文章审核通过后将在博客推荐列表中显示
确定推荐此文章吗?
确定推荐此博主吗?
聚合全网技术文章,根据你的阅读喜好进行个性推荐
指定官方社区
深圳市奥思网络科技有限公司版权所有PHP实现搜索地理位置及计算两点地理位置间距离的实例
转载 &更新时间:日 14:45:43 & 作者:傲雪星枫
这篇文章主要介绍了PHP实现搜索地理位置及计算两点地理位置间距离的实例,地理位置搜寻的例子中使用到了MongoDB数据库,需要的朋友可以参考下
地理位置搜寻
LBS,存储每个地点的经纬度坐标,搜寻附近的地点,建立地理位置索引可提高查询效率。
mongodb地理位置索引,2d和2dsphere,对应平面和球面。
1.创建lbs集合存放地点坐标
db.lbs.insert(
type: "Point",
coordinates: [113..156206]
name: "广州东站"
db.lbs.insert(
type: "Point",
coordinates: [113..147234]
name: "林和西"
db.lbs.insert(
type: "Point",
coordinates: [113..165376]
name: "天平架"
2.创建地理位置索引
db.lbs.ensureIndex(
loc: "2dsphere"
3.查询附近的坐标
当前位置为:时代广场,
113..146436
搜寻附近一公里内的点,由近到远排序
db.lbs.find(
$geometry:{
type: "Point",
coordinates: [113..146436]
$maxDistance: 1000
搜寻结果:
{ "_id" : ObjectId("556aac2add8928fa"), "loc" : { "type" : "Point", "coordinates" : [ 113..147234 ] }, "name" : "林和西" }&
php代码如下:
// 连接mongodb
function conn($dbhost, $dbname, $dbuser, $dbpasswd){
$server = 'mongodb://'.$dbuser.':'.$dbpasswd.'@'.$dbhost.'/'.$
$conn = new MongoClient($server);
$db = $conn-&selectDB($dbname);
} catch (MongoException $e){
throw new ErrorException('Unable to connect to db server. Error:' . $e-&getMessage(), 31);
// 插入坐标到mongodb
function add($dbconn, $tablename, $longitude, $latitude, $name){
$index = array('loc'=&'2dsphere');
$data = array(
'loc' =& array(
'type' =& 'Point',
'coordinates' =& array(doubleval($longitude), doubleval($latitude))
'name' =& $name
$coll = $dbconn-&selectCollection($tablename);
$coll-&ensureIndex($index);
$result = $coll-&insert($data, array('w' =& true));
return (isset($result['ok']) && !empty($result['ok'])) ? true :
// 搜寻附近的坐标
function query($dbconn, $tablename, $longitude, $latitude, $maxdistance, $limit=10){
$param = array(
'loc' =& array(
'$nearSphere' =& array(
'$geometry' =& array(
'type' =& 'Point',
'coordinates' =& array(doubleval($longitude), doubleval($latitude)),
'$maxDistance' =& $maxdistance*1000
$coll = $dbconn-&selectCollection($tablename);
$cursor = $coll-&find($param);
$cursor = $cursor-&limit($limit);
$result = array();
foreach($cursor as $v){
$result[] = $v;
$db = conn('localhost','lbs','root','123456');
// 随机插入100条坐标纪录
for($i=0; $i&100; $i++){
$longitude = '113.3'.mt_rand(1);
$latitude = '23.15'.mt_rand();
$name = 'name'.mt_rand();
add($db, 'lbs', $longitude, $latitude, $name);
// 搜寻一公里内的点
$longitude = 113.323568;
$latitude = 23.146436;
$maxdistance = 1;
$result = query($db, 'lbs', $longitude, $latitude, $maxdistance);
print_r($result);
演示php代码,首先需要在mongodb的lbs中创建用户和执行auth。方法如下:
db.createUser(
"user":"root",
"pwd":"123456",
"roles":[]
"user":"root",
"pwd":"123456"
计算两点地理坐标的距离
功能:根据圆周率和地球半径系数与两点坐标的经纬度,计算两点之间的球面距离。
获取两点坐标距离:
* 计算两点地理坐标之间的距离
* @param Decimal $longitude1 起点经度
* @param Decimal $latitude1 起点纬度
* @param Decimal $longitude2 终点经度
* @param Decimal $latitude2 终点纬度
* @param Int
单位 1:米 2:公里
* @param Int
精度 保留小数位数
* @return Decimal
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=2, $decimal=2){
$EARTH_RADIUS = ; // 地球半径系数
$PI = 3.1415926;
$radLat1 = $latitude1 * $PI / 180.0;
$radLat2 = $latitude2 * $PI / 180.0;
$radLng1 = $longitude1 * $PI / 180.0;
$radLng2 = $longitude2 * $PI /180.0;
$a = $radLat1 - $radLat2;
$b = $radLng1 - $radLng2;
$distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
$distance = $distance * $EARTH_RADIUS * 1000;
if($unit==2){
$distance = $distance / 1000;
return round($distance, $decimal);
// 起点坐标
$longitude1 = 113.330405;
$latitude1 = 23.147255;
// 终点坐标
$longitude2 = 113.314271;
$latitude2 = 23.1323;
$distance = getDistance($longitude1, $latitude1, $longitude2, $latitude2, 1);
echo $distance.'m'; // 2342.38m
$distance = getDistance($longitude1, $latitude1, $longitude2, $latitude2, 2);
echo $distance.'km'; // 2.34km
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
我装了这个官方的php库
但是看了半天文档也不知道如何聚合查询
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
$json = '{
"first_judge_time": {
"terms": {
"field": "first_judge_time",
"order": [
"_term": "desc"
"size": 12
"aggs": {}
$params = [
'index' =& 'xx_index',
'type' =& 'doc',
'body' =& $json
$res = $this-&esClient-&search($params);
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
这个就是啊
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。入门级:简单的一款PHP+MYSQL增删改查程序源码(含分页)
PHP语言基础
开发语言:PHP
实例大小:9.55KB
下载次数:
浏览次数:
发布时间:
实例类别:PHP语言基础
发 布 人:
所需积分:1
&相关标签:
同类人气实例
实例下载地址
入门级:简单的一款PHP+MYSQL增删改查程序源码(含分页)
不能下载?内容有错? 点击这里报错
好例子网口号:伸出你的我的手 & 分享!
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
Copyright &
好例子网(https://www.haolizi.net).All Rights Reserved备案编号:冀ICP备号 石公备号(10)thinkphp通过经纬度获取周边信息的例子
thinkphp实现附近范围的查询,如附近的人和附近团购之类。首先,要定位用户的经纬度。客户端定位的方法可以使用地图api或者用5浏览器定位(比较不稳定而且不会太精确)。然后,将当前经纬度,和需要搜索的距离范围,一个经纬度范围,这个范围就是“附近”。要有数据库的支持,效果图:
参数说明:
默认是500米(0.5Km)
function returnSquarePoint($lng, $lat,$distance = 0.5)
2 * asin(sin($distance / (2 * 6371)) / cos(deg2rad($lat)));
$dlng = rad2deg($dlng);
$dlat = $distance/6371;
$dlat = rad2deg($dlat);
return array(
'left-top'=&array('lat'=&$lat + $dlat,'lng'=&$lng-$dlng),
'right-top'=&array('lat'=&$lat + $dlat, 'lng'=&$lng + $dlng),
'left-bottom'=&array('lat'=&$lat - $dlat, 'lng'=&$lng - $dlng),
'right-bottom'=&array('lat'=&$lat - $dlat, 'lng'=&$lng + $dlng)
在文件中调用并组成条件:
$array = $this-&returnSquarePoint($latitude, $lonude, 5);
生成Thinkphp查询条件
$map = array(
"latitude" =& array(array('EGT',$array['right-bottom']['lat']),array('ELT',$array['left-top']['lat']),'or'),
"longitude" =& array(array('EGT',$array['left-top']['lng']),array('ELT',$array['right-bottom']['lng']),'or'),
"status" =& array("eq",1),
查询结果:

我要回帖

更多关于 php离我最近 的文章

 

随机推荐