Komentare ku vlastnemu eshopu
- MKI-Miro
- Člen | 279
Ahojte
Spravil som si mensi vlastny eshop a chcel by som vas poprosit o komentare ku kodu ako napr
- co je spravene uplne zle
- co by sa dalo vylepsit
Zdrojove kody najdete tu:
https://gitlab.websupport.sk/…/tree/master
Pripadne zdielal niekto uz svoje zdorjaky eshopu? s ktorym by som si to vedel porovnat …
Vdaka
- David Matějka
- Moderator | 6445
https://gitlab.websupport.sk/…pository.php#L69 skrz
parametr id
bych tam mohl protlacit SQL.. a ani to type a action
neni stastne, tam bys asi mel kontrolovat, jestli jsou v nejakem povolenem
seznamu hodnot.
- David Matějka
- Moderator | 6445
dale jen tak namatkove:
$session = $this->presenter->context->getService("session");
$cartSession = $session->getSection('cart');
- v presenteru
$this->presenter=== $this
- na context bys nemel sahat (skoro nikde)
- v presenteru muzes session ziskat pres
$this->getSession('cart')
…
https://gitlab.websupport.sk/…resenter.php#L33 to cislo 11, neni vubec dobry se takhle spolehat na ID v databazi. a kdyzuz, tak bys to mel mit v nejake konstante..
…
https://gitlab.websupport.sk/…resenter.php#L98 generovat takhle nejaky kody neni bezpecne. pouzij radeji treba https://api.nette.org/…/Random.html
…
https://gitlab.websupport.sk/…resenter.php#L219
na sestavovani url muzes pouzit treba https://api.nette.org/…ttp/Url.html
nebo aspon http://cz2.php.net/…ld-query.php
…
checkoutpresenter a objednavkapresenter maji skoro stejny kod.
…
https://gitlab.websupport.sk/…resenter.php#L38
count()
nad selection je neefektivni. to vybere vsechny zaznamy
z db. pokud chces pouzit promo count v sql, dej tam parametr *
,
tedy count('*)
- MKI-Miro
- Člen | 279
David Matějka napsal(a):
https://gitlab.websupport.sk/…pository.php#L69 skrz parametr
id
bych tam mohl protlacit SQL.. a ani to type a action neni stastne, tam bys asi mel kontrolovat, jestli jsou v nejakem povolenem seznamu hodnot.
stymi filtrami nad produktami by ma celkom zaujimala nejaka best practise
tie examples ktore sa daju stiahnut su totiz dost male, chcelo by nejaky poriadny vacsi priklad
- MKI-Miro
- Člen | 279
David Matějka napsal(a):
dale jen tak namatkove:
$session = $this->presenter->context->getService("session"); $cartSession = $session->getSection('cart');
- v presenteru
$this->presenter=== $this
- na context bys nemel sahat (skoro nikde)
- v presenteru muzes session ziskat pres
$this->getSession('cart')
…
https://gitlab.websupport.sk/…resenter.php#L33 to cislo 11, neni vubec dobry se takhle spolehat na ID v databazi. a kdyzuz, tak bys to mel mit v nejake konstante..
…
https://gitlab.websupport.sk/…resenter.php#L98 generovat takhle nejaky kody neni bezpecne. pouzij radeji treba https://api.nette.org/…/Random.html
…
https://gitlab.websupport.sk/…resenter.php#L219
na sestavovani url muzes pouzit treba https://api.nette.org/…ttp/Url.html nebo aspon http://cz2.php.net/…ld-query.php…
checkoutpresenter a objednavkapresenter maji skoro stejny kod.
…
https://gitlab.websupport.sk/…resenter.php#L38
count()
nad selection je neefektivni. to vybere vsechny zaznamy z db. pokud chces pouzit promo count v sql, dej tam parametr*
, tedycount('*)
dakujem opravil som vsetky tieto nedostatky
inac ak by sa to dotiahlo uplne, mohlo by sa to niekde hodit aj tu na stranku pre inspiraciu pre ostatnych
- MKI-Miro
- Člen | 279
Ahojte
takze implementoval som vsetky pripomienky
https://gitlab.websupport.sk/…/tree/master
napada niekoho este nejake vylepsenie ?
myslite ze by sa to mohlo niekde publikovat aby to pomohol zaciatocnikom ?
online sa to da vidiet tu
Vdaka
Editoval MKI-Miro (21. 8. 2016 19:09)
- GEpic
- Člen | 566
MKI-Miro napsal(a):
Ahojte
takze implementoval som vsetky pripomienky
https://gitlab.websupport.sk/…/tree/master
napada niekoho este nejake vylepsenie ?
myslite ze by sa to mohlo niekde publikovat aby to pomohol zaciatocnikom ?
online sa to da vidiet tu
Vdaka
Ahoj,
Jaký má význam ten levý sloupec?
Upřímně co se mě týče, v roli zákazníka bych ten eshop asi vypl, a pokračoval dál. Vyhledávání by určitě mělo našeptávat jak produkty, tak kategorie. A levý panel by určitě neměl být vypsán výrobci na prvním místě.
Když jdu pro hračky, chci dejme tomu třeba tank, protože je rád lepím. No tady musím použít ctrl+f, abych tu kategorii vůbec našel.
Editoval GEpic (21. 8. 2016 19:57)
- GEpic
- Člen | 566
Editoval jsem původní post, nevšiml jsem si, že si odpovídal.
Plus za mě další věc:
- Zobrazení na mobilních telefonech / tabletech
A nemůžu se zbavit pocitu, že i přesto že to je na Nette, je to nějaké pomalé (a to nemám pomalý internet). Nekoukal jsem do kódu, ale ty výrobce asi nemáš nacachované, že? Veškeré kategorie v levém sloupci vypisuješ při každém requestu.
Editoval GEpic (21. 8. 2016 20:01)
- MKI-Miro
- Člen | 279
@GEpic nemam nacachovane (hned aj idem pozriet ak sa to robi)
na tablete sa ti to zle zobrazuje ? celkovo aleob len nejaka cast ?
@Myiyk
kde by som tu licenciu mal dat ?
(skusim tie commity pomenuvavat)
@ all
mam na vas este jednu otazku
v base presenteri nastavujem $this->lang
ale v translatorovi mi nefunguje if ($this->lang == "") {
ako to spravne zapisat ?
vdaka
- GEpic
- Člen | 566
MKI-Miro napsal(a):
@GEpic nemam nacachovane (hned aj idem pozriet ak sa to robi)
na tablete sa ti to zle zobrazuje ? celkovo aleob len nejaka cast ?
@Myiyk
kde by som tu licenciu mal dat ?
(skusim tie commity pomenuvavat)@ all
mam na vas este jednu otazku
v base presenteri nastavujem $this->lang
ale v translatorovi mi nefunguje if ($this->lang == "") {
ako to spravne zapisat ?vdaka
Doporučuju Chrome a mrknout se po Device Toolbaru (přímo v Chrome), simuluje přímo mobilní zařízení, můžeš si vybrat třeba zobrazení na Nexusu, iPhonu nebo vlastním rozlišení a podobně a pomocí toho můžeš odladit i responsivní zobrazení.
Editoval GEpic (7. 9. 2016 13:03)
- Muhahe
- Člen | 79
MKI-Miro napsal(a):
Muhahe napsal(a):
Jen takova technicka, proc nikde v presenterech nepouzivas konstruktor? (neber to jako pripominku, jen cira zvedavost)
otocim otazku, kedy by bolo vhodne ho pouzit ?
Jsem jenom zacatecnik, ale prijde mi taknejak automaticke (nerikam ze je to spravne) pouzivat neco takoveho
public function __construct(Nette\Database\Context $database, \Nette\DI\Container $container) {
$this->database = $database;
$this->model = new administrationModel($this->database); // $model;
$this->crawlerModel = new crawlerModel($this->database); //$crawlerModel;
$this->container = $container;
$this->mailer = new Mailer\mailerClass($this->database);
$this->datatablesModel = new Model\DatatablesModel($this->database);
}
Kde presenteru predam databazi, a v tomhle pripade i DI container (ten mam z duvodu rozpoznani zda se jedna o normalni HTTP request a nebo CLI z CRONu), vytvorim si instance modelu a pak jedu
- MKI-Miro
- Člen | 279
namiesto konsturktoru robim mam inject nie ?
/** @var \App\Model\category_manufacturerRepository @inject */
public $category_manufacturerRepository;
1.stale nerozumiem co ine by malo byt v tom konstruktore
2.
mam na vas este jednu otazku
v base presenteri nastavujem $this->lang
ale v translatorovi mi nefunguje if ($this->lang == "") {
ako to spravne zapisat ?
- Muhahe
- Člen | 79
MKI-Miro napsal(a):
namiesto konsturktoru robim mam inject nie ?
/** @var \App\Model\category_manufacturerRepository @inject */ public $category_manufacturerRepository;
1.stale nerozumiem co ine by malo byt v tom konstruktore
2.
mam na vas este jednu otazku
v base presenteri nastavujem $this->lang
ale v translatorovi mi nefunguje if ($this->lang == "") {
ako to spravne zapisat ?
S tim bych rekl ze to bude proto, ze $this->lang v base presenteru je v uplne jinem contextu nez $this->lang v translatoru. (nededi z basePresenteru. ale nejsem si jistej jestli $lang neni nejaka „globalni“ promenna)
ASi bych v tomto pripade nespolehal na to ze je nejaka promena prazdna, a snazil bych se ji davat obsah vzdy. Takze budto bude $this->lang == „svk“ nebo $this->lang == „en“ a pak to muzes oddebugovat v translatoru.
Editoval Muhahe (7. 9. 2016 14:12)
- Muhahe
- Člen | 79
Pavel Kravčík napsal(a):
@Muhahe: To mi přijde strašné. Jaké to má výhody?
Netvrdim ze to ma vyhody, prave proto se ptam, proc on to nepouziva, abych pripadne nasel lepsi cestu. Puvodne jsem predaval modely do parametru konstruktoru, ale casto jsem se dostal do problemu, ze jich bylo docela dost. Tak predavam jen database, a modely vytvarim prave v konstruktoru
Editoval Muhahe (7. 9. 2016 14:07)
- Pavel Kravčík
- Člen | 1196
@Muhahe: Já mám právě za to, že je tohle ošklivé zneužívání containeru. Na google se bude dát něco najít, třeba pěkný článek od Davida.
Nejhezčí varianta samozřejmě je mít presentery, co nejčistější. Buď komponenty s továrničkami nebo modely, které si svoje závislosti řeší sami. Případně předek s injectem.
- Muhahe
- Člen | 79
Pavel Kravčík napsal(a):
@Muhahe: Já mám právě za to, že je tohle ošklivé zneužívání containeru. Na google se bude dát něco najít, třeba pěkný článek od Davida.
Nejhezčí varianta samozřejmě je mít presentery, co nejčistější. Buď komponenty s továrničkami nebo modely, které si svoje závislosti řeší sami. Případně předek s injectem.
Dobre. Diky za odkaz a novou myslenku ;)
- CZechBoY
- Člen | 3608
@Muhahe tvůj kód přepsaný do DI
public function __construct(administrationModel $model, crawlerModel $crawlerModel, IMailer $mailer /* dic sám vloží nějakou implementaci tohoto rozhraní, třeba ten tvůj mailerClass*/, DatatablesModel $datatablesModel) {
$this->model = $model;
$this->crawlerModel = $crawlerModel;
$this->mailer = $mailer;
$this->datatablesModel = $datatablesModel;
}
Odebral jsem
- databázi: nevim jestli potřebuješ, když stejně používáš modely
- DIC: nevim jestli potřebuješ, případně si předej z DIC jen to co fakt používáš – třeba parametry v konfiguráku (parameters: xxx: yyy)
- Barvoj
- Člen | 60
Netvrdim ze to ma vyhody, prave proto se ptam, proc on to nepouziva, abych pripadne nasel lepsi cestu. Puvodne jsem predaval modely do parametru konstruktoru, ale casto jsem se dostal do problemu, ze jich bylo docela dost. Tak predavam jen database, a modely vytvarim prave v konstruktoru
@Muhahe Za mě je určitě lepší předávat přímo modely. Třída
potřebuje crawlerModel
tak se k němu v konstruktoru hlásí a
ne že si ho sama bude v konstruktoru vytvářet.
Co když někdy v budoucnu budeš chtít používat jinou implementaci
crawlerModel
? Například z důvodu unit testování.. Budeš
potřebovat závislosti mockovat a u tvého způsobu to nepůjde.
Problém s příliš mnoha závislostmi v konstruktoru lze určitě řešit lépe – buď třídu rozdělit do více menších tříd, které nebudou potřebovat tolik závislostí, a nebo několik závislostí obalit novou třídou-modelem, která bude té tvé třídě poskytovat rozhraní. Místo 9 závislostí pak budeš mít třeba 3 (ty nové třídy-modely) z nichž každá bude mít třeba taky 3.
Editoval Barvoj (7. 9. 2016 15:04)
- Pavel Kravčík
- Člen | 1196
@CZechBoY: A nebylo by lepší vůbec ten příklad nedělat
s konstruktorem, ale raději s @inject
nebo
injectMethod()
.
Parametry je lépe si tahat buď pomocí nějakého
SettingManageru
nebo si presenter registrovat jako službu a
předat si to pomocí setupu.
- CZechBoY
- Člen | 3608
@PavelKravčík To už je myslím jen otázka priorit :-) Já
konstruktor používám jen u komponent, protože jsou ve většině případů
finální, případně přes setup+decorator nastavím potřebné závislosti do
Base* tříd.
U BasePresenterů se mi teda spíš osvědčily inject* metody, protože
u public property nikdy nevíš kdo je bude chtít použít někde úplně mimo
(v komponentě třeba), nebo nějakej potomek ji bude taky využívat (to se mi
nelíbí tak používám private
v BasePresenterech).
Myslim, že se moc odkláníme od tématu… :-/
- Pavel Kravčík
- Člen | 1196
@CZechBoY: Jasně, pointa je vůbec neukazovat
injektování konstruktorem v presenterech
nováčkům. :)
- MKI-Miro
- Člen | 279
vidite
existuje x otazok ako nieco spravit aby to bolo „best practise“, nikde nie je urobene nejake komplexnejsie riesenie z ktoreho by sa to dalo okukat a prave to ma prividlo k tomu aby som zverjnil nieco co moze pomoct ostatnym :)
takze uz len sa zhodnut ako to upravit aby bolo vsetko vporiadku :)
- MKI-Miro
- Člen | 279
CZechBoY napsal(a):
@Muhahe To tvoje mi přijde, že není úplně podle DI pravidel (vytváříš třídu ručně, nikoliv aby sis ji nechal předat již vytvořenou).
@MKI-Miro o jazyku by měl vědět asi translator, tak mu nějakej jazyk nastav.
cize navrhujes aby to co sa robi v Base preseneteri:
$httpRequest = $this->context->getService('httpRequest')->getUrl();
if ($httpRequest->host == "www.hrackykosice.sk" || $httpRequest->host == "hrackykosice.sk")
{$this->lang = "";$this->site = "hracky";}
else if ($httpRequest->host == "www.gameskosice.com" || $httpRequest->host == "gameskosice.com")
{$this->lang = "_en";$this->site = "games";}
else if ($httpRequest->host == "www.wholesalekosice.eu" || $httpRequest->host == "wholesalekosice.eu")
{$this->lang = "_en";$this->site = "wholesale";}
aby sa robil aj v Translator ?
- Muhahe
- Člen | 79
MKI-Miro napsal(a):
CZechBoY napsal(a):
@Muhahe To tvoje mi přijde, že není úplně podle DI pravidel (vytváříš třídu ručně, nikoliv aby sis ji nechal předat již vytvořenou).
@MKI-Miro o jazyku by měl vědět asi translator, tak mu nějakej jazyk nastav.
cize navrhujes aby to co sa robi v Base preseneteri:
$httpRequest = $this->context->getService('httpRequest')->getUrl(); if ($httpRequest->host == "www.hrackykosice.sk" || $httpRequest->host == "hrackykosice.sk") {$this->lang = "";$this->site = "hracky";} else if ($httpRequest->host == "www.gameskosice.com" || $httpRequest->host == "gameskosice.com") {$this->lang = "_en";$this->site = "games";} else if ($httpRequest->host == "www.wholesalekosice.eu" || $httpRequest->host == "wholesalekosice.eu") {$this->lang = "_en";$this->site = "wholesale";}
aby sa robil aj v Translator ?
Osobne bych detekoval jazyk prave v tom translatoru, ale jestli to neni prasarna, to ti nepovim. Ale urcite bude problem v tom ze promena $this->lang v basePresenteru je uplne jina promenna nez $this->lang v translatoru.
A myslenka translatoru mi prijde takova, ze prave on se stara o to, v jakem jazyku ma byt vysledek, takze proc zatezovat zbytek kodu jazykem? at se pekne postara translator :)
- MKI-Miro
- Člen | 279
vyriesil som to takto:
v base presenter
$translator = new \App\Language\Translator($this->lang);
$this->template->setTranslator($translator);
translator
class Translator implements \Nette\Localization\ITranslator {
private $lang;
public function __construct($lang) {
$this->lang = $lang;
}
/**
* Translates the given string.
*/
public function translate($message, $count = NULL) {
if ($this->lang == "") {
return constant('\App\Language\Slovak::'. $message);
}
else {
return constant('\App\Language\English::'. $message);
}
}
}
- CZechBoY
- Člen | 3608
@MKI-Miro já bych si zaregistroval ten tvůj překladač do DIC a po vytvoření bych zavolal nějakou metodu na detekci jazyku.
class Translator implements \Nette\Localization\ITranslator
{
public function detectLanguage()
{
// nejak zjisti jazyk..
// muzes si do parametru i nechat predat nejakou sluzbu
}
public function translate($message, $count = null)
{
// tvoje implementace ITranslator::translate
}
}
services:
-
class: App\Translator
setup:
- detectLanguage
jinak to kontrolování jazyka při každém volání translate je nic moc… co použít třídní proměnnou, kterou naplníš v tom detectLanguage?
btw. můžeš si udělat vlastní latte.templateFactory abys měl v každý šabloně už translator nastavený
Editoval CZechBoY (7. 9. 2016 16:26)
- Oli
- Člen | 1215
@CZechBoY: Jasně, pointa je vůbec neukazovat injektování konstruktorem v presenterech nováčkům. :)
@PavelKravčík s tímhle rozhodně nesouhlasím. Podle mě je to best practice. Ostatní metody by se měli používat v předcích kvůli constructor hell. To že se to (i já to tak mám) používá i ve finálních presenterech je v podstatě kvůli lenosti. Ale neřekl bych, že by se to nemělo ukazovat nováčkům :-)
@Muhahe
Puvodne jsem predaval modely do parametru konstruktoru, ale casto jsem se dostal do problemu, ze jich bylo docela dost. Tak predavam jen database, a modely vytvarim prave v konstruktoru
Tohle je špatně. Myslím, že se tomu říká skrytá závislost. Tvoje
třída má závislost třeba na Mailer\mailerClass
, ale ty to ani
nevíš, dokud neotevřeš kód. Správně by jsi měl, jak už bylo
konstatováno, předávat konkrétní třídy, který jsou pro tvou třídu
potřeba. Případně ještě lépe jejich interface.
Pokud jich je moc, tak to většinou naznačuje na chybu v návrhu. Třída by měla dělat jednu věc. Například, pokud máš třeba třídu, která se stará o objednávky, tak by jsi v ní neměl řešit odesílání mailů. Na to jsou události. :) Jediná výjimka na kterou jsem narazil jsou formuláře. Pokud formulář obsahuje hodně číselníků načítaných z databáze, tak se závislosti na několika službách neubráníš (v některý z vrstev).
$httpRequest = $this->context->getService(‚httpRequest‘)->getUrl();
Tohle taky vypadá dost hrozně :-) Vždyť ty potřebuješ instanci
Http\Request, ale vůbec o tom nevíš. Dokud nenarazíš na tenhle kus kodu,
tak o tom nemůžeš mít ani tušení. Pokud jsi v presenteru, tak se na to
dostaneš jako $this->getHttpRequest()
. Pokud jsi v jiné
třídě, tak si to předej jako závislost konstruktorem.
Na context jsem za x let vývoje nemusel (v normálních třídách) šáhnout. ;-)
- MKI-Miro
- Člen | 279
CZechBoY napsal(a):
@MKI-Miro já bych si zaregistroval ten tvůj překladač do DIC a po vytvoření bych zavolal nějakou metodu na detekci jazyku.
>
jinak to kontrolování jazyka při každém volání translate je nic moc… co použít třídní proměnnou, kterou naplníš v tom detectLanguage?
btw. můžeš si udělat vlastní latte.templateFactory abys měl v každý šabloně už translator nastavený
tak k tomuto mam viacero otazok
1. toto sa teda nema nachadzat v base presenter ?
$translator = new \App\Language\Translator($this->lang);
$this->template->setTranslator($translator);
2. Kedy volat detectLanguage?
3. ako v tom datectLanguage zistim aktualnu domenu ?
dakujem
- Pavel Kravčík
- Člen | 1196
@Oli, @CZechBoY: Ok díky. Takže pokud si je člověk jistý, že je to finální presenter může používat constuctor. Já jsem to na začátku tak nějak pochopil, že by se tomu člověk měl vyhnout v každém případě. Díky za tip.
- CZechBoY
- Člen | 3608
@MKI-Miro
překladač je služba, kterou můžeš používat i jinde než v presenterech
(v komponentách, latte filtrech nebo i modelech a obyč třídách), takže
bys to měl taky jako službu používat (zaregistruj do DIC
v konfiguráku).
ad detekce jazyka podle domény: můžeš si předat třeba instanci
Nette\Http\IRequest
a z ní vyčíst doménu (jak už si ukazoval
nahoře)
public function detectLanguage(\Nette\Http\IRequest $httpRequest)
{
if ($httpRequest->host === "www.hrackykosice.sk" || $httpRequest->host === "hrackykosice.sk") {
$this->lang = "Slovak";
} elseif ($httpRequest->host === "www.gameskosice.com" || $httpRequest->host === "gameskosice.com") {
$this->lang = "English";
} elseif ($httpRequest->host === "www.wholesalekosice.eu" || $httpRequest->host === "wholesalekosice.eu") {
$this->lang = "English";
} else {
$this->lang = "Czech";
}
}
pak translate:
public function translate($message, $count = null)
{
return constant("App\Language\\{$this->lang}::{$message}");
}
kdy volat detectLanguage jsem ti napsal minule, zaregistruj si ten
překladač jako službu a jako setup uveď tu metodu
detectLanguage
(parametry se doplní z DIC).
Editoval CZechBoY (7. 9. 2016 17:02)
- MKI-Miro
- Člen | 279
inac ako riesite takyto spam v logu
[2016-09-07 19-01-15] Nette\Application\BadRequestException: Cannot load presenter 'General:Php', class 'App\GeneralModule\Presenters\PhpPresenter' was not found. in /nfsmnt/hosting2_2/e/9/e92e7430-7908-48c7-83ea-4f117a5ce58b/hrackykosice.sk/web/vendor/nette/application/src/Application/Application.php:127 caused by Nette\Application\InvalidPresenterException: Cannot load presenter 'General:Php', class 'App\GeneralModule\Presenters\PhpPresenter' was not found. in /nfsmnt/hosting2_2/e/9/e92e7430-7908-48c7-83ea-4f117a5ce58b/hrackykosice.sk/web/vendor/nette/application/src/Application/PresenterFactory.php:71 @ http://hrackykosice.sk/general.php @@ exception--2016-09-07--19-01--36280ee7df.html
[2016-09-07 19-01-16] Nette\Http\UrlScript #7c45 scriptPath private => "/" scheme private => "http" (4) user private => "" password private => "" host private => "hrackykosice.sk" (14) port private => 80 path private => "/general.php" (12) query private => array () fragment private => "" @ http://hrackykosice.sk/general.php
[2016-09-07 19-01-16] Mozilla/5.0 (Windows NT 6.0; rv:16.0) Gecko/20130722 Firefox/16.0 @ http://hrackykosice.sk/general.php
mam tam kopec takychto zaznamov, a vyzera to na robotov ktori skusaju rozne varianty url