yii2tech / ar-position
为 Yii2 提供 ActiveRecord 自定义排序支持
Requires
- yiisoft/yii2: *
This package is auto-updated.
Last update: 2022-01-10 10:43:08 UTC
README
ActiveRecord Position Extension for Yii2
本扩展提供对 ActiveRecord 自定义记录顺序设置的支持。
有关许可信息,请参阅 LICENSE 文件。
安装
安装此扩展的首选方式是通过 composer。
运行以下命令:
php composer.phar require --prefer-dist yii2tech/ar-position
或者添加以下内容到您的 composer.json 的 require 部分:
"yii2tech/ar-position": "*"
使用方法
此扩展通过基于列的位置索引提供对自定义记录顺序设置的支持。
此扩展为在 Yii2 中支持此类解决方案提供了 \yii2tech\ar\position\PositionBehavior
ActiveRecord 行为。您可以通过以下方式将其附加到您的模型类中
<?php use yii\db\ActiveRecord; use yii2tech\ar\position\PositionBehavior; class Item extends ActiveRecord { public function behaviors() { return [ 'positionBehavior' => [ 'class' => PositionBehavior::className(), 'positionAttribute' => 'position', ], ]; } }
行为使用数据库实体的特定整数字段来设置位置索引。因此,模型所引用的数据库实体必须包含字段 positionAttribute
。
为了正确显示自定义列表,您应该按 positionAttribute
以升序对其进行排序
<?php $records = Item::find()->orderBy(['position' => SORT_ASC])->all(); foreach ($records as $record) { echo $record->position . ', '; } // outputs: 1, 2, 3, 4, 5,...
位置保存
附加行为后,会自动为新记录填充 positionAttribute
值,将其放置在列表末尾
<?php echo Item::find()->count(); // outputs: 4 $item = new Item(); $item->save(); echo $item->position; // outputs: 5
但是,您可以明确为新记录设置位置
<?php echo Item::find()->count(); // outputs: 4 $item = new Item(); $item->position = 2; // enforce position '2' $item->save(); echo $item->position; // outputs: 2 !!!
位置切换
可以使用以下方法将现有记录移动到另一个位置
movePrev()
- 将记录移动一个位置到列表的开头。moveNext()
- 将记录移动一个位置到列表的末尾。moveFirst()
- 将记录移动到列表的开头。moveLast()
- 将记录移动到列表的末尾。moveToPosition()
- 将所有者记录移动到指定位置。
您还可以通过提供给 positionAttribute
的属性来更改记录的位置
<?php $item = Item::find()->andWhere(['position' => 3])->one(); $item->position = 5; // switch position to '5' $item->save();
组内位置
有时单个数据库实体包含多个列表,这些列表需要自定义排序,并通过分组属性在逻辑上分离。例如:FAQ 问题可以根据类别分组,而在单个类别内问题应手动排序。为此,可以使用 \yii2tech\ar\position\PositionBehavior::$groupAttributes
<?php use yii\db\ActiveRecord; use yii2tech\ar\position\PositionBehavior; class FaqQuestion extends ActiveRecord { public function behaviors() { return [ 'positionBehavior' => [ 'class' => PositionBehavior::className(), 'positionAttribute' => 'position', 'groupAttributes' => [ 'categoryId' // multiple lists varying by 'categoryId' ], ], ]; } }
在这种情况下,行为将使用 groupAttributes
的所有者值作为位置计算和更改的附加条件
<?php echo FaqQuestion::find()->andWhere(['categoryId' => 1])->count(); // outputs: '4' echo FaqQuestion::find()->andWhere(['categoryId' => 2])->count(); // outputs: '7' $record = new FaqQuestion(); $record->categoryId = 1; $record->save(); echo $record->position; // outputs: '5' $record = new FaqQuestion(); $record->categoryId = 2; $record->save(); echo $record->position; // outputs: '8'
列表导航
应用了自定义位置排序的记录会形成一个链表,如果需要,您可以进行导航。您可以使用 \yii2tech\ar\position\PositionBehavior::getIsFirst()
和 \yii2tech\ar\position\PositionBehavior::getIsLast()
方法来判断特定记录是否为列表中的第一个或最后一个。例如
<?php echo Item::find()->count(); // outputs: 10 $firstItem = Item::find()->andWhere(['position' => 1])->one(); echo $firstItem->getIsFirst(); // outputs: true echo $firstItem->getIsLast(); // outputs: false $lastItem = Item::find()->andWhere(['position' => 10])->one(); echo $lastItem->getIsFirst(); // outputs: false echo $lastItem->getIsLast(); // outputs: true
对于特定的记录实例,您可以使用 \yii2tech\ar\position\PositionBehavior::getNext()
或 \yii2tech\ar\position\PositionBehavior::getPrev()
方法来找到位于它之后或之前的记录。例如
<?php $item = Item::find()->andWhere(['position' => 5])->one(); $nextItem = $item->findNext(); echo $nextItem->position; // outputs: 6 $prevItem = $item->findPrev(); echo $prevItem->position; // outputs: 4
您还可以获取列表中的第一个和最后一个记录。例如
<?php echo Item::find()->count(); // outputs: 10 $item = Item::find()->andWhere(['position' => 5])->one(); $firstItem = $item->findFirst(); echo $firstItem->position; // outputs: 1 $lastItem = $item->findLast(); echo $lastItem->position; // outputs: 10