Увеличить несколько строк в laravel

У меня есть немного сложный запрос, с которым мне нужна помощь:

Logic

  1. В таблице subscriptions есть строки с user_id (у каждого пользователя может быть много строк)
  2. Таблица products требует tokens (пример 2 токена требуется для продукта A)
  3. Теперь эти токены должны быть рассчитаны на основе суммы подписки пользователя. Допустим, у пользователя есть 2 строки в таблице подписок, одна с токеном 1, а другая с токеном 5 (всего у пользователя 6 токенов), и ему нужно использовать только 2 из них.
  4. Что я пытаюсь сделать здесь, так это обновить таблицу подписок для этого пользователя и пометить его столбец строк used_tokens, увеличив их.

Вы можете быть сбиты с толку немного сейчас! вот скриншоты, чтобы сделать это визуально понятным для вас.

products table

subscriptions table

Проблема

Проблема в том, что я не могу обновить столбцы used_tokens в этих двух строках в таблице subscriptions.

Вот что должно получиться в итоге

Код

Это то, что у меня есть на данный момент (получение правильного продукта, получение пользовательских подписок), и мне нужно обновить эти подписки:

$product = Product::findOrFail($request->input('product_id')); // Get product
$required_tokens = $product->required_tokens; // Get product require tokens (i.e. 2)
$subscriptions = Subscription::where('user_id', $user->id)->where('isPaid', true)->where('used_tokens', '<', 'tokens')->get(); // Get user subscription rows

Как я могу обновить (увеличить) used_tokens в этих строках?

Вместо того, чтобы распределять стоимость токена (2) по обеим строкам подписки, не будет ли проще уменьшить одну строку до тех пор, пока она не будет исчерпана, а затем перейти к следующей? Или есть причина, по которой они должны быть распределены поровну? Это поднимает вопрос о том, как справиться с этим, когда стоимость, например, равна 3.

Gavin 15.04.2023 13:15
$subscriptions = Subscription::where('user_id', $user->id)->where('isPaid', true)->where('used_tokens', '<', 'tokens')->update(['used_tokens' => DB::raw('used_tokens + 1')]); ??
OMi Shah 15.04.2023 14:03

@OMiShah, где в этом запросе гарантируется, что увеличенное число used_tokens не превышает число tokens, и оно переключается на следующую строку, когда первая строка used_tokens и tokens равны?

mafortis 15.04.2023 21:15

@mafortis, да, это так.

OMi Shah 16.04.2023 13:00

@OMiShah, ты тоже не забыл использовать $required_tokens? откуда он должен знать, сколько токенов он предполагает увеличить?

mafortis 17.04.2023 06:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как насчет чего-то подобного?

$product = Product::findOrFail($request->input('product_id'));
$required_tokens = $product->required_tokens;
$subscriptions = Subscription::where('user_id', $user->id)->where('isPaid', true)->where('used_tokens', '<', 'tokens')->get();

$remaining_tokens = $required_tokens;

foreach ($subscriptions as $subscription) {
  if ($remaining_tokens > 0) {
    $row = DB::table('subscriptions')
       ->where('id', $subscription->id)
       ->first();

    if (!empty($row)) {
      $available_tokens = $row->tokens - $row->used_tokens;

      if ($available_tokens > 0) {
        $tokens_to_be_used = ($remaining_tokens >= $available_tokens) ? $available_tokens : $remaining_tokens;

        $final_used_tokens = $row->used_tokens + $tokens_to_be_used;

        DB::table('subscriptions')
           ->where('id', $subscription->id)
           ->update([
               'used_tokens' => final_used_tokens,
           ]);

        $remaining_tokens = $remaining_tokens - $available_tokens;
      }
    }
  }
}

Окончательный (очищенный) код

$subscriptions = Subscription::where('user_id', $user->id)->where('isPaid', true)->get();

foreach ($subscriptions as $subscription) {
    if ($subscription->used_tokens < $subscription->tokens){
        if ($required_tokens > 0) {
            $available_tokens = $subscription->tokens - $subscription->used_tokens;
            $tokens_to_be_used = ($required_tokens >= $available_tokens) ? $available_tokens : $required_tokens;
            $final_used_tokens = $subscription->used_tokens + $tokens_to_be_used;
            DB::table('subscriptions')
            ->where('id', $subscription->id)
            ->update([
                'used_tokens' => $final_used_tokens,
            ]);
            $required_tokens = $required_tokens - $available_tokens;
        }
    }
}

где в этом запросе гарантируется, что увеличенное число used_tokens не превышает число tokens, и оно переключается на следующую строку, когда первая строка used_tokens и tokens равны?

mafortis 15.04.2023 21:16

Ваша 3-я команда гарантирует, что used_tokens меньше, чем tokens: $subscriptions = Subscription::where('user_id', $user->id)->where('isPaid', true)->where('used_tokens', '<', 'tokens')->get(); Таким образом, каждая запись подписки имеет место для увеличения. 0 становится 1 для первой строки (1 маркер), 0 становится 1 для второй строки (5 маркеров). Верно?

Ahmet Firat Keler 16.04.2023 11:42

да, но вы не забыли использовать $required_tokens? откуда он должен знать, сколько токенов он предполагает увеличить?

mafortis 17.04.2023 06:25

Понял тебя. Я обновил свой ответ.

Ahmet Firat Keler 17.04.2023 11:25

Спасибо, это сработало (поэтому ответ принят), но возникла проблема со сравнением used_tokens и tokens в запросе модели, а также в вашем коде были некоторые ненужные части. Итак, я обновил ваш ответ окончательным очищенным кодом.

mafortis 18.04.2023 08:33

Вы сделали то, что я ожидал. Спасибо.

Ahmet Firat Keler 18.04.2023 09:25

Вы можете одновременно обновлять несколько моделей в laravel, используя красноречивые отношения laravel.

#App\Models\User.php
class User extends Authennticable {
    public function subscriptions ()
    {
        return $this->hasMany(Subscription::class);
    }
}

После установки этого отношения вы можете обновить подписки пользователя, используя приведенный ниже код:

$user = User::find($id);

$user->subscriptions()->where(isPaid, true)->upadte(['used_tokens' => 'new_value']);

Другие вопросы по теме