#php #mysql #doctrine #user-defined #routines
#php #mysql #доктрина #определяемый пользователем #процедуры #определяемая пользователем #подпрограммы
Вопрос:
Я должен написать определяемую пользователем процедуру для моей базы данных MySQL (функция вычисления расстояния).
- Возможно ли определить ее в файле схемы yaml?
После определения процедуры в терминале mysql-client все в порядке, пока функция ‘doctrine build-all-reload’ не будет удалена, что вполне понятно;
- Как я могу прикрепить 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:
- Подключитесь к MySQL
- Отправьте SQL для создания вашей функции
- Отключить
P.S. Другой подход заключается в написании вашей функции вычисления расстояния на PHP в качестве поведения doctrine (расширьте Doctrine_Record_Listener); в качестве бонуса вы получаете переносимость базы данных. Но это привязывает код к Doctrine, поэтому другие приложения не могут использовать функцию так, как они могут с помощью подпрограммы mysql.