我必须为我的MySQL数据库编写一个用户定义的例程(计算距离函数)。
在终端mysql-client中定义例程之后一切正常,直到'doctrine build-all-reload' - 函数被删除,这是可以理解的;
抱歉我的英文。 汤姆
答案 0 :(得分:1)
我通过在doctrine.php文件中添加以下行找到了一个解决方案(在某种程度上类似于你的解决方案):
$q = file_get_contents('../configs/sql/routines.sql');
$conn = Doctrine_Manager::connection();
$conn->execute($q);
现在,每次执行./doctrine build-all-reload都会执行以下脚本:
DROP FUNCTION IF EXISTS DIST;
CREATE FUNCTION DIST (fi11 DOUBLE, ksi11 DOUBLE, fi22 DOUBLE, ksi22 DOUBLE)
RETURNS DOUBLE
DETERMINISTIC
BEGIN
DECLARE d DOUBLE;
DECLARE fi1 DOUBLE;
DECLARE fi2 DOUBLE;
DECLARE ksi1 DOUBLE;
DECLARE ksi2 DOUBLE;
SET fi1 = PI()*(fi11)/180;
SET fi2 = PI()*(fi22)/180;
SET ksi1 = PI()*(ksi11)/180;
SET ksi2 =PI()*(ksi22)/180;
SET d = ACOS((SIN(fi1)*SIN(fi2))+(COS(fi1)*COS(fi2)*COS((ksi1-ksi2))))*6371.0;
RETURN d;
END;
这个解决方案可能不优雅,但对我有用:) 我不打算从MySQL更改数据库。
之后我可以在Doctrine Queries中使用DIST函数,它比使用标准的内置函数实现快几倍,而且要短得多。
$q->where('DIST(a.lan, a.lon, b.lan, b.lon) < ?', array(2.0));
而不是
$q->where('ACOS((SIN(...)... ... wrrrr ;-P ))*6371.0 < ?', array(2.0));
感谢您的帮助。
答案 1 :(得分:0)
我认为这可以通过Doctrine行为完成。
按照我自己的博文http://darrendev.blogspot.com/2010/03/creating-doctrine-custom-behaviour-part.html,但使用setUp()而不是setTableDefinition(),您可以使用以下代码创建一个文件:
class DarrenTestable extends Doctrine_Template{
public function setUp(){
...
}
}
...是您可以影响表创建的地方。您使用以下命令在yaml文件中附加此行为:
ActsAs:
DarrenTestable
在“...”部分可能有一个简洁的学说方式来做你需要的东西,但是在找到源代码后我有点不确定,因为这只是在你的申请的有效期,我个人在Doctrine以外的地方做这件事:
P.S。另一种方法是在PHP中编写距离计算函数作为学说行为(扩展Doctrine_Record_Listener);作为奖励,您将获得数据库可移植性。但它将代码绑定到Doctrine,因此其他应用程序无法以mysql例程的方式使用该函数。