Jak na výpočet a zobrazení věku dle data narození?

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

Zdravím,
řeším teď takovou maličkost. Na základě data načteného z databáze potřebuji vypočítat a zobrazit věk. Je nějaká možnost jak to jednoduše udělat v šabloně?

Marek Šneberger
Člen | 130
+
+1
-

Proč bys to počítal až v šabloně, když ti to může spočítat rovnou databáze? Pokud teda nepoužíváš entity.

Pavel Kravčík
Člen | 1196
+
+3
-

Proč bys to počítal až v šabloně, když ti to může spočítat entity, pokud teda používáš entity.

Croc
Člen | 270
+
0
-

No dříve jsem věk počítal přímo v DB. Měl jsem vytvořený View a v něm jsem měl věk. Ale teď s Nette jsem zatím View nepotřeboval. Tak mě zajímalo jestli to nějak nelze v šabloně.

Co tím máte kontrétně na mysli?

Editoval Croc (19. 5. 2015 10:30)

David Matějka
Moderator | 6445
+
0
-

Pokud v sablone, tak pomoci vlastniho filtru

leninzprahy
Člen | 150
+
0
-

filtr třeba…

$template->addFilter('age', function (\DateTime $date) {
    return floor((time() - $date->getTimestamp()) / (60 * 60 * 24 * 365.24219));
});
Croc
Člen | 270
+
0
-

Nutně v šabloně to být nemusí. Chtěl jsem zjistit jestli to v šabloně jde nějak elegantně, popřídě nějak jinak. Poté bych si vybral jak to udělat.

Co bylo myšlenou tím entity?

Oli
Člen | 1215
+
0
-

ORM. Entita je třída, která drží stav nějakého objektu, který je typicky natažený z databáze. Takže můžeš mít třeba třídu User, která má property name, age, address, … no a z databáze se to všechno vytáhne a namapuje na tu třídu. Ty potom teda voláš například (new User)->setName('Pepa')->setAddress('Z depa'). Prostě pracuješ s databází jako s objekty.

Pro tebe bude asi nejjednodušší počítat to v db. Pokud to budeš potřebovat častěji, tak si napsat ten filter.

Šaman
Člen | 2666
+
+1
-

Počítat to v db není dobré, pokud k tomu nemáš hodně dobrý důvod (třeba že bys podle věku chtěl řadit už na urovni db – to lze ale obejít řazením podle data narození). Není dobré drobit výpočty, takže pokud máš všechno v modelu, měj tam opravdu všechno.

Nette na to má filtry. Pokud používáš ORM, tak ten věk vrací už samotná entita. A pokud bys nechtěl použít ani jedno z toho, pořád si můžeš napsat nějakou pomocnou třídu se statickou metodou countAge($birthDate), případně třeba i isBirthday(birthDate), pokud bys takovou informaci potřeboval.

Croc
Člen | 270
+
0
-

Díky za rady.

Jinak ono to bude trochu „složitější“ funkce, než jen vypočítání věku. Potřeboval bych na vstupu 2 parametry.

Výstup by byl:

  1. Dostupné oba datumy – počet let/měsíců mezi.
  2. Pouze jeden datum – počet let/měsíců mezi k aktuálnímu datu.
  3. Pokud v bodu 2 bude věk větší než X, vrátí prázdný řetězec.

Toto bude využíváno na více místech, takže by použití filtru nebylo špatné.

Když budu mít vlastní filtr age, budu moci zapsat toto? (v některých případech bude date2 NULL:

Věk: {$owner->date1|age:$owner->date2}

Editoval Croc (19. 5. 2015 14:08)

Šaman
Člen | 2666
+
0
-

IMHO už na tohle filtry nejsou vhodné. Filtr slouží ke zformátování hodnoty při výpisu, nikoliv pro nějaké složitější výpočty.
Na tohle ideálně tu entitu (a nebo vlastní datový objekt, nebo použít DateInterval) a filtr použít jen pro zformátování intervalu do požadovaného formátu

Croc
Člen | 270
+
0
-

Pravda. Tím tu vzniká otázka, jaké ORM k Nette použít?

Editoval Croc (19. 5. 2015 15:23)

David Matějka
Moderator | 6445
+
+1
-

@Croc nevznika, doctrine je jasna volba ;)


Jinak myslim, ze v tomhle pripade jsou filtry jeste OK

Šaman
Člen | 2666
+
0
-

No, nevím, v jakém stavu ten projekt je. Nebudeš kvůli tomu přepisovat už hotový :)
Takže bych si do šablony předal jen ten objekt DateInterval (nebo ho v nejhorším v té šabloně i vytvořil z dostupných dat) a ten pak při výpisu prohnal filtrem. Ono se tomu říká filtry, ale ve skutečnosti jsou to spíš formattery.

Croc
Člen | 270
+
0
-

Projekt je na začátku, takže ideální stav. Navíc pokud je to opravdu pomocník, tak se v budoucnu bude určitě hodit.

Díky moc za tipy. Jdu kouknout na Doctrine :)

David Matějka
Moderator | 6445
+
+1
-

@Croc pro integraci do nette pouzij kdyby/doctrine :)

Šaman
Člen | 2666
+
0
-

Ještě než se na ni vrhneš, tak to ještě zvaž a přečti třeba tohle. Na malé projekty mi NDb stačí, na větší jsem doteď používal LeanMapper, ale už bych šel taky do Doctrine. Pravé entity jsou super. Ale je to hodně studia a práce a ladění navíc. Měl bys už předem vědět, proč ji chceš. Jinak na ni jen zanevřeš (jako už mnoho programátorů před tebou – i několikrát po sobě :) ).

Croc
Člen | 270
+
+2
-

Tak jsem si přečetl výše zmíněnou diskuzi a cca 7 článků na zdrojáku a rozhodl jsem se že do Doctrine nejdu a ani do žádného ekvivalentu. V tomto zůstanu pouze u Nette.

Editoval Croc (24. 5. 2015 17:49)

Croc
Člen | 270
+
0
-

leninzprahy napsal(a):

filtr třeba…

$template->addFilter('age', function (\DateTime $date) {
    return floor((time() - $date->getTimestamp()) / (60 * 60 * 24 * 365.24219));
});

Díky za typ. Kde je nejlepší místo, kam tyto vlastní filtry umístit? A opravdu stačí jen uvedený kód na definici svého filtru?

hrach
Člen | 1838
+
0
-

@Croc ja samozrejme doporucuji nextras/orm :)

Editoval hrach (2. 6. 2015 10:12)

Azathoth
Člen | 495
+
+4
-

já bych doporučil doctrine :)

leninzprahy
Člen | 150
+
0
-

Croc napsal(a):

Díky za typ. Kde je nejlepší místo, kam tyto vlastní filtry umístit? A opravdu stačí jen uvedený kód na definici svého filtru?

Nejjednodušší je v nějakém BasePresenteru (nebo BaseControl), přetížit metodu createTemplate()

protected function createTemplate() {
	$template = parent::createTemplate();
	$template->addFilter('age', function (\DateTime $date) {
    	return floor((time() - $date->getTimestamp()) / (60 * 60 * 24 * 365.24219));
	});
	return $template;
}

viz Šablony sekce Filtry

Pokud jich budeš mít víc, je asi lepší to dát do samostatného souboru, např Filters

namespace App;

class Filters {

	public static function loader($filter) {
		return method_exists(__CLASS__, $filter) ?
				call_user_func_array([__CLASS__, $filter], array_slice(func_get_args(), 1)) : null;
	}

	public static function age(\DateTime $date) {
		return floor((time() - $date->getTimestamp()) / (60 * 60 * 24 * 365.24219));
	}

	// ... další filtry
}

a zaregistrovat v configu

services:
	latte.latteFactory:
		setup:
			- addFilter(null, [App\Filters(), loader])
Croc
Člen | 270
+
0
-

@leninzprahy – Super, díky moc. Určitě jich bude víc. Dnes na to kouknu a uvidím jak se zadaří :)