关于php:下一个&

get next & previous id record in database on Yii

我需要yii框架上数据库中的下一个和上一个ID记录来下一个和上一个导航按钮?


我在yii2的模型中添加了以下功能:

1
2
3
4
5
6
7
8
9
public function getNext() {
    $next = $this->find()->where(['>', 'id', $this->id])->one();
    return $next;
}

public function getPrev() {
    $prev = $this->find()->where(['<', 'id', $this->id])->orderBy('id desc')->one();
    return $prev;
}


我做了一个函数来获取你要查找的ID。我建议您在模型中声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static function getNextOrPrevId($currentId, $nextOrPrev)
{
    $records=NULL;
    if($nextOrPrev =="prev")
       $order="id DESC";
    if($nextOrPrev =="next")
       $order="id ASC";

    $records=YourModel::model()->findAll(
       array('select'=>'id', 'order'=>$order)
       );

    foreach($records as $i=>$r)
       if($r->id == $currentId)
          return isset($records[$i+1]->id) ? $records[$i+1]->id : NULL;

    return NULL;
}

所以要使用它,你所要做的就是:

1
YourModel::getNextOrPrevId($id /*(current id)*/,"prev" /*(or"next")*/);

它将返回下一条或上一条记录的对应ID。

我没有测试过,所以试一下,如果出了什么问题,请告诉我。


生成用于将信息传递给其他函数的私有var。

在模型中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Model1 .....
{
   ...
   private _prevId = null;
   private _nextId = null;
   ...

   public function afterFind()  //this function will be called after your every find call
   {
    //find/calculate/set $this->_prevId;
    //find/calculate/set $this->_nextId;
   }

   public function getPrevId() {
      return $this->prevId;
   }

   public function getNextId() {
      return $this->nextId;
   }

}

检查在VIEWDETAL链接中生成的代码,并使用修改视图文件中的prev/net链接

1
$model(or $data)->prevId/nextId

在数组("id"=>)部分中。


我的实现基于SearchModel。

控制器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public function actionView($id)
{
    // ... some code before

    // Get prev and next orders
    // Setup search model
    $searchModel = new OrderSearch();
    $orderSearch = \yii\helpers\Json::decode(Yii::$app->getRequest()->getCookies()->getValue('s-' . Yii::$app->user->identity->id));
    $params = [];
    if (!empty($orderSearch)){
        $params['OrderSearch'] = $orderSearch;
    }
    $dataProvider = $searchModel->search($params);
    $sort = $dataProvider->getSort();
    $sort->defaultOrder = ['created' => SORT_DESC];
    $dataProvider->setSort($sort);

    // Get page number by searching current ID key in models
    $pageNum = array_search($id, array_column($dataProvider->getModels(), 'id'));
    $count = $dataProvider->getCount();
    $dataProvider->pagination->pageSize = 1;

    $orderPrev = $orderNext = null;
    if ($pageNum > 0) {
        $dataProvider->pagination->setPage($pageNum - 1);
        $dataProvider->refresh();
        $orderPrev = $dataProvider->getModels()[0];
    }
    if ($pageNum < $count) {
        $dataProvider->pagination->setPage($pageNum + 1);
        $dataProvider->refresh();
        $orderNext = $dataProvider->getModels()[0];
    }
    // ... some code after
}

订单搜索:

1
2
3
4
5
6
7
8
9
10
11
public function search($params)
{
    // Set cookie with search params
    Yii::$app->response->cookies->add(new \yii\web\Cookie([
        'name' => 's-' . Yii::$app->user->identity->id,
        'value' => \yii\helpers\Json::encode($params['OrderSearch']),
        'expire' => 2147483647,
    ]));

    // ... search model code here ...
}

PS:确定是否可以使用array_column作为对象数组。这在PHP7+中很好,但在较低版本中,您必须自己提取id。也许在php 5.4中使用array_walkarray_filter是个好主意。+


把原来的答案改为yii2,稍微整理一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * [nextOrPrev description]
 * @source http://stackoverflow.com/questions/8872101/get-next-previous-id-record-in-database-on-yii
 * @param  integer $currentId [description]
 * @param  string  $nextOrPrev  [description]
 * @return integer         [description]
 */

public static function nextOrPrev($currentId, $nextOrPrev = 'next')
{
    $order   = ($nextOrPrev == 'next') ? 'id ASC' : 'id DESC';
    $records =
amespace\path\Model::find()->orderBy($order)->all();

    foreach ($records as $i => $r) {

       if ($r->id == $currentId) {
          return ($records[$i+1]->id ? $records[$i+1]->id : NULL);
       }

    }

    return false;
}


当您得到第一个或最后一个记录,并且它们对数据库进行多个调用时,前面的解决方案是有问题的。下面是我的工作解决方案,它对一个查询进行操作,处理表尾并禁用表尾的按钮:

在模型中:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static function NextOrPrev($currentId)
{
    $records = <Table>::find()->orderBy('id DESC')->all();

    foreach ($records as $i => $record) {
        if ($record->id == $currentId) {
            $next = isset($records[$i - 1]->id)?$records[$i - 1]->id:null;
            $prev = isset($records[$i + 1]->id)?$records[$i + 1]->id:null;
            break;
        }
    }
    return ['next'=>$next, 'prev'=>$prev];
}

在控制器内:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
     public function actionView($id)
{
    $index = <modelName>::nextOrPrev($id);
    $nextID = $index['next'];
    $disableNext = ($nextID===null)?'disabled':null;
    $prevID = $index['prev'];
    $disablePrev = ($prevID===null)?'disabled':null;

    // usual detail-view model
    $model = $this->findModel($id);

    return $this->render('view', [
        'model' => $model,
        'nextID'=>$nextID,
        'prevID'=>$prevID,
        'disableNext'=>$disableNext,
        'disablePrev'=>$disablePrev,
    ]);
}

在视图中:

1
2
<?= Html::a('Next', ['view', 'id' => $nextID], ['class' => 'btn btn-primary r-align btn-sm '.$disableNext]) ?>
<?= Html::a('Prev', ['view', 'id' => $prevID], ['class' => 'btn btn-primary r-align btn-sm '.$disablePrev]) ?>