В этой строке кода:
$ratio = $this->getColorRatioForDeck($communityDecks[0]->username, $communityDecks[0]->deck_uid);
Вы заметите, что я получаю это соотношение по индексу, и я могу получить их все, используя цикл for, например так:
$ratio = [];
foreach($communityDecks as $deck) {
$ratio[] = $this->getColorRatioForDeck($deck->username, $deck->deck_uid);
}
Однако я бы попадал в базу данных n раз в зависимости от количества $ колод.
Как я могу объединить 2 запроса в приведенном ниже коде, чтобы получить информацию за один раз?
Вот что у меня сейчас есть:
private $take = 10;
public function decks() {
// get decks created by the community
$communityDecks = $this->getCommunityDecks();
$skip = 0;
return parent::ajaxView('mtg.decks', compact('communityDecks', 'skip'));
}
public function getCommunityDecks($skip = 0) {
$communityDecks = DB::table('auth.users_deck_overview as deckOverviewDB')
->select('deckOverviewDB.username', 'deckOverviewDB.by', 'deckOverviewDB.deck_uid', 'deckOverviewDB.featured', 'deckOverviewDB.name', 'deckOverviewDB.description', 'deckOverviewDB.usage', 'deckOverviewDB.format', 'deckOverviewDB.private')
->skip($skip)
->take($this->take)
->get();
// need to refactor this so it doesn't hit the database n times - ideally this for loop query should be combined with the above query
foreach($communityDecks as $deck) {
$deck->ratio = $this->getColorRatioForDeck($deck->username, $deck->deck_uid);
}
return $communityDecks;
}
public function getColorRatioForDeck($username, $deckUid) {
// get the corresponding deck information to calculate color ratio
$query = DB::table('auth.users_deck_overview as deckOverviewDB')
->leftJoin('auth.users_deck_cards as deckCardsDB', 'deckOverviewDB.deck_uid', '=', 'deckCardsDB.deck_uid')
->leftJoin('mtg_cards.cards as cardsDB', 'deckCardsDB.card_uid', '=', 'cardsDB.uid')
->select('cardsDB.name', 'deckCardsDB.card_quantity', 'cardsDB.manaCost', 'cardsDB.cmc')
->where('deckOverviewDB.username', '=', $username)
->where('deckOverviewDB.deck_uid', '=', $deckUid)
->where('deckCardsDB.board', '=', 0)
->where('cardsDB.cmc', '!=', '')
->get();
$ratio = [];
$ratio['cmc'] = 0;
$ratio['{W}'] = 0;
$ratio['{U}'] = 0;
$ratio['{B}'] = 0;
$ratio['{R}'] = 0;
$ratio['{G}'] = 0;
$ratio['{n}'] = 0; // colorless (does not count {X})
foreach($query as $card) {
$cmc = $card->cmc;
$W = substr_count($card->manaCost, '{W}');
$U = substr_count($card->manaCost, '{U}');
$B = substr_count($card->manaCost, '{B}');
$R = substr_count($card->manaCost, '{R}');
$G = substr_count($card->manaCost, '{G}');
$n = ($cmc - $W - $U - $B - $R - $G);
$ratio['cmc'] += $cmc * $card->card_quantity;
$ratio['{W}'] += $W * $card->card_quantity;
$ratio['{U}'] += $U * $card->card_quantity;
$ratio['{B}'] += $B * $card->card_quantity;
$ratio['{R}'] += $R * $card->card_quantity;
$ratio['{G}'] += $G * $card->card_quantity;
$ratio['{n}'] += $n * $card->card_quantity;
}
return $ratio;
}
Вы можете немного изменить свою функцию, чтобы принимать массив вместо целого числа, рассмотрим:
$deckIds = [];
foreach($communityDecks as $deck) {
$deckIds[] = $deck->deck_uid;
}
$ratios = $this->getColorRatioForDeck($deck->username, $deckIds);
Тогда ваша функция:
public function getColorRatioForDeck($username, array $deckUids) {
// get the corresponding deck information to calculate color ratio
$query = DB::table('auth.users_deck_overview as deckOverviewDB')
->leftJoin('auth.users_deck_cards as deckCardsDB', 'deckOverviewDB.deck_uid', '=', 'deckCardsDB.deck_uid')
->leftJoin('mtg_cards.cards as cardsDB', 'deckCardsDB.card_uid', '=', 'cardsDB.uid')
->select('cardsDB.name', 'deckCardsDB.card_quantity', 'cardsDB.manaCost', 'cardsDB.cmc')
->where('deckOverviewDB.username', '=', $username)
->whereIn('deckOverviewDB.deck_uid', $deckUids) // <-- changed comparison
->where('deckCardsDB.board', '=', 0)
->where('cardsDB.cmc', '!=', '')
->get();
Возможно, вам придется изменить остальную часть вашего getColorRatioForDeck
функция, чтобы учесть тот факт, что вы сейчас возвращаете несколько записей, я не уверен, но есть пример.
Других решений пока нет …