Oznámení
Lean Mapper – přidání nové „hasMany“ property do DB
před 6 lety
- svezij
- Člen | 69
Ahojte, pravděpodobně se jedná o úplně triviální otázku, ale nějak jsem na ni nenašel odpověď. Mám následovně definovanou entitu:
/**
* @property int $id
* @property string $username
* @property string $password
* @property string|NULL $name
* @property string|NULL $company
* @property string $default_resource
* @property Role[] $roles m:hasMany(:user_roles::roles)
* @property Resource[] $rights m:hasMany(:user_rights::resources)
* @property UserAction[] $history m:belongsToMany(user_id:user_actions)
*/
class User extends \LeanMapper\Entity
{
}
Dále mám formulář, kde vyplním údaje a vyberu role uživatele. Nyní bych rád zpracoval data z formuláře, což dělám následovně:
$user = new \MyNS\Entity\User();
foreach ($form->values as $key => $value) {
if ($value) {
if (Strings::startsWith($key, 'role_')) {
list($prefix, $role_id) = explode('_', $key);
// tady bych rád přidal do tabulky user_roles pár $user_id, $role_id
} else {
$user->$key = $value;
}
}
}
// add it to the database
$this->userRepository->persist($user);
Jak jsem uvedl v kódu, ve větvi podmínky, zda se jedná o roli, tak bych rád přidal do tabulky user_roles pár id uživatele / id role, ale nevím, jak na to.
Za odpověď mockrát děkuji.
Oprava:
Resp. vím, jak na to, prostě bych si ty role uložil do pole, které bych po
uložení uživatele do DB prošel a postupně vkládal přímo přes Dibi.
Ptám se ale, jestli je to možné přímo přes Lean Mapper – např.:
$user->link_role($role_id); // nebo tak nějak - prostě přímo přes entitu uživatele
Editoval svezij (12. 8. 2013 14:54)
před 6 lety
- Tharos
- Člen | 1042
Ahoj,
myslím, že hledáš přesně tohle. Bohužel je to zatím „zdokumentované“ jenom na fóru…
$user = new \MyNS\Entity\User();
foreach ($form->values as $key => $value) {
if ($value) {
if (Strings::startsWith($key, 'role_')) {
list($prefix, $id) = explode('_', $key);
$user->addToRoles($id);
} else {
$user->$key = $value;
}
}
}
$this->userRepository->persist($user);
před 6 lety
- svezij
- Člen | 69
Super, kouknu na to. Větev fóra o Lean Mapperu také čtu, ale je toho hodně, a tohoto jsem si nevšiml. Díky moc.
před 6 lety
- svezij
- Člen | 69
Opět vás šecky zdravím. Přečetl jsem si, co dalšího LeanMapper umí a
musím říct: „dobrá práce“ (nejednou mnoho „maličkostí“, které mi
velmi usnadní práci, využiji).
Možnost specifikace vlastního mapperu je super, má to téměř neomezené
možnosti, hlavně pro nasazení na starší databáze. Samozřejmě se s tím
pojilo několik problémů – laděnka na mě hned křičela, že:
- třídě
\LeanMapper\Repository
dávámDibiConnection
místoLeanMapper\Connection
- mi chybí druhý argument (instance rozhraní
IMapper
– možná by to mohl být volitelný parametr a když ho nedám, mohla by se načíst instance třídyLeanMapper\DefaultMapper
) - neexistuje entita
Users
– tady mě trochu zaskočilo, že už to nevychází z názvu repozitáře, ale z názvu tabulky, tudíž mě to donutilo implementovat metodugetEntityClass($table, LeanMapper\Row $row = NULL)
– nebylo by dobré, abych měl v Mapperu možnost získat název třídy repozitáře? Není náhodou už teď nějaká možnost specifikovat název entity přes anotaci repozitáře? - atd.
Všech těchto „malých“ problémků jsem se zbavil, ale zůstal jeden,
se kterým si nevím rady. Týká se kódu, který jsme společně
s Tharosem řešili výše. Zavolám-li tohle (bez
„dočasného“ persist($user)
):
$user = new \MyNS\Entity\User();
foreach ($form->values as $key => $value) {
if ($value) {
if (Strings::startsWith($key, 'role_')) {
list($prefix, $id) = explode('_', $key);
$user->addToRoles($id);
} else {
$user->$key = $value;
}
}
}
$this->userRepository->persist($user);
laděnka vyhodí výjimku
Call to a member function getTable() on a non-object
File: ...\libs\LeanMapper\tharos\leanmapper\LeanMapper\Entity.php Line: 656
656: $table = $this->mapper->getTable($this->getCurrentReflection()->getName());
případně tohle (s „dočasným“ persist($user)
):
$user = new \MyNS\Entity\User(array('sloupec' => 'docasna hodnota'));
$this->userRepository->persist($user); // "dočasné" `persist($user)`
foreach ($form->values as $key => $value) {
if ($value) {
if (Strings::startsWith($key, 'role_')) {
list($prefix, $id) = explode('_', $key);
$user->addToRoles($id);
} else {
$user->$key = $value;
}
}
}
$this->userRepository->persist($user);
laděnka vyhodí výjimku
Argument 3 passed to LeanMapper\Row::createReferencingDataDifference() must be an instance of LeanMapper\Filtering, string given, called in D:\nette\libs\LeanMapper\tharos\leanmapper\LeanMapper\Entity.php on line 391 and defined
File: ...\libs\LeanMapper\tharos\leanmapper\LeanMapper\Row.php Line: 231
231: public function createReferencingDataDifference($table, $viaColumn = null, Filtering $filtering = null, $strategy = null)
Za pomoc znovu mockrát děkuji.
před 6 lety
- Tharos
- Člen | 1042
@svezij:
- mi chybí druhý argument (instance rozhraní
IMapper
– možná by to mohl být volitelný parametr a když ho nedám, mohla by se načíst instance třídyLeanMapper\DefaultMapper
)
Implicitně vytvářet DefaultMapper
se samozřejmě nabízí,
ale v duchu DI by to nebylo optimální. Repository
je prostě
závislé na instanci IMapper
a musí ji zvenčí dostat.
- neexistuje entita
Users
– tady mě trochu zaskočilo, že už to nevychází z názvu repozitáře, ale z názvu tabulky, tudíž mě to donutilo implementovat metodugetEntityClass($table, LeanMapper\Row $row = NULL)
– nebylo by dobré, abych měl v Mapperu možnost získat název třídy repozitáře? Není náhodou už teď nějaká možnost specifikovat název entity přes anotaci repozitáře?
Nad repositářem může být anotace @table
, která určí, se
kterou (hlavní) tabulkou pracuje. Je pak úkolem mapperu přeložit to na
správnou entitu (getEntityClass
). Funkce pro získání názvu
třídy repositáře by IMHO měla jen velmi malé využití.
Možnost specifikovat název entity v anotaci byla, ale odstranil jsem ji, protože to nebylo dotažené do všech důsledků a hlavně vlastní mapper tohle celé řeší mnohem lépe (a hlavně napříč celou aplikací).
Všech těchto „malých“ problémků jsem se zbavil, ale zůstal jeden, se kterým si nevím rady. Týká se kódu, který jsme společně s Tharosem řešili výše. Zavolám-li tohle (bez „dočasného“
persist($user)
):
Zkus prosím update na aktuální develop
, mělo by to být
fixnuté. Stále ale platí omezení (o kterém jsem psal), že takhle pracovat
je možné pouze s entitami, které „jsou attached“.
před 6 lety
- svezij
- Člen | 69
Výborně, výborně – funguje přesně tak, jak jsem si přál :-). Děkuji, jen tak dál ;-)