Parametry pro celý web – best practise

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

Mám total begginer dotaz.

Mám parametr, který pro celý web(2 moduly) určuje, jestli se v jednom modulu budou něco zobrazovat (asi na 4 obrazovkách). Rád bych to měl jako jednoduchý parametr někde v kódu (tedy ne v db – uživatelé k této volbě nebudou mít přístup).

Mám pročtenou doku ohledně konfigurace, ale nějak jsem nepochopil, jak použít můj vymyšlený parametr. Měl jsem představu, že v config.neon zadám discount_percent_visible: 1 a všude v kódu k této proměnné budu mít přístup…

Můžete mi prosím poradit, jakou cestou se vydat a co nastudovat ? Uvítám jednoduchost.

A jak chápat větu „predavat konkretni parametry tam, kde jsou potreba (nejlepe do sluzeb a komponent, vyhnout se presenterum)“?

díky Váňa

CZechBoY
Člen | 3608
+
0
-

k tomu slouzi polozka parameters.
jinak mrkni i na toto https://pehapkari.cz/…kty-v-nette/

rerege
Člen | 58
+
0
-

ten článek na pehapkari jsem již četl – se tam docela v komentářích pak rozchází v názorech
nicméně, když dám do config.neon
parameters:
discount_percent_visible: 1

jak se k tomu co nejjednodušeji dostanu?
edit: třeba takto, že..
$this->context->parameters[‚discount_percent_visible‘]

proč to není doporučené? co místo toho?

Editoval rerege (22. 8. 2017 11:04)

Rob Bob
Člen | 60
+
-4
-

Vytvoř si službu např. paramService, která ti bude relevantní parametry pro aplikaci/presentery poskytovat, může vypadat např. takto

<?php
   class ParamService {

    private $params = [];

    public function __construct(array $params) {
        $this->params = $params;
    }

    public function getParams() {
        return $this->params;
    }

    public function getParam($paramName) {
       if(!isset($this->params[$paramName]) {
			throw new NonExistingParamException("Parameter {$paramName} does not exist");
       }
	   return $this->params[$paramName];
    }

}
?>

A v konfigu

services:
    paramService: ParamService(@container::getParameters())

V BasePresenter si pak službu injectuješ a používáš $this->paramService->getParam("param");. Do komponent a dalších služeb si budeš samozřejmě injectovat jen konkrétní parametry.

Proč není doporučené přistupovat ke context najdeš zde na foru pod hledáním pojmu „předávání klavíru“ a s tím souvisejícím vtipem.

Editoval Rob Bob (22. 8. 2017 14:14)

matopeto
Člen | 395
+
-1
-

Pokial su tie parametre dane, nepouzival by som paramService->getParam("itemsPerPage") ale v tej param service mal properties ku kazdemu parametru takze by to bolo normalne paramService->itemsPerPage – budes tak mat syntakticku aj typovu kontrolu.

Rob Bob
Člen | 60
+
0
-

Máš pravdu, když jsem se nad tím potom na chvíli víc zamyslel, tak to vlastně není o nic moc lepší řešení než context->parameters, jen oklikou

matopeto
Člen | 395
+
0
-

Rob Bob napsal(a):

Máš pravdu, když jsem se nad tím potom na chvíli víc zamyslel, tak to vlastně není o nic moc lepší řešení než context->parameters, jen oklikou

Ide o to ze ked predavas kontext tak si z neho moze ktokolvek vytiahnut cokolvek, nie len parametre ale i sluzby a navonok nedava vediet svoje zavislosti. (V kontexte je vsetko) Pokial predas iba to co naozaj potrebujes (parametricku sluzbu) tak objekt dostane iba to co potrebuje. Je to na vonok jasne, vymenitelne, testovatelne. Zaklad DI. Kod je cistejsi a citatelnensi. Nehovoriac o tom ze jedneho dna budes chciet tie parametre nacitavat z databaze, tak vymenis len implementaciu ten param service.

Editoval matopeto (22. 8. 2017 13:55)

David Matějka
Moderator | 6445
+
+5
-

obecne param services jsou spatne, lepsi je predat konkretni parametr tam, kde ho potrebuju. (maximalne muzu vytvorit nejaky config objekt, ktery bude obalovat nekolik souvisejicich parametru v nejake omezene scope)

Rob Bob
Člen | 60
+
0
-

@matopeto Jako jo, je to lepší než nic, ale lepší by bylo se asi vydat cestou Configuration objektů pro jednotlivé služby a presenter (tedy parametry přístupné „kdykoliv“) a do nich vkládat jen relevantní parametry/sekce parametrů narozdíl od předávání všech jako v případě @container::getParameters()

Editoval Rob Bob (22. 8. 2017 14:10)

matopeto
Člen | 395
+
+1
-

Suhlasim s vami, globalbne parametre/parametricke sluzby su zlo, predpokladal som ze si pre kazdu skupinu objektov, ktora potrebuje nejake parametre vytvori samostatnu sluzbu :)

rerege
Člen | 58
+
0
-

@DavidMatějka
je prosím někde na netu příklad, jak tedy udělat SPRÁVNĚ „globální parametry“?
Ten návod na pehapkari – to je to co doporučuješ?

Editoval rerege (22. 8. 2017 17:28)

David Matějka
Moderator | 6445
+
+3
-

@rerege to, co je na pehapkarich je celkem ok, ale muze to byt nekdy zbytecny overkill. casto si staci ten parametr predat tam, kde ho potrebuju

rerege
Člen | 58
+
+1
-

chlapi já Vám závidím ty Vaše vědomosti …

@DavidMatějka áha … to jsi radil i v jiném vláknu … prosím můžeš uvést příklad?

Já jsem doteď objevil 2 možnosti

  1. přes context – to prý není dobře
  2. a pak přes settery a gettery
    1. v config.neon mám

    parameters:

    email: 'xyz@gmail.com'

    1. v presenteru pak pomocí DI

      public function setEmail($email)

    {$this->email = $email;}

Proč 1) možnost není správně
Je možnost 2) správně?
A jak to, že ten setter si to umí načíst z configu, jak se tomu říká, abych si to v dokumentaci našel?

CZechBoY
Člen | 3608
+
+1
-

setter si to nenacte sam. ty v konfiguraci presenteru musis uvest zavolani setteru a jakej presne parametr tam chces.
https://doc.nette.org/…onfiguration#…

rerege
Člen | 58
+
+1
-

@CZechBoY čéče to je pravda … takže

config.neon

parameters:

promenna: ‚ááá‘

services:

class: App\EshopModule\Presenters\OrderPresenter

setup:

  • setPromenna(%promenna%)

a v Presenteru

public function setPromenna($promenna) {
$this->promenna = $promenna;
 }

Takhle je to správně? Tím myslím, jak kódově, tak i obecně, jestli je to doporučené řešení?

CZechBoY
Člen | 3608
+
+1
-

jo, vypada to ok.
nekdy jeste predsvam parametr primo pres konstruktor jakozto povinnou zavislost.

rerege
Člen | 58
+
0
-

@CZechBoY vřelé díky – máš u mě šálek pravé brazilské(pardon asi týden Columbia) kávy – když si to pohasíš po D1 – ozvi se…

jinak přes ten context, je to tisíckrát jednodušší – proč se to nesmí(nemá) používat?

matopeto
Člen | 395
+
+1
-

rerege napsal(a):

@CZechBoY vřelé díky – máš u mě šálek pravé brazilské(pardon asi týden Columbia) kávy – když si to pohasíš po D1 – ozvi se…

jinak přes ten context, je to tisíckrát jednodušší – proč se to nesmí(nemá) používat?

pisal som to o par postov vyssie: https://forum.nette.org/…est-practise#…

CZechBoY
Člen | 3608
+
+1
-

@rerege díky, kávu nepiju :-) po D1 jedu akorát o víkendu do Olomouce :D ale to hádám nebude ten správnej směr.

Používání service locatoru vs DI je popsáno třeba u Davida https://phpfashion.com/…vice-locator

rerege
Člen | 58
+
0
-

@matopeto máš pravdu – ono je to tom, že jsem si to přečetl, ale neporozuměl … dnes tomu vláknu více rozumím než před 2 dny… a i tak, mi některá vyjádření unikají … kaju se a děkuji za shovívavost

tož pokud kafe nepijete, tak se mi ozvěte až v zimě uvíznete na D1 na Vysočině – Pomocí nějaké závislosti Vám mohu injektnout Rum … a zabalit do kontejneru zvaného deka

rerege
Člen | 58
+
0
-

Moc se omlouvám, že ještě jednou oživuji toto vlákno…

v presenteru globální parametr zvládám na 1*

chci se zeptat, jak v šabloně? Napadá mě zatím tato možnost:

globální parametr převést v presenteru do template a v šabloně mít podmínku

existuje nějaká lepší varianta?

matopeto
Člen | 395
+
+1
-

Myslim ze je to takto najednoduchsie… pokial pouzivas dedicnost, tak v basepresentru si ho v hodit do sablony.

rerege
Člen | 58
+
0
-

@matopeto jo vidíš v basepresenteru mě to nenapadlo – já bych to rval do jednotlivých presenterů
jsem rád, že jsem se zeptal a ještě raději, žes mi to poradil

ještě jednou veliké díky (již po stopadesáté!)

Váňa

rerege
Člen | 58
+
0
-

já se z toho zVencnu

po přidání do config.neon

	-
		class: App\EshopModule\Presenters\BaseEshopPresenter
		setup:
			- setDiscountPercentVisible(%discountPercentVisible%)

hláška Class App\EshopModule\Presenters\BaseEshopPresenter used in service ‚40‘ not found or is not instantiable.

na netu jsem našel pouze rady ohledně lomítek… to jsem zkusil, cache jsem smáznul…

matopeto
Člen | 395
+
+1
-

basepresenter je abstraktny, preto nejde instancovat, takto bohuzial neviem ako to basepresentru nastavit priamo v configu (Ale mozno to nejako ide), ak by si to mal ako parametricku sluzbu, tak by ti stacilo uviest ako parameter konstruktora…

CZechBoY
Člen | 3608
+
+3
-

Pro nastavování abstraktních tříd se používá decorator.
Tvůj příklad pomocí decoratoru:

decorator:
    App\EshopModule\Presenters\BaseEshopPresenter:
	    setup:
	        - setDiscountPercentVisible(%discountPercentVisible%)

Editoval CZechBoY (24. 8. 2017 12:54)

rerege
Člen | 58
+
0
-

vše již funguje jak má… převeliké díky
jenom se ještě zeptám, když bych chtěl injektovat do dvou Presenterů… může být tento zápis v config.neon takto?

services:
	-
		class: App\EshopModule\Presenters\ProductPresenter
		setup:
			- setStockQuantityVisible(%stockQuantityVisible%) # injektování globálního parametru
	-
		class: App\EshopModule\Presenters\OrderPresenter
		setup:
			- setStockQuantityVisible(%stockQuantityVisible%) # injektování globálního parametru

syntaxi to nijak nevyhazuje, ale při injektování v druhé presenteru (OrderPresenter) mi to vyhazuje chybu (viz níže)

injektáž

public function setStockQuantityVisible($stockQuantityVisible) {
	$this->stockQuantityVisible = $stockQuantityVisible;
}

a volání v kódu

$orderNumber = $this->orderManager->setState($id, $state, **$this->stockQuantityVisible**);

a nyní ta chyba:
„Cannot read a write-only property App\EshopModule\Presenters\OrderPresenter::$stockQuantityVisible.“

nevíte prosím, čím by to mohlo být?

edit: vyřešeno – problém byl v config.neon neb jsem tam měl službu na ten presenter dvakrát

Editoval rerege (29. 8. 2017 14:23)