【问题标题】:Get 3 Items per day from array with a cron job使用 cron 作业每天从数组中获取 3 个项目
【发布时间】:2019-07-16 21:34:14
【问题描述】:

我有一个每天运行的小型 PHP Cron 作业,从 API 获取文件并将其保存到静态文件中。

file_put_contents("api.json", fopen("http://example.com/api", 'r'));

这个 JSON 的内容是这样的:

{ 
  recipes: [
  {
    id: 30476,
    title: "Selfmade Chicken Nuggets",
    ...
  }, 
  {...} ] 
}

我的问题:我想创建一个“每日食谱”逻辑。

因此,我想每天创建一个包含食谱的额外数组。

在最好的情况下,我想要这样的东西:

第 1 步:创建一个包含所有食谱的“剩余食谱数组”

第 2 步:每天从剩余的食谱数组中获取 3 个食谱,并将它们放入某种“当日食谱”-数组中

第 3 步:如果剩余的食谱数组为空或没有 3 个元素,则从食谱中重新填充它

我的 Javascript 客户端中已经有了这个逻辑:

let fullRecipeList = await this.appData.getRecipeList();
let recipesOfTheDay = await this.appData.getItem("recipesOfTheDay");
let recipesOfTheDayValidUntil = await this.appData.getItem(
    "recipesOfTheDayValidUntil"
);
let remainingRecipes = await this.appData.getItem("remainingRecipes");

if (!remainingRecipes || remainingRecipes.length < 3) {
    remainingRecipes = this.shuffleArray(fullRecipeList);
}

if (
  recipesOfTheDay &&
  moment(recipesOfTheDayValidUntil).isSame(new Date(), "day")
) {
    this.recipeList = recipesOfTheDay;
} else {
    recipesOfTheDay = remainingRecipes.splice(0, 3);
    this.recipeList = recipesOfTheDay;
    await this.appData.setItem("remainingRecipes", remainingRecipes);
    await this.appData.setItem("recipesOfTheDay", recipesOfTheDay);
    await this.appData.setItem(
        "recipesOfTheDayValidUntil",
        moment().startOf("day")
    );
}

是否可以在我的服务器端 cron 作业中创建这种逻辑?

代码会是什么样子?我对整个 PHP 世界都很陌生 :)

【问题讨论】:

  • 是的,您可以使用相同的逻辑。你可以有两个文件,recipesOfTheDay.jsonremainingRecipes.json
  • 最好通过服务器端实际实现它,但我建议您考虑使用 SQLite 之类的存储,而不是使用 JSON 文件。它更快、更高效。

标签: php cron


【解决方案1】:

有时如果你直接在cron 中使用php,环境上下文不同,文件可能会出现问题:找不到文件进行读取,或者文件可以写入奇怪的地方。

我在 cron 工作中所做的是直接使用 wget 或类似实用程序调用 Web 服务:

# every day at eight run recipes of the day
* 8 * * * wget -q -O /dev/null 'https://www.server.com/recipesOfTheDay.php'

您甚至可以使用localhost 作为您的服务器名称。

然后您的脚本可以保存到本地 JSON 文件或任何修改过的内容。

【讨论】:

    【解决方案2】:

    这样的?

    <?php
    
    $totalRecipesPerDay = 3;
    
    // Open remaining receipes. If the file does not exists, return an empty array
    $remainingRecipes = file_exists('remaining_recipes.json') ? json_decode(file_get_contents('remaining_recipes.json'), true) : [];
    
    // Check if atleast $totalRecipesPerDay are available
    if (count($remainingRecipes) < $totalRecipesPerDay) {
        // Insufficient receipes, getting it from the complete list
        $remainingRecipes = json_decode(file_get_contents('all_recipes.json'), true);
    
        // Shuffling results
        shuffle($remainingRecipes);
    }
    
    $recipesOfTheDay = [];
    for ($i = 0; $i < $totalRecipesPerDay; ++$i) {
        // Extracting n times a recipe from my remaining list, and update it in the meantime
        $recipesOfTheDay[] = array_shift($remainingRecipes);
    }
    
    // Save results :D
    file_put_contents('remaining_recipes.json', json_encode($remainingRecipes));
    file_put_contents('recipes_of_the_day.json', json_encode($recipesOfTheDay));
    
    
    

    然后使用crontab -e设置一个cronjob:

    * * * * * php /var/www/your_project/file.php

    这里是说明:

    https://www.ostechnix.com/wp-content/uploads/2018/05/cron-job-format-1.png

    【讨论】:

      【解决方案3】:

      未测试。见脚本下面的 cmets。

      if ( ! file_exists('remaining-recipes.json')  // e.g. on first ever run of script
         $reminingRecipeArray = renew_remaining_recipes_file();
      }
      else {
         $reminingRecipeArray = json_decode(file_get_contents('remaining-recipes.json'), true);
         if count($reminingRecipeArray) < 3 ) renew_remaining_file();
      }
      
      // equivalent to your javascript example
      $recipesOfTheDayArray = array[];
      shuffle($reminingRecipeArray);
      for ($i=0; $i < 2; $i++) {
        $recipesOfTheDayArray[i] = array_pop($reminingRecipeArray);
       // n.b. pop gets/removes element from array end - see my answer
      }
      
      file_put_contents('recipes_of_the_day.json', json_encode($recipesOfTheDayArray));
      file_put_contents('remaining_recipes.json', json_encode($reminingRecipeArray));
      
      //----------------
      //***Functions****
      //----------------
      
      function renew_remaining_recipes_file() {
        if ( ! file_exists('allrecipes.json') ) {
          get_all_recipes_file(); // remove surrounding "if" to always refresh via API whenever remaining list empty
        }
        $reminingRecipeArray = json_decode(file_get_contents('allrecipes.json'), true);
        if (empty( $reminingRecipeArray) || count($reminingRecipeArray) < 3 ) {  // on fail or empty array
          email_and_exit('could not refresh remaining recipe list - maybe allrecipes file is not json');
        }
        return $reminingRecipeArray;
      }
      
      function get_all_recipes_file() {
        // uses yor current code which I assume works
        $allOK = file_put_contents("allrecipes.json", fopen("http://example.com/api", 'r'));
        // $allOK is FALSE (0) on failure otherwise number of bytes in file
        if ($allOK < 500) {
          email_and_exit('Failed to create "allrecipes.json" or created file or too small for expected data');
        }
      }
      
      DEFINE("TESTING", TRUE);
      function email_and_exit($msg) {
        if (TESTING) echo $msg; // additionally echo msg to screen when testing
        mail(YOUR_EMAIL_ADDRESS, 'Recipe Error', $msg, 'From: yourpage@YOURSITE');
        exit;
      }
      

      上面的代码使用 array_pop 从剩余食谱数组的末尾取出 3 个项目。如果您希望从数组的开头获取食谱,请使用数组 _shift 但效率较低https://www.php.net/manual/en/function.array-pop.php#112946

      您的访问者可能位于不同的时区,因此如果他们在第二天(他们的)12 小时后返回,他们可能会看到相同的食谱。这可以单独使用 PHP 解决,但回想起来,在使用天气 API 时,如果不熟悉 PHP,这可能会很棘手。您可以通过混合使用 PHP 和 JS 创建和循环 3(9?) recipe of day 条目(或以天数为后缀的 3 个文件)来满足这一点

      来自 PHP 的天数;

      $serverDay = idate('w', $timestamp);  // day of week as integer (Sunday=0);
      $dayafter = $intDay + 1;
      $daybefore = $intDay - 1;
      

      然后在您的 JavaScript 调用中使用 getDay() 中的数字来告诉服务器应该提供哪一天。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-06-14
        • 2013-09-06
        • 1970-01-01
        • 2011-05-31
        • 2012-08-09
        • 2022-01-07
        • 2015-08-19
        • 2021-04-01
        相关资源
        最近更新 更多