Spojení dvou tabulek (opak ref)
- thorewi
- Člen | 84
Zdravim,
dejme tomu ze mam tabulku user se sloupci id, email, password, pak mam tabulku userdata se sloupci user_id, firstname, surname a useradata2 se sloupci user_id, address, city.
A potreboval bych nejdrive spojit user s userdata. Vim ze muzu pouzit
$user->related('userdata')->fetch()
ale to mi vybere jen data z druhe tabulky. Data z obou tabulek sice muzu vybrat takto:
$user->related('userdata')->select('user.*, userdata.*')->fetch()
ale zase pak nemuzu uz pouzit related na userdata2.
Chtelo by to neco co mi provede
SELECT user*, userdata.* FROM user INNER JOIN userdata ON user.id = userdata.user_id
a nevrati Row ale ActiveRow.
Delam neco spatne?
- enumag
- Člen | 2118
Ano, špatně to používáš. Znovu vybírat user.*
nepotřebuješ, protože to již máš v $user. Obdobně data z tabulky
userdata2 (doporučuji přejmenovat) máš získat druhým voláním
related.
$data = $user->related('userdata2'); //vrátí Selection, pro zpracování použij foreach
Editoval enumag (22. 10. 2012 7:46)
- thorewi
- Člen | 84
Omlouvam se, to $user jsem tam dal jen pro zjednodušení, ve skutečnosti ho nemám, zasílám celou funkci:
public function getOne($id) {
$user = $this->connection->table('users')->get($id);
if($user->role == 'client' || $user->role == 'tutor') {
return $user->related($user->role)->select("user.*, $user->role.*")->fetch();
}
return $user;
}
Z tohoto lze videt ze ty pomocne tabulky se jmenuji tutor nebo client a ja je chci spojit s tabulkou user podle toho, jakou ma uzivatel roli.
- petr.pavel
- Člen | 535
Nemůžeš použít $user->related()
, protože jak pravil
enumag, $user není Selection.
Řešení 1:
public function getOne($id) {
$user = $this->connection->table('users')->get($id);
if (!in_array($user->role, array('client', 'tutor'))) {
return $user;
}
return $this->connection->table('users')->where('id', $id)
->related($user->role)->select("user.*, $user->role.*")->fetch();
}
Řešení 2: (ušetříš opakovaný dotaz do users
)
public function getOne($id) {
$user = iterator_to_array($this->connection->table('users')->get($id));
if (!in_array($user['role'], array('client', 'tutor'))) {
return $user;
}
$role = $this->connection->table($user['role'])->where('user_id', $id)->fetch();
$user = array_merge($user, iterator_to_array($role));
return $user;
}
Kdyby ti vadilo, že vrací pole, můžeš zkusit přetypovat na objekt
přes return (object) $user;
- thorewi
- Člen | 84
Nechapu prvni vete – vsak related se pouziva na ActiveRow ne, takze proc bych to nemohl pouzit?
Jinak k tvemu reseni – presne takove jsem mel (reseni cislo 2), ale pak jsem si uvedomil ze chci vracet object, tak jsem to pretypoval na object… Pak jsem si uvedomil ze bych s tim rad pracoval jako s polem i jako s objektem, tak jsem to pretypoval na ArrayHash. A pak jsem si uvedomil, ze pozdeji na to potrebuju jeste pouzivat to related, takze jsem hledal reseni ktere mi vrati ActiveRow.
- petr.pavel
- Člen | 535
Ach jo, máš pravdu, napsal jsem úplnou blbost (řešení 1) a navíc jsem tvůj původní dotaz nečetl moc pozorně. Příště se pořádně vyspím, než budu radit. Soráč.
- enumag
- Člen | 2118
@thorewi: Základní nesmysl v té tvé funkci je, že related vrátí Selection, což je množina řádků, a ty to pomocí fetch() omezuješ na jeden. To je omluvitelné pouze pokud víš že dostaneš jen jeden (např. FK je unikátní) nebo pokud ti stačí libovolný. V obou případech je vhodné přidat před fetch ještě ->limit(1).
No a co s tím teda? Tohle se dělá úplně jednoduše, z té funkce prostě vrať $user (vždy) a to related volej až tam, kde ta data reálně potřebuješ. Tzn. roli kontroluj také až tam.