Как отправить литеральный параметр через Doctrine в БД? - PullRequest
2 голосов
/ 04 августа 2009

Если я хочу сделать что-то подобное (обратите внимание на строку с истекшим сроком действия):

$duration=24; //in hours

$reset=new PasswordReset();
$reset->code=md5(uniqid());
$reset->expires="now() + interval $duration hours";
$reset->User=$user;
$reset->save();

Как я могу заставить Doctrine НЕ цитировать его перед отправкой в ​​postgresql? Я знаю, что мог бы сделать это на PHP, но я хотел бы знать это для дальнейшего использования.

1 Ответ

1 голос
/ 04 августа 2009

Возможно, вы захотите взглянуть на Использование значений выражений

Данный пример выглядит следующим образом (цитирование документа) :

$user = new User();
$user->username = 'jwage';
$user->updated_at = new Doctrine_Expression('NOW()');
$user->save();

И генерирует этот SQL-запрос:

INSERT INTO user (username, updated_at_) VALUES ('jwage', NOW())

Полагаю, это подойдет, в вашем случае?
(у меня нет проекта с поддержкой Doctrine, поэтому я не могу проверить его для вас)


Как примечание: у меня нет сервера PostGreSQL для тестирования; но то, что вы предлагаете, не работает на MySQL: похоже, вы должны использовать «now() + interval 2 hour», а не «now() + interval 2 hours» - тем не менее, я не знаю о PG


РЕДАКТИРОВАТЬ после комментария

Э-э, вы правы, это не правильное решение; это не работает : - (

Ну ... Интересный вопрос, поэтому я выкопал еще немного и пошел к исходному коду Doctrine; Я думаю, что мог найти что-то интересное.

Если вы посмотрите на источник Doctrine_Query_Where::parseValue, вы увидите эту часть кода:

// If custom sql for custom subquery
// You can specify SQL: followed by any valid sql expression
// FROM User u WHERE u.id = SQL:(select id from user where id = 1)
} elseif (substr($trimmed, 0, 4) == 'SQL:') {
    $rightExpr = '(' . substr($trimmed, 4) . ')';
// simple in expression found

Я абсолютно не пробовал, но это может быть интересно ...

Может быть, вы могли бы сделать что-то вроде этого:

$reset->expires="SQL:(now() + interval $duration hours)";

Если вы попробуете это, мне очень интересно знать, сработает ли это!
Может быть полезно, один день или другой; -)

Кстати, похоже, он также используется в Doctrine_Search; Глядя на этот, может быть, он будет работать без скобок, например:

$reset->expires="SQL:now() + interval $duration hours";

Ну ... Надеюсь, на этот раз это поможет ... Потому что я не вижу другого способа сделать то, что вы пытаетесь получить (и Google тоже мне не помогает ^^ )


РЕДАКТИРОВАТЬ после второго (третьего, если считать мой) комментария.
Я получу это работает ... иначе я не буду хорошо спать ^^

Ну, я мог бы найти способ (и на этот раз я его проверил ^^) ; на самом деле не так хорошо, как хотелось бы, но, в любом случае, похоже, что обновления работают ...

Допустим, у меня есть таблица, созданная таким образом:

CREATE TABLE  `test1`.`test` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(32) NOT NULL,
  `value` varchar(128) NOT NULL,
  `date_field` datetime NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Соответствующий класс модели выглядит так:
Вероятно, не идеально: это тестовый класс, который я написал для чего-то другого, который я мутировал, чтобы соответствовать этому ^^

class Test extends Doctrine_Record
{
    public function setTableDefinition()
    {
        $this->setTableName('test');
        $this->hasColumn('id', 'integer', 4, array(
             'type' => 'integer',
             'length' => 4,
             'unsigned' => 0,
             'primary' => true,
             'autoincrement' => true,
             ));
        $this->hasColumn('name', 'string', 32, array(
             'type' => 'string',
             'length' => 32,
             'fixed' => false,
             'notnull' => true,
             ));
        $this->hasColumn('value', 'string', 128, array(
             'type' => 'string',
             'length' => 128,
             'fixed' => false,
             'primary' => false,
             'notnull' => true,
             'autoincrement' => false,
             ));
        $this->hasColumn('date_field', 'integer', 4, array(
             'type' => 'timestamp',
             'notnull' => true,
             ));
    }
}

Я вставлю две строки в эту таблицу:

$test = new Test();
$test->name = 'Test 1';
$test->value = 'My Value 1';
$test->date_field = "2009-01-30 08:30:00";
$test->save();

$test = new Test();
$test->name = 'Test 2';
$test->value = 'My Value 2';
$test->date_field = "2009-02-05 08:30:00";
$test->save();

Который получает эти данные из SQL:
Кстати: у меня нет pg-сервера, поэтому я все протестирую с MySQL - все равно должно работать и на pg ...

mysql> select * from test;
+----+--------+------------+---------------------+
| id | name   | value      | date_field          |
+----+--------+------------+---------------------+
|  1 | Test 1 | My Value 1 | 2009-01-30 08:30:00 |
|  2 | Test 2 | My Value 2 | 2009-02-05 08:30:00 |
+----+--------+------------+---------------------+
2 rows in set (0.00 sec)

Итак, две строки с датами в прошлом.


Теперь, чтобы быть уверенным, давайте просто возьмем строку # 1:

$testBefore = Doctrine::getTable('Test')->find(1);
var_dump($testBefore->toArray());

Я получаю такой вывод:

array
  'id' => string '1' (length=1)
  'name' => string 'Test 1' (length=6)
  'value' => string 'My Value 1' (length=10)
  'date_field' => string '2009-01-30 08:30:00' (length=19)


А теперь интересная часть: давайте обновим эту строку, используя выражение, подобное тому, которое вы указали , чтобы установить значение date_field:

$query = new Doctrine_Query();

$query->update('test')
    ->set('date_field', 'NOW() - interval 2 hour')
    ->where('id = ?', 1)
    ->execute();

var_dump($query->getSql());

SQL, который я получаю в качестве вывода, это:

string 'UPDATE test SET date_field = NOW() - interval 2 hour WHERE id = ?' (length=65)

Какой вид, что вы хотите, если я не ошибаюсь; -)


И, чтобы быть уверенным, давайте еще раз приведем нашу строку:

$testAfter = Doctrine::getTable('Test')->find(1);
var_dump($testAfter->toArray());

И я получаю такой результат:

array
  'id' => string '1' (length=1)
  'name' => string 'Test 1' (length=6)
  'value' => string 'My Value 1' (length=10)
  'date_field' => string '2009-08-04 21:26:30' (length=19)

Учитывая дату и время, кажется, это сработало - ура!

И, конечно, давайте запросим данные непосредственно из БД:

mysql> select * from test;
+----+--------+------------+---------------------+
| id | name   | value      | date_field          |
+----+--------+------------+---------------------+
|  1 | Test 1 | My Value 1 | 2009-08-04 21:26:30 |
|  2 | Test 2 | My Value 2 | 2009-02-05 08:30:00 |
+----+--------+------------+---------------------+
2 rows in set (0.00 sec)

И ... Даааа!


Что ж, теперь не очень хорошие части: чтобы использовать этот синтаксис, мне нужно было создать запрос «вручную», использовать метод set(), вместо того, чтобы «делать его красиво» с классом модели и save() метод: - (

Теперь вам предстоит увидеть вас, которых можно интегрировать в ваш модельный класс ... Веселитесь с этим; -)

И если вы когда-нибудь найдете способ использовать выражения, подобные этому, в других частях запроса или сделать это более понятным способом, я был бы очень признателен, если бы вы могли опубликовать комментарий, чтобы сообщить мне ; -)


И в этот раз я искренне надеюсь, что нашел способ ^^

...