2009-08-25 15 views
5

J'ai un grand ensemble de données (plus d'un milliard de lignes). Les données sont partitionnées dans la base de données par date. En tant que tel, mon outil de requête DOIT spécifier une clause SQL entre chaque requête, ou il devra analyser chaque partition .. et bien, il va expirer avant qu'il ne revienne jamais.Modèle CakePHP avec "Entre dates"

Alors .. ma question est, le champ dans la base de données des thats partitionné une date ..

En utilisant CakePHP, comment puis-je spécifier « entre » dates dans ma forme?

Je pensais faire "start_date" et "end_date" dans le formulaire lui-même, mais cela peut m'apporter deux une deuxième question ... comment puis-je valider cela dans un modèle qui est lié à une table?

Répondre

0

Vous pouvez écrire une méthode personnalisée dans votre modèle de recherche entre les dates:

function findByDateRange($start,$end){ 
    return $this->find('all',array('date >= '.$start,'data >= .'$end)); 
} 

En ce qui validation, vous pouvez utiliser le rappel beforeValidate() du modèle pour valider les deux dates. Plus d'infos sur ce here.

function beforeValidate(){ 
    if(Validation::date($this->data['Model']['start_date'])){ 
     return false; 
    } 
    if(Validation::date($this->data['Model']['end_date'])){ 
     return false; 
    } 
    return parent::beforeValidate(); 
} 

Est-ce que cela répond à votre question?

8

Si je vous suit correctement:

  • L'utilisateur doit spécifier dates de début/fin pour trouver des requêtes générées à partir d'un formulaire
  • Vous devez valider ces dates afin que, par exemple:
    • date de fin après la date de début
    • date de fin
    • pas des siècles loin de la date de début
  • Vous voulez des erreurs de validation apparaissent en ligne dans le formulaire (même si ce n'est pas sauver)

Puisque vous voulez valider ces dates auxquelles ils seront plus difficiles à attraper quand ils sont nichés dans votre tableau de conditions. Je vous conseille d'essayer de les transmettre séparément et traiter ensuite avec eux plus tard:

$this->Model->find('all', array(
    'conditions' => array(/* normal conditions here */), 
    'dateRange' => array(
     'start' => /* start_date value */, 
     'end' => /* end_date value */, 
    ), 
)); 

Vous devriez nous l'espérons être en mesure de gérer tout le reste dans le filtre beforeFind:

public function beforeFind() { 
    // perform query validation 
    if ($queryData['dateRange']['end'] < $queryData['dateRange']['start']) { 
     $this->invalidate(
      /* end_date field name */, 
      "End date must be after start date" 
     ); 
     return false; 
    } 
    /* repeat for other validation */ 
    // add between condition to query 
    $queryData['conditions'][] = array(
     'Model.dateField BETWEEN ? AND ?' => array(
      $queryData['dateRange']['start'], 
      $queryData['dateRange']['end'], 
     ), 
    ); 
    unset($queryData['dateRange']); 
    // proceed with find 
    return true; 
} 

Je ne l'ai pas essayé d'utiliser Model::invalidate() pendant une opération de recherche, donc cela pourrait même ne pas fonctionner. L'idée est que si le formulaire est créé en utilisant FormHelper ces messages devraient le faire revenir à côté des champs de formulaire.

A défaut, vous devrez peut-être effectuer cette validation dans le contrôleur et utiliser Session::setFlash(). Si c'est le cas, vous pouvez également vous débarrasser du beforeFind et mettre le tableau d'état BETWEEN avec vos autres conditions.

1

si vous voulez trouver les données des 20 derniers jours.

$this->loadModel('User'); 
    //$this->User->recursive=-1; 
    $data=$this->User->find('all', array('recursive' => 0, 
    'fields' => array('Profile.last_name','Profile.first_name'),'limit' => 20,'order' => array('User.created DESC'))); 

autres sages entre deux dates

$start = date('Y-m-d') ; 
     $end = date('Y-m-d', strtotime('-20 day')); 
     $conditions = array('User.created' =>array('Between',$start,$end)); 
     $this->User->find("all",$conditions) 
Questions connexes