Laravel 正确的条件处理

Laravel correct condition handling

我的网站上有一个功能,可以每 24 小时自动为会员创建一次促销代码。如果促销代码创建后已过去 24 小时,则会从数据库中删除旧促销,并重新生成一个新促销。但是现在这个功能有问题,不管是否过了24小时,每次都会生成一个新的优惠码。

我的函数:

    public function autoGroupPromos()
    {

        $userList = Promo::get();
        $userIds = $userList->pluck('user_id');


        foreach ($userIds as $id)  {
            $date = Carbon::now();
            $promoCodes = Promocode::query()->where('vk_user_id', '!=', null)->get();
            foreach ($promoCodes as $promos) {

                // If promo create 24 hours ago
                $hours = $promos->created_at->diffInHours($date);
                if ($hours >= 24) {
                    $promos->delete();
                }
            }

            $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyz';
            $code = substr(str_shuffle($permitted_chars), 0, 8);

                    Promocode::query()->create([
                        'name' => $code,
                        'sum' => '0.25',
                        'activates' => '100',
                        'vk_user_id' => $id
                    ]);


                    $promoText = Promocode::where('vk_user_id', $id)->orderBy('created_at', 'desc')->first();
                    $promoName = $promoText->name;


                    $message = 'Your new promo: ' . $promoName . ';

                    $url = 'https://api.vk.com/method/messages.send';
                    $params = array(
                        'message' => $message,  
                        'access_token' => 'token',
                        'v' => '5.81',
                        'peer_ids' => $id
                    );

                    $result = file_get_contents($url, false, stream_context_create(array(
                        'http' => array(
                            'method' => 'POST',
                            'header' => 'Content-type: application/x-www-form-urlencoded',
                            'content' => http_build_query($params)
                        )
                    )));
        }
    }

也就是说,如果促销创建后不到 24 小时 - 不应将其删除,也不应生成新的促销代码。但现在不幸的是某处出错了。

可能是什么问题?

function autoGroupPromos()
{
  // removed for loop to clean outdated promos in single request
  // note that this way of deleting rows won't fire model events (if any)
  Promocode::whereNotNull('vk_user_id')
    ->where('created_at', '<=', Carbon::now()->subDay(1))
    ->delete();

  $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyz';

  $userIds = Promo::pluck('user_id');  
  
  foreach ($userIds as $id) {
    /* in the begining we cleaned all outdated codes, so if user still has 
     some - no need to create new */
    if (Promocode::where('vk_user_id', $id)->exists()){
      continue;
    }

    $code = substr(str_shuffle($permitted_chars), 0, 8);
    /* you can immidiately get create model like this - 
       no need to make another request
    $createdPromo = Promocode::create([*/
    Promocode::create([
      'name' => $code,
      'sum' => '0.25',
      'activates' => '100',
      'vk_user_id' => $id
    ]);

    /* didn't get why you were requesting newly created 
    promo to get name field if you put there $code value */
    $message = `Your new promo: $code`;

    $url = 'https://api.vk.com/method/messages.send';
    $params = array(
      'message' => $message,
      'access_token' => 'token',
      'v' => '5.81',
      'peer_ids' => $id
    );

    $result = file_get_contents($url, false, stream_context_create(array(
      'http' => array(
        'method' => 'POST',
        'header' => 'Content-type: application/x-www-form-urlencoded',
        'content' => http_build_query($params)
      )
    )));
  }
}

upd:这里可以使用 hasOneOfMany 并跳过每个用户请求以检查促销代码是否存在

// User model
public function promocodes() {
  return $this->hasMany(Promocode::class);
}

public function promocode() {
  return $this->hasOne(Promocode::class)->latestOfMany();
}
function autoGroupPromos()
{
  // note that this way of deleting rows won't fire model events (if any)
  Promocode::whereNotNull('vk_user_id')
    ->where('created_at', '<=', Carbon::now()->subDay(1))
    ->delete();

  $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyz';

  // taking users without promo after cleanup
  User::whereDoesntHave('promo')->get()
    ->each(function (User $user) use ($permitted_chars) {
      $code = substr(str_shuffle($permitted_chars), 0, 8);
      // pay attention on relation name - using hasMany
      $user->promocodes()->save(
        new Promocode([
          'name' => $code,
          'sum' => '0.25',
          'activates' => '100',
        ])
      );

      $message = `Your new promo: $code`;

      $url = 'https://api.vk.com/method/messages.send';
      $params = array(
        'message' => $message,
        'access_token' => 'token',
        'v' => '5.81',
        'peer_ids' => $id
      );

      $result = file_get_contents($url, false, stream_context_create(array(
        'http' => array(
          'method' => 'POST',
          'header' => 'Content-type: application/x-www-form-urlencoded',
          'content' => http_build_query($params)
        )
      )));
    });
}

link Inserting & Updating Related Models