Nette/Forms – addDatetime smazatelný?
- Pavel Kravčík
- Člen | 1195
My jsme to v našem rozšíření dělali tak, že jsme dědili
TextBase
kvůli nullable
, akorát ve
forms: 3.1.13
už to takhle snadno nepůjde.
- David Grudl
- Nette Core | 8227
Je fakt, že podpora color už je napříč prohlížeči plná, tak ho přidat můžu.
- m.brecher
- Generous Backer | 871
@DavidGrudl
Prosím doplnit do nových DateTimeControl prvků (addDate(), addDateTime(), addTime()) automatickou hodnotu setOption(‚type‘, ‚datetime‘). Všechny existující formulářové prvky mají hodnotu ‚type‘ automaticky nastavenu.
Já tato option používám pro nastavení custom css tříd ve formulářích:
$class = $component->getControl()->getAttribute('class');
$class .= $class ? ' ' : '';
$class .= match($component->getOption('type')){
'text', => 'text-input block-input',
'increment', => 'increment-input block-input',
'datetime' => 'date-input block-input', // toto option nyní chybí
'textarea' => 'text-area-input block-input',
'select' => 'select-input block-input',
'checkbox' => 'checkbox',
'radio' => 'radio',
'file' => 'upload-input',
'dialogButton' => 'submit-button',
'button' => $component instanceof SubmitButton
? 'submit-button'
: 'control-button',
default => '',
};
- evromalarkey
- Nette Blogger | 20
@DavidGrudl vesměs u všech input typů by měla být dobrá podpora
v prohlížečích až na week
a month
, viz. https://developer.mozilla.org/…lement/input#…, ale ty se
dají přípaně polyfillovat
- m.brecher
- Generous Backer | 871
@PavelKravčík
My jsme to v našem rozšíření dělali tak, že jsme dědili TextBase kvůli nullable
To by mě docela zajímalo, jaké potíže jste měli s nullable ve formulářích ?? Formuláře Nette vracejí pro nevybranou hodnotu (nullable) prázdný řetězec, což je v souladu s html normami. Nullable problémy začínají v okamžiku, kdy jdeme ukládat nullable data do databáze. Kupříkladu, když chci uložit '' do MySQL tabulky do sloupce typu int, který je nullable, obdržím chybovou hlášku „Incorrect integer value“, což je správně, protože jsem měl ukládat null. Stejný problém vyvstane, když půjdu uložit „nullable“ hodnotu '' z html inputu datetime-local, který když není vybráno datum vrací '';
Také jsem zkoušel tento problém fixovat přímo ve formulářovém custom inputu, který jsem si pro Date/DateTime udělal, protože v Nette chyběly. Custom input vracel místo "" hodnotu null. Ono to takto funguje. Jenže jsem došel k názoru, že je to nesprávný postup a jediné správné místo, kde by se mělo řešit nastavení nullable hodnot je databázová knihovna.
Téma ukládání nullable do databáze je ale OT tohoto vlákna a tak na toto téma založím nové vlákno k diskuzi. Je to složitější než na první pohled vypadá.
- David Grudl
- Nette Core | 8227
@mbrecher předpokládám, že tím myslel, že nemůže přepsat metodu addDatetime() protože nevrací TextBase. Nicméně nullable se tohle téma stejně vůbec jinak netýká.
- m.brecher
- Generous Backer | 871
@DavidGrudl
Nicméně nullable se tohle téma stejně vůbec jinak netýká.
Ano, netýká, proto budu pokračovat v novém vláknu „nullable“. Z příspěvku @PavelKravčík je ale vidět, že lidi s nullable hodnotami určitý problém mají a každý se to snaží řešit, jak nejlíp umí. Mělo by se to rozebrat v novém vlákně.
- Pavel Kravčík
- Člen | 1195
m.brecher napsal(a):
@DavidGrudl
Nicméně nullable se tohle téma stejně vůbec jinak netýká.
Ano, netýká, proto budu pokračovat v novém vláknu „nullable“. Z příspěvku @PavelKravčík je ale vidět, že lidi s nullable hodnotami určitý problém mají a každý se to snaží řešit, jak nejlíp umí. Mělo by se to rozebrat v novém vlákně.
Asi nemusíš nové vlákno. Po vydání nové verze jsou tyhle informace stejně nepodstatné. Když to rychle shrnu:
- AddDate jsme si dali do naší nadstavby před několika roky (dřív JS datepicker)
- Používáme s ORM (entity
public ?\Datetime date_publish
)
$form->addDate('date_publish', 'Datum publikování článku')
->setNullable();
//success Form
$entity->date_publish = $values->date_publish;
- m.brecher
- Generous Backer | 871
@DavidGrudl
prvek addTime() vrací v objektu DateTimeImmutable hodnotu ‚0000–01–01 17:53:00.000000‘. Tuto hodnotu nelze uložit do MySQL sloupce DATETIME:
Invalid datetime format: 1292 Incorrect datetime value: '0000-01-01 17:53:00' for column 'my_time'
Napadlo mne, vzhledem k tomu, že datumová část není nastavena na ‚0000–00–00‘, ale na ‚0000–01–01‘, jestli nebylo záměrem umožnit uložení Time i do sloupce DATETIME, jehož rozsah začíná na ‚1000–01–01 00:00:00‘, kdyby addTime() vracel ‚1000–01–01 17:53:00.000000‘ tak by to šlo.
- David Grudl
- Nette Core | 8227
DateTimeImmutable nemuže mít den a měsíc 00, protože to je mimo
povolené hodnoty (i ten rok 0 je nesmysl, ale to projde). Naopak
s uložením 0000-01-01 17:53:00
do MySQL žádný
problém nemám…
- Marek Bartoš
- Nette Blogger | 1274
do MySQL sloupce DATETIME
time → time
datetime → datetime / timestamp
date → date
?
- David Grudl
- Nette Core | 8227
@mbrecher jak jsem psal, s uložením do MySQL DATETIME žádný problém nemám. MySQL 8.0.24
- dms
- Člen | 94
- addDate, addDatetime a addTime – vyzkoušeno a funguje super
- addColor – funguje jak má, ale bohužel nelze hodnotu mazat (což je default chování browserů), takže stále potřeba workaround
Ještě jsem procházel aplikaci a máme tam často tyto případy (jen taková idea co by se mi líbilo):
$form->addText('tel')->setHtmlType('tel');
// $form->addTel('tel') by bylo víc cool
a
$form->addText('recipients', 'E-mail příjemnce (nebo více oddělené čárkou)');
$form->setHtmlType('email');
$form->setHtmlAttribute('multiple');
// $form->addEmail() s možností parametru multiple
// a automatickou validací zda jsou zadány jen validní e-maily oddělené čárkou
- Pavel Kravčík
- Člen | 1195
Dá se tam dát pattern v HTML a na telefonech se například zobrazuje „volat“ a „speciální klávesnice na čísla bez písmen“, když máš on-focus.
Editoval Pavel Kravčík (3. 11. 2023 14:50)
- dms
- Člen | 94
Ano přesně tak, většina těch type u inputů mění klávesnici na telefonu více přizpůsobenou danému inputu a nebo přidává drobné vylepšení (třeba search input dává ikonu na smazání inputu) více o jednotlivých inputech pak zde:
- m.brecher
- Generous Backer | 871
@MarekBartoš
time → time
datetime → datetime / timestamp
date → date
Ano, použít v MySQL odpovídající typ pro datum a čas je ideální. Ale:
MySQL type TIME je v Nette Explorer problematicky podporován. ActiveRow z databázové knihovny vrací nikoliv Nette\Utils\DateTime, ale DateInterval. Ten nelze jednoduše vykreslit v šablonách latte:
{$row->datetime} {* MySQL DATETIME - latte vykreslí *}
{$row->date} {* MySQL DATE - latte vykreslí *}
{$row->time} {* MySQL TIME - latte NEUMÍ vykreslit *}
{$row->time|date 'H:i'} {* MySQL TIME - toto filtr latte také NEUMÍ *}
Jak zaznělo v této diskuzi, nově přidaný prvek addTime() také nedokázal načíst čas z objektu DateInterval, což @DavidGrudl bleskově opravil, ale ne tak, že by změnil v ActiveRow DateInterval na Nette\Utils\DateTime s datumem ‚0000–01–01‘, ale přidal do addTime() schopnost zpracovat i DateInterval.
Jenže situace jaká byla v addTime() je i v šablonách Latte (code samply výše). Pokud by někdo opravdu chtěl použít pro čas typ MySQL TIME, tak si bude muset pro latte udělat speciální filtr.
Udělat si pro MySQL TIME speciální latte filtr není složité, nevyřeší se tím ale přímý výpis bez filtru {$row->time}, což se často používá při psaní šablon – nejprve nahodím do šablony data, až potom doplním filtry.
Nebo použít pro čas MySQL DATETIME – také ne ideální. V budoucnu bychom mohli využívat metadata uložená v MySQL serveru jako support pro automatické generování formulářů. Když budou správně nastaveny datové typy, tak pro DATE použijeme ve formuláři prvek addDate(), pro DATETIME použijeme addDateTime() a pro TIME použijeme addTime().
Ideální je věci nekomplikovat a mít stejné API pro datum a čas jak ve formulářích, tak v databázi, tak i v databázových tabulkách – tedy používat pro čas MySQL typ TIME, ale zbavit se DateInterval-u v ActiveRow.
Ještě je zde možnost jít v Latte stejnou cestou jako v addTime() a pozměnit latte tak, aby si automaticky převedlo DateInterval na Nette\Utils\DateTime. To by řešilo skoro vše, ale pořád zde zůstane nekonzistentní DateInterval v ActiveRow pro sloupec TIME.
Přitom DateInterval není nic speciálně navrženého jenom pro čas, umožňuje vyjádřit časový interval i v letech a měsících, takže by nejlepší ho z Nette úplně vyřadit. Bohužel je to BC, ale čas se moc nepoužívá a většina lidí bezpochyby stejně pro čas používá DATETIME právě kvůli nemožnosti výpisu v latte.
Editoval m.brecher (3. 11. 2023 17:21)
- Kamil Valenta
- Člen | 820
evromalarkey napsal(a):
@DavidGrudl vesměs u všech input typů by měla být dobrá podpora v prohlížečích až na
week
amonth
Jen na okraj: datetime-local má trochu nepříjemnou podporu ve Firefoxu, kde picker nabízí jen datum a čas se musí dopsat ručně. Jiné prohlížeče nabízí picker pro datum i pro čas.
- m.brecher
- Generous Backer | 871
@Pepino
@mbrecher MySQL sloupec time není určen pro čas ve smyslu 0–23h ale pro časový interval. HTML input time je pouze pro 0–23h. Takže je správně, že vrací DateInterval.
Díky za připomínku, máš pravdu, dokumentace MySQL: „TIME values may range from ‚-838:59:59‘ to '838:59:59“ a záměrem je poskytnout typ TIME: a) pro reprezentaci času během dne (0–24 h), b) pro reprezentaci časového intervalu mezi dvěma událostmi.
Proto je jak píšeš pro typ MySQL TIME správná reprezentace v ActiveRow pomocí DateInterval. Ze stejného důvodu není vhodné aby Latte automaticky vykreslovalo DateInterval jako čas, protože vývojář musí určit, zda se jedná o čas nebo časový interval.
Pak je nejlepším řešením navrhovat pro Nette aplikace datové typy pro datum a čas v MySQL takto:
date → DATETIME nebo DATE
datetime → DATETIME
time → DATETIME, nikdy TIME
dateInterval → TIME
Ne každého napadne, že by neměl v aplikacích Nette používat pro time TIME, protože dokumentace MySQL ho k tomu naopak vybízí: „je určen a) pro čas během dne, b) pro časový interval“. Viz příspěvek uživatele @Pepiik , který pro time používá typ TIME, jak vyplývá z jeho příspěvku: https://forum.nette.org/…e-smazatelny#…
Hledal jsem v dokumentaci Database\Explorer popis formátů sloupců v objektu ActiveRow, ale nic jsem nenašel. Asi by bylo vhodné doplnit do dokumentace Database\Explorer samostatný odstavec s popisem objektu ActiveRow, popsat formáty výstupních dat + doporučit optimální datové typy MySQL pro datum a čas a vysvětlit proč. Stejně tak vysvětlit jak Nette pracuje s nullable hodnotami (formuláře) a doporučit nějaký optimální postup (setNulable(), setPrompt(), …). Zkusím nějaké PR napsat.
Editoval m.brecher (3. 11. 2023 20:55)