У меня есть немного сложный запрос, с которым мне нужна помощь:
Logic
subscriptions есть строки с user_id (у каждого пользователя может быть много строк)products требует tokens (пример 2 токена требуется для продукта A)1, а другая с токеном 5 (всего у пользователя 6 токенов), и ему нужно использовать только 2 из них.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 в этих строках?
$subscriptions = Subscription::where('user_id', $user->id)->where('isPaid', true)->where('used_tokens', '<', 'tokens')->update(['used_tokens' => DB::raw('used_tokens + 1')]); ??
@OMiShah, где в этом запросе гарантируется, что увеличенное число used_tokens не превышает число tokens, и оно переключается на следующую строку, когда первая строка used_tokens и tokens равны?
@mafortis, да, это так.
@OMiShah, ты тоже не забыл использовать $required_tokens? откуда он должен знать, сколько токенов он предполагает увеличить?






Как насчет чего-то подобного?
$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 равны?
Ваша 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 маркеров). Верно?
да, но вы не забыли использовать $required_tokens? откуда он должен знать, сколько токенов он предполагает увеличить?
Понял тебя. Я обновил свой ответ.
Спасибо, это сработало (поэтому ответ принят), но возникла проблема со сравнением used_tokens и tokens в запросе модели, а также в вашем коде были некоторые ненужные части. Итак, я обновил ваш ответ окончательным очищенным кодом.
Вы сделали то, что я ожидал. Спасибо.
Вы можете одновременно обновлять несколько моделей в 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']);
Вместо того, чтобы распределять стоимость токена (2) по обеим строкам подписки, не будет ли проще уменьшить одну строку до тех пор, пока она не будет исчерпана, а затем перейти к следующей? Или есть причина, по которой они должны быть распределены поровну? Это поднимает вопрос о том, как справиться с этим, когда стоимость, например, равна 3.