【问题标题】:Yii2 How to use dataprovider with custom and dynamic aliasYii2 如何使用具有自定义和动态别名的数据提供程序
【发布时间】:2021-10-28 10:44:19
【问题描述】:

在 yii2 中我必须使用带有用户定义的动态别名的 SQL。

由于它是动态的,因此无法在模型中添加为公共属性。

因此以下代码不适用于以下 SQL:

SELECT `item_id`         AS `Item Id`,
       `on_hand`         AS `On Hand`,
       `initial_on_hand` AS `Amount Produced`,
       `best_by_date`    AS `Best By`,
       `item_name`               AS `Item Name`
FROM   `stock` 

这里是yii2代码:

$dataProvider = new ActiveDataProvider([
   'query' => $query,
]);

那么,我可以使用带有分页和控件的 yii2 网格的可能解决方案是什么?

【问题讨论】:

  • 你有什么理由必须在 SQL 中使用这些别名?从您的示例看来,使用模型的标签会是更好的解决方案。
  • 是的,因为我使用了查询生成器,在这里用户可以为任何字段添加他们选择的标签

标签: yii yii2 yii2-advanced-app yii-extensions


【解决方案1】:
$query = StockModel::find();
$query->select([
            'stock.item_id as Item Id',
            'stock.on_hand as On Han',
            'stock.intial_on_hand as Amount Produced',
            'stock.best_By_date as Best By',
            'stock.item_name as Item Name'
    ]);

$dataProvider = new ActiveDataProvider(['query' => $query]);

【讨论】:

    【解决方案2】:

    如果您绝对坚持在 SQL 查询中使用用户输入作为别名,您可以使用 yii\data\SqlDataProvider 而不是 yii\data\ActiveDataProvider

    我仍然认为这样做是个坏主意,因为可能存在 SQL 注入。在 SQL 查询中无法使用参数作为别名。这意味着您让用户直接修改您的 SQL 查询。

    如果您想拥有动态标签,例如,您可以这样做。 假设您在 DB 中有一些 dynamic_label 表,您可以在其中存储在后端设置的标签。该表可以如下所示:

    id model field label
    1 Stock item_id Item ID
    2 Stock on_hand On hand

    您还拥有 DynamicLabel 模型作为该表的 ActiveRecord 模型。然后,您的模型可以如下所示:

    class Stock extends ActiveRecord
    {
        private static ?array $labels = null;
    
        private static function loadLabels(): void
        {
            if (self::$labels !== null) {
                // Labels are already loaded
                return;
            }
            self::$labels = DynamicLabel::find()
               ->select(['label', 'field']) // we will only need columns label and field
               ->where(['model' => 'Stock']) // select only rows that belong to current model 
               ->indexBy('field') // index result using the value in field column
               ->column(); // get first column of result as array
        }
    
        public function attributeLabels(): array
        {
            self::loadLabels();
            return self::$labels;
        }
    
        // ... other definitions in Stock model ...
    }
    

    标签存储在静态属性中,以确保它们在请求期间仅加载一次,即使使用多个 Stock 模型实例并且多次调用 attributeLabels() 方法。

    【讨论】:

      【解决方案3】:

      使用这个解决方案

      $query = (new Query()) 
             ->select(
             'stock.item_id as Item Id,
              stock.on_hand as On Han,
              stock.intial_on_hand as Amount Produced,
              stock.best_By_date as Best By ,
              stock.item_name as Item Name
             )
              ->from('notifications as n') ->all()
          
          ------------------------------------------------------------------------
      

      如果您的目的是获取标签,您可以简单地在模型库存中创建一个名为 attributeLabels() 的方法,而不是这样做。

        public function attributeLabels()
          {
              return [
                  'item_id' => 'Item Id',
                  'on_hand' => 'On Hand',
                  'initial_on_hand' => 'Amount Produced`,
                  'decaissement_id' => 'Decaissement ID',
                  'best_by_date' => 'Approved By',
                  'item_name' => 'Item Name',
              ];
          }
      

      【讨论】:

      • 不,作为在后端添加别名的用户不起作用,我必须创建一个带有该标签的网格。所以它是一个动态值而不是预定义的
      • 好吧,你的问题并不准确,所以我给你两种可能性。第二个应该可以正常工作
      猜你喜欢
      • 2020-02-16
      • 1970-01-01
      • 2011-09-09
      • 2013-03-05
      • 2021-02-11
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多