【问题标题】:In PHP, is there a way to loop through a query and organize it into a specific column based on a value?在 PHP 中,有没有办法循环查询并根据值将其组织到特定列中?
【发布时间】:2019-08-24 08:31:00
【问题描述】:

我正在使用 Laravel 并尝试从查询中填充 HTML 表。数据库中的表包含idusershift 等列。大约有 100 个条目,shift 列将包含字母 ABCD。我想将它输出到单个 HTML 表中,以便在循环时,输出表中的第一列将只包含具有该值的 A 的条目,第二个 B 的条目,依此类推。

这是我的查询:

Shift::orderBy('shift', 'ASC')
        ->get();

这当然会按字母顺序排序,然后当我循环使用它时:

      ...
  <tbody>
    @foreach ($shifts as $shift)
          <tr>
              <td>{{ $shift->id }}</td>
            ...
           </tr>
      @endforeach
   </tbody>
  ...

或类似的变体,我已经尝试了很多,它将遍历所有带有A 的条目并在表格中创建这些单元格/行,然后从B 开始。但是到那时,因为已经创建了这些,B 条目开始了,但是许多 A 条目已经关闭。

我已经遍历它并创建了四个单独的表,但我更愿意将它合二为一。我想用 Laravel Excel 导出表格,如果它们是单独的表格,它只是将它们堆叠起来,但我希望它们并排。无论如何,这就是我的意思和想要的(带有字母的行将是决赛表中的其他信息):

我错过了什么?我觉得我做的事情不是很简单。谢谢你的帮助。

【问题讨论】:

  • 您可能需要重新评估您存储和检索数据的方式。但是如果你必须实现这个目标,听起来你需要将它们分成 4 个数组,然后将它们重新组合在一起,每个数组值包含一个嵌套数组,其中包含 A-D 的潜在值。
  • 是的,我想我必须改变一些东西。我宁愿不这样做,因为这只是为了在将其导出到电子表格并循环创建 4 个表时显示得更好。但这是另一个话题。

标签: php html laravel html-table


【解决方案1】:

是的,您可以使用为此目的而存在的usort 对它们进行排序。 usort() 将使用用户定义的比较函数按值对数组进行排序。

$arr = [
    ['letter'=>'C'],
    ['letter'=>'A'],
    ['letter'=>'B'],
    ['letter'=>'A'],
    ['letter'=>'D'],
];

// Function to sort by provided column name
function cmp($key){
    // Returns comparision function to be used with usort
    return function($a,$b)use($key){
        return strcmp($a[$key], $b[$key]);
    };
}
usort($arr, cmp('letter'));
print_r($arr);

希望对你有帮助,

【讨论】:

    【解决方案2】:

    我想说实现这一点的最有效方法是在数据库级别进行排序。为此,您应该使用 orderBy() 方法。同样好的方法是有这个范围。

    public function scopeOrderByShiftsAsc($query)
    {
        return $query->orderBy('shifts', 'asc')->orderBy('created_at', 'desc');
    }
    
    // then in your controller
    public function index()
    {
        $users = \App\User::orderByShiftsAsc()->get();
    }
    

    您可以在 Query builder 或 eloquent 的方法链中使用这种方式 (orderBy())。 Query Scopes.

    【讨论】:

    • 如果我只是分组移位(字母 AD),它只从每个字母返回一个条目。如果我进一步分组,它只会输出与原始查询相同的结果;首先是所有的As,然后是Bs,Cs,然后是Ds。我做错了吗?
    • 现在尝试使用排序而不是分组。
    • 这就是我的原始查询(减去范围),我想我应该发布的。它只是按字母顺序排列,所以每个字母一个接一个大约有 20 个。它们都是从电子表格中导入的,因此创建时间是相同的。我认为通过排序实现这一目标的唯一方法是通过对ABCD 的块进行分组来对其进行排序;就像从每个字母中提取第一个条目,然后为每个字母重复该条目。但我想这必须在数据库级别之后使用数组来完成。
    • 对不起,我很困惑。您正在混合 HTML 中的表格和 DB 中的表格。您可以发布表格结构和硬编码或想要的 HTML 图像吗?您无需使用真实数据,而是帮助我们更好地了解您的要求。按照these 的建议去做。
    • 更新了原帖。抱歉我的含糊不清和混乱。
    【解决方案3】:

    使用:

    Shift::get()->keyBy('shift')->toArray();
    

    你得到一个类似于以下的结构:

    $data = [
      "A" = [
        ['id' => 1, 'shift' => 'A'],
        ...
      ],
      "B" = [
        ['id' => 2, 'shift' => 'B'],
        ...
      ],
      ...
    ]
    

    接下来,您可以遍历最大的字母并创建所需的输出结构:

    $letters = array_keys($data)
    $maxLength = 0
    foreach($letters as $letter) {
      $len = count($data[$letter]);
      if ($len > $maxLength) $maxLength = $len;
    }
    $output = []
    for($i = 0; $i < $maxLength: $i++) {
       $newRow = [];
       foreach($letters as $letter) {
         if (isset($data[$letter][$i])) {
           $newRow[$letter] = $data[$letter][$i]['id'];
         } else {
           $newRow[$letter] = '';
         }
       }
       $output[] = $newRow;
    }
    

    然后您可以将输出传递给刀片文件并将表创建为:

    @foreach ($output as $row)
          <tr>
              <td>{{ $row['A'] }}</td>
              <td>{{ $row['B'] }}</td>
              ...
           </tr>
      @endforeach
    

    【讨论】:

    • 谢谢,但该查询不是只导致该数组中有四个条目(每个字母 1,因为这是关键)?我需要收集然后循环遍历的每个字母大约有 25 行。
    • 不,这应该得到一切。
    猜你喜欢
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2019-08-28
    • 2020-05-08
    • 1970-01-01
    相关资源
    最近更新 更多