2017-06-08 4 views
2

Récemment, j'ai commencé à coder avec Symfony et Propel 2.x, et je suis tombé sur un problème avec la clause WHERE IN.Propel WHERE dans la clause et la fonction MySQL

Je veux obtenir des clients qui est né en 1993 et ​​1988.

J'ai écrit ce fragment de code Propel Requête:

$query = ClientQuery::create() 
    ->where('YEAR(Client.Birthdate) IN ?', [1993, 1988]) 
    ->find(); 

... et l'ORM cartographié ces entiers comme objet DateTime , alors regardez la requête finale comme:

SELECT clients.id, clients.user_id, clients.first_name, clients.last_name, clients.birthdate, clients.document_id, clients.street, clients.postal_code, clients.city, clients.country 
FROM clients 
WHERE YEAR(clients.birthdate) IN ('1970-01-01','1970-01-01') 

y at-il moyen d'utiliser Propel pour construire la requête comme ci-dessous, sans utiliser RAW requête SQL?

SELECT clients.id, clients.user_id, clients.first_name, clients.last_name, clients.birthdate, clients.document_id, clients.street, clients.postal_code, clients.city, clients.country 
    FROM clients 
    WHERE YEAR(clients.birthdate) IN (1993, 1988) 

J'ai essayé d'ajouter YEAR(clients.birthdate) SELECT avec alias pour, mais aussi je ne peux pas attendre la requête.

+0

Quel type de colonne est birthdate dans la table des clients? Pouvez-vous montrer certaines données stockées int? – m1n0

+0

@ m1n0 cette colonne est de type DATE. Propel pense que je compare les DATE au lieu de INT, donc il jette mes valeurs à l'objet DateTime. – lepsus

Répondre

2
Vous pouvez essayer de spécifier le type de liaison: -> où ('AN (Client.Birthdate) IN?', [1993, 1988], PDO :: PARAM_INT)

Edit:

Oui, vous avez raison. Cette solution entraînera une exception PropelException, car Propel/PDO ne peut pas lier un tableau à int.

Sinon, vous pouvez utiliser des conditions:

$years = [1993, 1988]; 
    // Get the key of the first element 
    $firstKey = key($years); 
    $query = ClientQuery::create(); 
    foreach ($years as $key => $year) { 
     // Add _or() call for all elements except the first one 
     if ($key !== $firstKey) { 
      $query->_or(); 
     } 
     // Add where condition and binding type 
     $query->where('YEAR(Client.Birthdate) = ?', $year, PDO::PARAM_INT); 
    } 
    $query = $query->find(); 

Je conviens que cette solution ne semble pas très agréable, mais ça fonctionne.

+0

Malheureusement, cela ne fonctionne pas. Got PropelException: ' Impossible d'exécuter l'instruction SELECT [SELECT clients.id, clients.user_id, clients.first_name, clients.last_name, clients.birthdate, clients.document_id, clients.street, clients.postal_code, clients.city, clients .country FROM clients O WH ANNÉE (clients.date de naissance) IN: p1] ' – lepsus

+0

Cette solution ne peut tirer parti d'aucun index sur le champ birthdate. – Ben

+0

SQL brut dans une requête ORM ... Wouldn ' t il serait préférable d'utiliser SQL brut sans Propel ou de comprendre comment faire cette requête dans Propel sans SQL brut? – Ben

0

Ouais, on dirait que vous allez devoir utiliser 4 conditions:

  • date de naissance> = '1993-01-01' et date de naissance < '1994-01-01'
  • OU date de naissance > = '1988-01-01' et date de naissance < '1989-01-01'

Vous pouvez le faire en utilisant les méthodes condition() et combine() de la classe ClientQuery.

http://propelorm.org/Propel/reference/model-criteria.html#combining-several-conditions

Je vous conseille de ne pas utiliser la méthode _or().

Aussi, je parierais que l'utilisation d'horodatages unix rendrait la logique de votre application plus facile à construire.