Problém se zobrazením query v latte

zeddosx
Člen | 3
+
0
-

Zdravím, snažím se z databáze dostat do tablu týmy z následujících tabulek (teams¨: id, name) k nim se snažím přiřadit členy týmu (members: id, teamid, racerid) a jejich jména se berou z tabulky závodníků (racers: id, firstname, lastname, type). V „čistém php“ jsem tohoto efektu již docílil, pomocí 3 foreach loopů, a teď se snažím replikovat tento efekt v nette. Z nějakého důvodu se mi vykreslí pouze bloky tablu, ale jména se v nich již nezobrazí. Je možné v nette něco takového udělat, nebo se na to musí jinak?

<?php
namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;


class TeamsPresenter extends Nette\Application\UI\Presenter
{
	private Nette\Database\Explorer $database;

	public function __construct(Nette\Database\Explorer $database)
	{
		$this->database = $database;
	}

	public function renderDefault(): void
    {
	$this->template->teams = $this->database->fetchAll('SELECT * FROM teams ORDER BY id');
	$this->template->types = $this->database->fetchAll('SELECT * FROM types');

	foreach($this->template->teams as $team)
	{
	foreach($this->template->types as $type)
	{
		$this->template->members = $this->database->fetchAll('SELECT b.firstname, b.lastname FROM members a JOIN racers b ON b.id = a.racerid WHERE a.teamid = ? AND b.type = ?', $team->id, $type->id);
		bdump($this->template->members);
	}
    }
}
}

<table class="table">
  <thead class="thead-dark">
    <tr>
      <th scope="col">#</th>
      <th scope="col">Tým</th>
      <th scope="col" n:foreach="$types as $type" >{$type->name}</th>
    </tr>
  </thead>
  <tbody>
    <tr n:foreach="$teams as $team">
      <th scope="row">{$team->id}</th>
      <td>{$team->name}</td>
      <td n:foreach="$types as $type">
      <p n:foreach="$members as $member">{$member->firstname} {$member->lastname}</p>
      </td>
    </tr>
  </tbody>
</table>
David Matějka
Moderator | 6445
+
+1
-

V tom foreachi stále zapisuješ do members, takže tu hodnotu přepisuješ a do šablony se pošle z poslední iterace. Pokud bys to chtěl řešit takhle, musíš si zkonstruovat dvourozměrné pole:

$members = [];
foreach($this->template->teams as $team)
	{
	foreach($this->template->types as $type)
	{
		$members[$team->id][$type->id] = $this->database->fetchAll('SELECT b.firstname, b.lastname FROM members a JOIN racers b ON b.id = a.racerid WHERE a.teamid = ? AND b.type = ?', $team->id, $type->id);
		bdump($this->template->members);
	}
    }
$this->template->members = $members;

a v šabloně pak přes tohle iterovat n:foreach="$members[$team->id][$type->id] as $member"

ale existuje ti tam výkonnostní problém, tvůj kód vygeneruje m*n dotazů – tedy pokud budeš mít 5 typů a 100 teamů, tak ti to pošle 500 dotazů. Můžeš to třeba vyřešit ručně, že pošleš jeden dotaz s team_id IN ($ids) AND type_id IN ($ids) a pak zkonstruuješ to dvourozměrné pole. Ale vzhledem k tomu, že nijak nefiltruješ teamy ani typy, tak je zbytečné filtrovat i ty membery. takže si prostě vyber vše z té tabulky memberů a vytvoř to pole.

další možnost je, že bys použil Nette Database Explorer, který zvládne některé optimalizace dotazů.
V šabloně bys měl (pokud jsem správně pochopil strukturu db) pak něco jako:

{foreach $team->related(members)->where(type, $type->id) as $member}{$member->racer->firstname}{/foreach}
zeddosx
Člen | 3
+
0
-

Super, to dvourozměrné pole funguje. Děkuji za pomoc.