Пользовательская процедура в Doctrine 1.2? - PullRequest
3 голосов
/ 10 июня 2011

Мне нужно написать пользовательскую подпрограмму для моей базы данных MySQL (функция вычисления расстояния).

  1. Можно ли определить ее в файле схемы yaml?

После определения подпрограммы в терминале mysql-client все в порядке, пока 'doctrine build-all-reload' - функция не удалена, что понятно;

  1. Как я могу прикрепить скрипт sql, который будет выполнятьсякаждый раз, когда я запускаю 'build-all-reload'?

Извините за мой английский.Том

Ответы [ 2 ]

1 голос
/ 20 июля 2011

Я нашел решение (в некотором роде похожее на ваше), добавив следующие строки в мой файл 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.

После этого я могу использовать функцию DIST в Doctrine Queries, и она работает в несколько раз быстрее, чем стандартная реализация встроенных функций, и намного короче.

$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));

Спасибо за вашу помощь.

0 голосов
/ 19 июля 2011

Я думаю это можно сделать с помощью доктрины.

После моего собственного сообщения в блоге 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. Disconnect

P.S. Другой подход состоит в том, чтобы написать свою функцию вычисления расстояния в PHP как поведение доктрины (extension Doctrine_Record_Listener); в качестве бонуса вы получаете переносимость базы данных. Но он связывает код с Doctrine, поэтому другие приложения не могут использовать функцию так, как они могут использовать подпрограмму mysql.

...