2009-08-04 14 views
2

Si je veux faire quelque chose comme ceci (notez la expires ligne):Comment envoyer un paramètre littéral via Doctrine à la base de données?

$duration=24; //in hours 

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

Comment puis-je obtenir Doctrine de pas citer avant de l'envoyer à PostGreSQL? Je sais que je pourrais le faire en PHP, mais je voudrais savoir pour référence future.

Répondre

1

Vous pouvez jeter un oeil à Using Expression Values

L'exemple ressemble à ceci (citant le doc):

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

et génère cette requête SQL:

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

Je suppose que cela ferait, dans votre cas?
(Je n'ai pas un projet a permis Doctrine ici, donc ne peut pas tester pour vous)


En sidenote: Je n'ai pas un serveur PostGreSQL pour tester sur; mais ce que vous proposez ne fonctionne pas sur MySQL: il semble que vous devez utiliser « now() + interval 2 hour », et non « now() + interval 2 hours » - encore, je ne sais pas PG


EDIT après le commentaire

Ergh, vous avez raison, ce n'est pas une solution correcte; il ne fonctionne pas :-(

Eh bien ... Question intéressante, donc je creusé un peu plus, et est allé à code source de la doctrine;

Je pense que je pourrais avoir trouver quelque chose d'intéressant Si. vous regardez la source de Doctrine_Query_Where::parseValue source, vous remarquerez cette partie de code:

// 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 

J'ai pas essayé absolutly, mais cela pourrait être intéressant ...

peut-être que vous pourriez faire quelque chose comme ça :

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

Si vous essayez cela, je suis très intéressé de savoir si cela fonctionnerait!
peut être utile, un jour ou l'autre ;-)

BTW, il semble qu'il est utilisé dans Doctrine_Search aussi; regardant celui-ci, peut-être que ça va marcher sans les parenthèses, comme ceci:

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

Eh bien ... je l'espère, cette fois-ci, il aide ...Parce que je ne vois pas beaucoup d'autre moyen de faire ce que vous essayez d'obtenir (et Google ne me permet pas non plus ^^)


EDIT après la deuxième (troisième, si le mien comptage) commentaire.
j'obtenir ce travail ... sinon je ne vais pas bien dormir ^^

Eh bien, je pourrais avoir trouvé un moyen (et, cette fois, je l'ai testé ^^); pas vraiment aussi grand que l'on voudrait, mais, pour des mises à jour de toute façon, il semble fonctionner ...

Disons que j'ai une table créé de cette façon:

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; 

La classe modèle correspondant ressemble ceci:
Probablement pas parfait: il est un test de classe que j'ai écrit pour quelque chose d'autre, que je suis muté pour adapter celui-ci ^^

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, 
      )); 
    } 
} 

Je vais insérer deux lignes dans cette table :

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

Ce qui me reçoit ces données de SQL:
BTW: Je n'ai pas un serveur p, donc je vais tester tout avec MySQL - devrait travailler pg aussi, encore ...

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) 

Ainsi, deux lignes, avec des dates il y a longtemps dans le passé.


Maintenant, pour être sûr, nous allons simplement chercher la ligne # 1:

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

Je reçois ce genre de sortie:

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) 


Et maintenant, la partie intéressante: mettons à jour cette ligne, en utilisant une expression comme celle que vous avez fourni pour définir la valeur 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 que je reçois en tant que sortie est celui-ci:

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

qui ressemblent un peu comme ce que vous voulez, si je ne me trompe pas ;-)


Et, juste pour être sûr, nous allons à notre ligne d'extraction une fois encore:

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

Et j'obtenir ce résultat:Compte tenu de la date et l'heure, il semble que cela a fonctionné - hourra!

Et, pour être sûr, nous allons interroger les données directement à partir du DB:

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) 

Et ... Yeeeepe!


Eh bien, maintenant, les moins bonnes parties: pour pouvoir utiliser cette syntaxe, je devais créer la requête « à la main », d'utiliser la méthode set(), au lieu de le faire « bien » avec le classe modèle et la méthode save() :-(

Il est maintenant à vous de vous voir qui pourrait être intégré dans votre classe de modèle ... Amusez-vous avec qui ;-)

et si vous trouvez un moyen, un jour, pour utiliser des expressions comme celle-ci dans d'autres parties de la requête, ou pour le faire d'une manière plus propre, j'apprécierais vraiment si vous pouviez poster un commentaire pour me le faire savoir ;-)


Et, cela, le temps, je l'espère sincèrement que je trouve le chemin ^^

+0

Il ressemble à Doctrine_Expression est à l'aide des fonctions SQL Doctrine peut convertir en expressions portables. Cela ne fonctionne pas dans ce cas. – ryeguy

+0

Ergh :-(J'ai édité ma réponse avec une autre idée ... Mais, si celle-ci ne fonctionne pas non plus, je crains qu'il n'y ait pas beaucoup d'espoir :-( –

+0

Merci de creuser, mais ça ressemble à Doctrine ne cherche que "SQL:" si c'est dans une clause where.Il ne semble pas se soucier si je le fais lors de la définition d'une valeur. +1 pour l'effort si, je l'apprécie – ryeguy

Questions connexes