0

现在,我有一个数据库表,它以“日期时间”格式存储有关用户的信息及其出生日期。该数据库表与相应的 ActiveRecord 模型相关联。

在用户搜索表单中,我想按年龄范围实现搜索(分别有两个表单下拉字段,“从”和“到”年龄)。

我认为在对数据库表执行搜索之前,我必须将通过表单提交的年龄转换为实际的“日期时间”日期。

总的来说,我对 CDb Criteria 和 Yii 的理解还不够。这在社交网络中似乎很常见,但我无法为我的问题找到足够的答案。

在等待回复时,我有点找到了解决方案。但我想我可能没有直接思考,所以我可能想出了一些不太合理的东西。但它有效。

我在我的用户模型中创建了两个变量:

        public $fromBirthdate;
        public $toBirthdate;

我将搜索表单中的搜索字段从单个生日字段更改为字段“to”和“from”,它们分别保存表示最小和最大年龄的整数。

我将这些字段与模型中新创建的变量联系起来。

<div class="row">
        <?php echo $form->label($model,'fromBirthdate'); ?>
        <?php echo $form->textField($model,'fromBirthdate'); ?>
    </div>

    <div class="row">
        <?php echo $form->label($model,'toBirthdate'); ?>
        <?php echo $form->textField($model,'toBirthdate'); ?>
    </div>

>

然后我写了一个函数,根据当前时间将年龄转换为生日:

//transforms age into birthdate based on current date
//@param integer age
//@param integer default age (what age should be applied in case the age parameter is null)
//$returns string date formatted MySQL timestamp

public function getBirthdate($age, $defaultAge)
{
    if($age == null)
    $age = $defaultAge;

    $birthDate = date('Y-m-d H:i:s',strtotime("-" . $age . "years", time()));
    return $birthDate;
}
  • 通过添加以下行,我在模型的 search() 函数中对 CDbCriteria 的实例进行了一些修改:

 
//specifies range of age the users should be searched within
    //if either of the age fields ("to" or "from" age") was not filled, default age is applied
    //default age range is from 10 to 110 years old. 
    $criteria->addBetweenCondition('birthdate', $this->getBirthdate($this->toBirthdate, 110), $this->getBirthdate($this->fromBirthdate, 10));

总而言之,当用户通过搜索表单提交年龄范围时,它会以整数形式存储在这两个变量中。然后它们会被包含从提交的年龄转换而来的日期时间戳的字符串覆盖。

如果用户没有在搜索中指定最小和最大年龄,我必须引入所谓的“默认最小和最大年龄值”。我不确定这是有史以来最明智的想法,但它对我很有效。

4

1 回答 1

0

我建议为此使用参数化的命名范围:http ://www.yiiframework.com/doc/guide/1.1/en/database.ar#named-scopes

将以下方法添加到您的模型中,确保将 createtime 更改为您自己的日期时间列的名称:

    public function byAge($to, $from)
    {
        $from = new DateTime("-$from years");
        $fromDate = $from->format('Y-m-d H:i:s');

        $to = new DateTime("-$to years");
        $toDate = $to->format('Y-m-d H:i:s');

        $this->getDbCriteria()->mergeWith(array(
            'condition' => 't.createtime BETWEEN :from AND :to',
            'params' => array(
                ':from' => $fromDate,
                ':to' => $toDate,
            ),
            'order' => 't.createtime DESC', // Youngest first
        ));

        return $this;
    }

从表单中获取 $to 和 $from 的值,其中 $to 是较年轻的年龄,$from 是较大的年龄。然后要使用该方法,请通过执行以下操作更改搜索方式:

$model = new User;
$to = 12;
$from = 25;
// Set other model attributes based on user input
$dataProvider = $model->byAge($to, $from)->search();

我用我自己的数据对此进行了测试并且它有效,但是如果你无法让它与你的数据一起使用,请告诉我。

于 2013-03-04T12:52:20.253 回答