Doctrine 1.2中用户定义的例程?

时间:2011-06-10 02:41:20

标签: php mysql doctrine user-defined routines

我必须为我的MySQL数据库编写一个用户定义的例程(计算距离函数)。

  1. 是否可以在yaml模式文件中定义它?
  2. 在终端mysql-client中定义例程之后一切正常,直到'doctrine build-all-reload' - 函数被删除,这是可以理解的;

    1. 如何附加每次运行'build-all-reload'时执行的sql脚本?
    2. 抱歉我的英文。 汤姆

2 个答案:

答案 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以外的地方做这件事:

  1. 连接MySQL
  2. 发送SQL以创建您的功能
  3. 断开
  4. P.S。另一种方法是在PHP中编写距离计算函数作为学说行为(扩展Doctrine_Record_Listener);作为奖励,您将获得数据库可移植性。但它将代码绑定到Doctrine,因此其他应用程序无法以mysql例程的方式使用该函数。