Nette + Doctrine2 + Gedmo

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
akadlec
Člen | 1326
+
0
-

Tak ono když se hodně zobecní ten pohled na gedmo, tak to jsou v podstatě jen pověšené eventy ne? Takže stačilo by to přepsat třeba na hosiplanovo rozšíření Kdyby\Events. Výjimkou jsou akorát tree, translatable a tuším versionable.

Dočasný fix pro tree nějaký mám, postoval jsem to v #42. Teď jsem si všechny modely přehodil na Kdyby\Doctrine a zkouším to používat dle hosiplana a s tím je spojeno přepsání repositářů pro tree a translatable.

Tomáš Votruba
Moderator | 1114
+
0
-

Pokud byste chtěli přesunout nastavení jazyka z presenteru extension, koukněte sem

Klainer
Člen | 42
+
0
-

Dobrý den,
snažím se rozjet Gedmo Translatable, na Kdyby Doctrine. V zásadě mi všechno funguje, jen jsem narazil na malé problémy a mám ještě pár dotazů. Gedmo jsem již používal bez Kdyby a tam mi vše fungovala tak jak má.

Co mi tedy nefunguje, je překlad do jiného jazyka než je v základu nastaven. Jelikož jsem chtěl Gedmo translatable propojit s Kdyby\Translations vytvořil jsem si listener a zaregistroval ho v neonu. Teď když v url zadám parametr (en,de,cs) se mi automaticky mění překlady statické a zároveň se nastaví listener pro načítání dat z DB v daném jazyku.

translatableListener:
    class: \Fibit\TranslatableListener
    tags: [kdyby.subscriber]

Toto vše zatím funguje. mám entitu article:

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Gedmo\Translatable\Translatable;

/**
 * @ORM\Entity
 */
class Article extends \Kdyby\Doctrine\Entities\BaseEntity implements Translatable
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue
     */
    public $id;

    /**
     * @Gedmo\Translatable
     * @ORM\Column(type="string")
     */
    protected $title;

    /**
     * @Gedmo\Locale
     * Used locale to override Translation listener`s locale
     * this is not a mapped field of entity metadata, just a simple property
     */
    protected $locale;

    public function setTranslatableLocale($locale)
    {
        $this->locale = $locale;
    }
}

A již existující vložený článek v DB, načtu si ho a chci do něj přidat překlad do němčiny:

		// http://127.0.0.1:8099/app/admin/de
		// a tohle se mi zavolá v presenteru metode (startup) - jen pro test
		$articles = $this->em->getDao(\App\Entity\Article::getClassName());
		$articleT = $articles->findOneBy(['id' => 5]);
		$articleT->setTranslatableLocale('de'); // change locale
		$articleT->setTitle('my name in de');
		$articles->save();

Přitom se mi vyhodí exception:

Doctrine\ORM\Query\QueryException
Invalid parameter number: number of bound variables does not match number of tokens search►

Prosím o radu, jak správně ukládat překlady v kombinaci těchto použitých technologií, nebo o vysvětlení zda něco dělám špatně.

Dále by mě zajímalo jestli se opravdu oplatí používat GEDMO Translatable a to hlavně z hlediska zátěže na serveru. Našel jsem i jiné řešení překladu viz: https://github.com/…ineBehaviors

Které používáte vy ?

Děkuji za odpověď.

Tomáš Votruba
Moderator | 1114
+
0
-

Prave Gedmo ma dotazy 1:m, Knp ma 1:1. Po pouzovani obou doporucuji Knp.

Pokud bys necemu v dokumentaci nerozumel, ptej se.

Jiří Nápravník
Člen | 710
+
0
-

Používal jsem donedávna Gedmo, protože KNP jsem neznal, ja kjsem ho našel, tak jsem začal používat to. Hlavně proto, že mi přijde i čistší a vyvíjí se pořád, Gedmo moc aktivity nemá.

Jediné co mi vadí, že má celkem odfláknuté stromové strukturu, jen materialized path, nested set mi tam dost chybí.

akadlec
Člen | 1326
+
0
-

takže přejít nebo ne? ;)

jinak teda dokumentace žádná pro to knp? Osobně bych využil:

translatable
timestampable
blameable
loggable
sluggable

a pokud dobře chápu, tak ty překlady jsou jinak než gedmo? Takže jedna extra tabulka kde budou jen překlady? třeba category_translation kde budou sloupce jako category_name, category_description a lang ci tak neco?

Editoval akadlec (1. 7. 2014 9:55)

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec Přejít! Dokumentace je stručně v readme, konkrétně v testech.

Translatable a Timestampable používám.
Překlady chápeš naprosto správně.

Editoval Tomáš Votruba (1. 7. 2014 13:48)

akadlec
Člen | 1326
+
0
-

sakra a mě se to gedmo tak libilo že jsem ho narval do všech modulů ;) tak zase refactor no ;) jinak dokumentace je dle mě ještě horší než nettí ;)

E: ovšem totok se mě docela dost nelibí, aby mě to nutilo používat „jejich“ property. V gedmo si pomocí anotace jednoduše určím co a jak.

E2: a ty překlady pak ziskaváte nějak takto? :

$category->getTranslation()->getName();

Editoval akadlec (1. 7. 2014 15:16)

Tomáš Votruba
Moderator | 1114
+
0
-

Právě jsem do Zenify\DoctrineBehaviors doplnil zbytek rozšíření. Kdyby něco, hlaste do issues.

@akadlec Mně se tato konvence naopak líbí a dává mi smysl. Největší přínos vidím v lehkosti knihovny a entity při zachování featur.

Jiří Nápravník
Člen | 710
+
0
-

@akadlec mě se teda Gedmo nelíbilo nikdy, jen jsem ho bral jako nutné zlo:-) Tohle je jednoduché bezproblémové. konvence může štvát, ale nevidí mv tom nějaký větší problém, když ty názvy stěží vymyslím lépe.

@TomášVotruba Zrovna včera jsem si napsal vlastní extension pro Knp, teď nevím jestl is inechat svojí, nebo přejít na tvojí:-)

Tomáš Votruba
Moderator | 1114
+
0
-

Tak tak, Gedmo je za trest :).

@JiříNápravník Pokud nemá rozdíly, přejdi na moji. Případně pošli PR. Plánuji dlouhodobě podporovat a už jsem poslal i Nette\Object opravný PR do KnpLabs.

Máš ji někde dostupnou online?

Jiří Nápravník
Člen | 710
+
0
-

@TomášVotruba Nette\Object jsem prave vcera taky resil, pak jsem jen aktualizoval:-) Online ji zatim nemam. Rozdil je jediny v podstate, ja to mam jako jednu extension a zapinam v configu podobně jako ma rixxi/gedmo v pripade gedmo

Tomáš Votruba
Moderator | 1114
+
+1
-

@JiříNápravník Kdysi to psal @FilipProcházka a já s tím souhlasím, že Gedmo by mělo být rozděleno do samostatných repozitářů. Zkoušet to míchat (a že jsem to zkoušel) do jednoho komplikuje správu a vývoj. Obdobně jako Nette před a po rozbalíčkování.

Proto jsem zvolil tuto cestu, přidáš si co potřebuješ a nemusíš řešit konfiguraci. Buď máš 6 řádků v extensions, nebo 1 v extensions a 7 v namespace toho rozšíření.

Jiří Nápravník
Člen | 710
+
0
-

@TomášVotruba Mě přijde logičtější pokud je to jeden balík (DoctrineBehaviors) mít to jako jedno rozšíření než až sedm či kolik různých. Ale tak jako tak je to podle mě jen implementační detail.

akadlec
Člen | 1326
+
0
-

no a ty překlady získáváte tak jak jsem se ptal? nebo jinak?

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec Editace jsem se nevšmil, bo jsem už odpověděl.

Stačí jako jakoukoliv jinou property:

$category->name

Editoval Tomáš Votruba (2. 7. 2014 9:13)

akadlec
Člen | 1326
+
0
-

hmm tak to se mě začíná líbit více. takže na venek to vystupuje jako jedna entita ? No možná tomu dám šanci ;)

jinak ale jako @Jiří Nápravník, nějak se mě nezdá to tvoje rozdělení na X extensions, stejnak je máš v jednom balíčku. Raději bych to viděl jako jednu s možností přes config on/off

Editoval akadlec (2. 7. 2014 10:41)

akadlec
Člen | 1326
+
0
-

Ale co tam nějak pořád nemůžu překousnout jsou ty traity…pokud nevložím do entity:

class Article
{
    use Knp\DoctrineBehaviors\Model\Timestampable\Timestampable;
}

tak prostě timestampable nebude fungovat a nechci tam tu traitu vkládat v tom tvaru jaký diktuje KNP protože potřebuju dodržet konvenci názvů sloupců, takže musím mít v property taky zadefinován název sloupce v DB, což samo v knp není a bere se automaticky createdat a updatedat Tady v tomto se mě více líbí přístup GEDMa, kde se to určilo anotací že tato property bude to a to.

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec On/off jsem zkoušel již u Doctine\Extensions a spíše mě to mátlo. Zejména když jsem chtěl u jednotlivých listenerů něco konfigurovat. Tyto featury navíc spolu nijak nesouvisí. Co z toho vznikne za chaos, když se šetří repositáři, je vidět krásně u Gedma.

Osobně bych doporučil použít jako první Translatable, tam je přínos největší.

Pokud potřebuješ Timestampable sloupce řešit zcela po svém, otevři si traitu a přesuň si její obsah do své entity s upravenými názvy property/getterů/setterů. Něco podobného mám u překladů, kde mám locale jako id entity.

Jiří Nápravník
Člen | 710
+
0
-

@akadlec On/off jsem zkoušel již u Doctine\Extensions a spíše mě to mátlo. Zejména když jsem chtěl u jednotlivých listenerů něco konfigurovat. Tyto featury navíc spolu nijak nesouvisí. Co z toho vznikne za chaos, když se šetří repositáři, je vidět krásně u Gedma.

@TomášVotruba Nějak nechápu tvé pojetí slova „repozitář“, KNP je přece taky jako jeden repozitář, jeden composer balík, i Zenify\DoctrineBehaviors je jeden repozitář/composer balík.

Uznávám, že v případě konfigurace je to celkem bordel. KNP umožňuje konfigurovat vše od trait až po listenery, ale většinou to asi nikdo dělat nebudeme:-)

Filip Procházka
Moderator | 4668
+
0
-

@akadlec můžeš si udělat například listener, který ti ke všem sloupcům opraví jak se mají jmenovat v databázi (tedy přepíše @Column(name=""))

akadlec
Člen | 1326
+
0
-

@Tomáš Votruba no moc tě teď nechápu, vidím to jako @JiříNápravník máš to jako jedno repo, kdyby si to rozdělil na jednotlivá repa tak budiž ale takto?

@FilipProcházka no to pak můžu rovnou celé implementovat po svém že ;) co sem koukal na samotné KNP tak to jsou jen listenery.

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec @JiříNápravník Nesrovnávám knihovny mezi sebou, jen jsem pro rozbalíčkování ve stylu Nette. Minimem, co mohu sám udělat, je použití samostatných extension pro něco, co bych sám udělal jako balíček. Pokud by Gedmo prošlo stejným procesem jako Nette, nejspíš by se dostalo do stavu, kdybych jej rád používal. Ale nevypadá to.

@akadlec Pokud potřebuješ Timestampable z Gedma, tak jej použij. Já z Gedma používám Tree.

Editoval Tomáš Votruba (2. 7. 2014 17:14)

akadlec
Člen | 1326
+
0
-

sice nesrovnáváš knihovny ale srovnáváš to s rozdělením nette a přitom to máš jako jedno repo což si tak trochu protiřečí ;)

Tomáš Votruba
Moderator | 1114
+
0
-

@akadlec Kdybych říkal, že rozdělím Gedmo, a byl jeho vlastníkem, tak bych si protiřečil, to jo :). Má knihovna je pouze port do Nette, který do určité míry musí respektovat původní strukturu. To, že jsou cizí knihovny nějak strukturovány neovlivním. Nette port není.

Editoval Tomáš Votruba (2. 7. 2014 19:17)

Jiří Nápravník
Člen | 710
+
0
-

@TomášVotruba souhlasím, že zrovna Gedmu by prospělo, kdyby se rozdělilo, je to orpavdu velký moloch a když někdo potřebuje jen stromy, tak tam k tomu přibalovat vše je nesmyslné. U toho KNP v takovém stavu jako je teď, kdy je to co Behavior to jedna dvě třídy mi to nijak nevadí. Na KNP mi vadí právě to, že tam nejsou nested set, a budu si je muset nejspíše dopsat sám (protože přibalovat si gedmo kvůli tomu nechci)

akadlec
Člen | 1326
+
0
-

ale zase u gedma je positivem že neumřelo a přebral to někdo jiný a je konečně jako composer package.

Tomáš Votruba
Moderator | 1114
+
0
-

@FilipProcházka Jak vůbec na to? Snažím se teď změnit nullable=true na nullable=false.
Mám $classMetadata a $reflection.

Filip Procházka
Moderator | 4668
+
0
-

Tady to můžeš přepsat, ale lepší bude asi použít setAttributeOverride

Tomáš Votruba
Moderator | 1114
+
0
-

@FilipProcházka Parada, slape to.

cubic
Člen | 45
+
0
-

Když je tady řeč o Gedmo / KnpLabs, můžu poprosit o radu, pokud jste někdo řešil podobnou situaci?

Mám projekt, je to několik e-shopů (může to být lokalizace jednoho do víc jazyků a nebo úplně jiné vedle sebe), které běží na společné DB, prodávají shodné produkty. Existuje něco jako centrální admin, kde spravuju všechny produkty (entita Product). Pak se ale můžu přepnout do editace pro jednotlivý shop a přepsat si lokálně třeba titulek, url, perex – ať už kvůli jazykovým mutacím a nebo jen kvůli SEO (ProductTranslation).

U některého produktu můžu změnit na shopu A jen titulek a url, u jiného třeba perex. Co není změněné, to potřebuju brát z hlavní entity Product.

Gedmo na tohle má nastavení fallback, kde využívá SQL funkci coalesce(col1, col2), ta vrací v mém případě první nenulovou hodnotu z produktů a překladů.

Gedmo Translatable jsem použil jednou a stačilo mi to, zařekl jsem se, že nikdy více. Teď potřebuju řešit tuhle situaci, nakonec to dopadlo tak, že jsem se inspiroval v Gedmu a podědil \Doctrine\ORM\Query\SqlWalker a napsal si vlastní třídu, která dělá to samé, ale efektivněji.

Zatím nemám ukládání samotných překladů do ProductTranslation (podobně jako KnpLabs) a nevím, jestli nad tím ztrácet čas a nebo existuje něco funkčního a otestovaného v praxi, co by splnilo mé požadavky. Hledal jsem a nic nenašel a KnpLabs to neumí, pokud nejsem slepý..