Определяемая пользователем процедура в Doctrine 1.2?

#php #mysql #doctrine #user-defined #routines

#php #mysql #доктрина #определяемый пользователем #процедуры #определяемая пользователем #подпрограммы

Вопрос:

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

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

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

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

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

Ответ №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.

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

 $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. Вы просто добавили execute ($ q) в конце doctrine.php ? Проблема в том, что если вы используете свой doctrine.php для любой команды, отличной от «build-all-reload». Но вы, конечно, можете создать выделенный doctrine.php для простой сборки-all-reload, и в этом случае мне нравится ваше решение 🙂

2. Да, эти строки были добавлены в конце doctrine.php файл.

Ответ №2:

Я думаю, что это можно сделать с помощью поведения Doctrine.

Следуя моему собственному сообщению в блоге http://darrendev.blogspot.com/2010/03/creating-doctrine-custom-behaviour-part.html, но используя setUp() вместо setTableDefinition(), вы создаете файл с этим кодом:

 class DarrenTestable extends Doctrine_Template{
    public function setUp(){
        ...
    }
}
  

The … здесь вы можете влиять на создание таблицы. Вы добавляете это поведение в файл yaml с:

 ActsAs:
    DarrenTestable
  

Может быть, есть аккуратный doctrine-способ сделать то, что вам нужно в части «…», но, немного покопавшись в исходном коде, я не уверен, и поэтому, поскольку это делается только один раз за время существования вашего приложения, я бы лично сделал все это вне Doctrine:

  1. Подключитесь к MySQL
  2. Отправьте SQL для создания вашей функции
  3. Отключить

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