【问题标题】:How to make looped function calls for pagination?如何使循环函数调用分页?
【发布时间】:2019-06-11 17:13:50
【问题描述】:

我正在尝试使用 Airtable API 从那里的数据中检索记录 - 具体来说,是我在列单元格中的 URL 列表。

我编写了一个函数get_airtable_records,通过curl 进行API 调用,它可以工作——将结果作为Json 对象返回。具体来说,我将 URL 推送到数组 $article_urls

唯一的问题是,Airtable 将结果的返回限制为最多 100 条记录的“页面”,而我的数据包含的不止这些。 API 接受参数maxRecordspageSize,但更重要的参数pageSize 仍然上限为100。

Airtable 还返回另一个 Json 值,offset,在这种情况下用于分页。 offset 是一个记录 ID,旨在用作输入参数(也称为 offset)。 您可以使用它来表示后续附加 API 调用中的开始记录。我明白这一点

我不明白的是如何修改我的代码以解决需要再次轮询 Airtable 的可能性。

换句话说,当没有offset 值时,我们应该始终从头开始运行。 然后,如果在返回的结果中存在 offset 值,我们应该再次检查 - 直到不存在 offset 值。

这就是我所拥有的。

  // Make get request, store result in array
  $articles = get_airtable_records($offset); // $offset won't exist at the start

  // Prepare Article URLs list as an array
  if (!isset($article_urls)) {
     $article_urls = array();
  }

  // For each URL found in Airtable
  foreach($articles['records'] as $record){
     $url = $record['fields']['Published URL'];
     // Add to our array list
     if (!empty($url)) {
        array_push($article_urls, $url);
     }
  }

  // URL list after first pass:
  echo '<pre>';
  print_r($article_urls);
  echo '</pre>';
  // May hit a max of 100

  // echo 'Offset: ' . $articles['offset'];
  // Value like "itrJYSLx0RfslI80f/recEu6TiPTPCSDxg5" may exist.
  // If so, go back to start, do get_airtable_records($offset) again and array_push
  // Until, once more there is no "offset" value at end

我推测某种while 循环会很有用...?

有几件事是真的......

  • 在第一次调用中,不需要传递原始 offset 值,因为它从记录 0 开始。
  • 但是那次和后续的传递可能会生成一个offset 值,应该使用它来进行另一次传递。
  • final 调用不会生成offset 值,因为它会返回耗尽结果的最后一页,无需重新开始。

【问题讨论】:

标签: php loops while-loop pagination offset


【解决方案1】:

非常感谢@anthony's answer to a similar question here,我似乎有一些工作代码...

  // Prepare Article URLs list as an array
  $article_urls = array();

  // Call Airtable records in pages of 100 max
  do {

        // Offset is either inherited from last page's results, or is nothing
        $offset = $articles['offset'] ?: "";

        // Make get request, store result in array
        $articles = get_airtable_records($offset);

        // For each URL found in Airtable
        foreach($articles['records'] as $record){
           $url = $record['fields']['Published url'];
           // Add to our array list
           if (!empty($url)) {
              array_push($article_urls, $url);
           }
        }

  } while(!empty($articles['offset'])); // If there's an offset value (ie. starting record of next page), do again

  // Output URL list for check
  echo '<pre>';
  print_r($article_urls);
  echo '</pre>';

解释似乎是:

使用do while 循环。 在此开始时,将 offset 设置为从上一次运行继承的值,或者不设置任何值。

我的 get_airtable_records 函数已经在 API 调用中限制了 offset 的存在与否,如果存在,它将offset 查询字符串添加到下一个 API 调用的 URL 中。 .

  if (!empty($offset)) {
    $q_offset = '&offset='.$offset;
  }

我已经对此进行了测试,它在我的$article_urls 数组中为我提供了两页中的所有 137 个结果。我没有用超过两页的结果对其进行测试。

【讨论】:

    【解决方案2】:

    递归匿名函数也适用于自动分页器。

    // http client
        $client
        // closure
        $autoPaginate = function (int $offset) use (&$autoPaginate, $client) {
            $response = $client->get('https://blah.com, [
                'offset' => $offset,
                'per_page' => 100,
            ]);
            // do response business logic/work
            
            // check your response meta or
            // wherever the next page or offset is passed back
            if (!$response->meta->next->offset) return;
            return $autoPaginate($response->meta->next->offset);
        };
        $autoPaginate(0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-07
      • 1970-01-01
      • 2016-07-13
      • 2016-04-01
      • 2018-02-16
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      相关资源
      最近更新 更多