每天从cron工作中获取3个项目

时间:2019-07-07 11:12:13

标签: php cron

我有一个每天运行的小型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世界都是陌生的:)

3 个答案:

答案 0 :(得分:1)

有时候,如果您直接在php中使用cron,则环境会有所不同,并且文件可能存在问题:找不到文件可供读取,或者文件可以写在陌生的地方

我在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文件或具有修改后内容的任何文件。

答案 1 :(得分:0)

像这样吗?

<?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

答案 2 :(得分:0)

未经测试。请参阅以下脚本注释。

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?)每日配方条目(或3个带日期编号的文件)

PHP的天数;

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

然后使用JavaScript调用中的getDay()中的数字告诉服务器应提供的日期。