具有“日期之间”的CakePHP模型

时间:2009-08-25 17:10:15

标签: mysql cakephp date

我有一个大型数据集(超过十亿行)。数据按日期在数据库中分区。因此,我的查询工具必须在每个查询中指定一个SQL between子句,否则它将必须扫描每个分区..而且,它会在它返回之前超时。

所以..我的问题是,分区数据库中的字段是日期..

使用CakePHP,如何在表单中指定“之间”日期?

我正在考虑在表单中执行“start_date”和“end_date”,但这可能会给我带来两个问题..如何在链接到表的模型中验证它?

3 个答案:

答案 0 :(得分:8)

如果我正确地关注你:

  • 用户必须指定从表单生成的查询查询的开始/结束日期
  • 您需要验证这些日期,例如:
    • 开始日期之后的结束日期
    • 结束日期距离开始日期不是几个世纪
  • 您希望验证错误在表单中内嵌显示(即使这不是保存)

由于您要验证这些日期,因此当它们隐藏在条件数组中时,它们将更难获取。我建议尝试单独传递这些内容,然后再处理它们:

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

您应该能够处理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;
}

我在搜索操作期间没有尝试使用Model::invalidate(),所以这可能甚至不起作用。我们的想法是,如果使用FormHelper创建表单,这些消息应该在表单字段旁边返回。

如果失败,您可能需要在控制器中执行此验证并使用Session::setFlash()。如果是这样,你也可以摆脱beforeFind并将BETWEEN条件数组与其他条件放在一起。

答案 1 :(得分:1)

如果您想查找过去20天的数据。

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

两个日期之间的其他明智

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

答案 2 :(得分:0)

您可以在模型中编写自定义方法,以便在日期之间进行搜索:

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

就验证而言,您可以使用模型的beforeValidate()回调来验证这两个日期。有关此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();
}

这会回答你的问题吗?