Použití jedné funkce na více stránkách
- kazlik
- Člen | 19
Zdravím, jaksi si nevím rady jak použít funkci na více stránkách.
Momentálně to mám
public function renderDefault($project)
{
$projectInfo = $this->database->table('project')->where('shortcut_url', $project)->limit(1);
foreach($projectInfo as $project){
$this->template->project = $project;
}
//...
}
a z
$projectInfo = $this->database->table('project')->where('shortcut_url', $project)->limit(1);
foreach($projectInfo as $project){
$this->template->project = $project;
}
potřebuju udělat samostatnou funkci, něco jsem zkoušel, ale bohužel se mi nic nepodařilo. viz:
public function renderDefault($project)
{
$this->template->project = getProjectInfo($project);
//...
}
private function getProjectInfo($project){
$projectInfo = $this->database->table('project')->where('shortcut_url', $project)->limit(1);
foreach($projectInfo as $project){
return $project;
}
}
- Azathoth
- Člen | 495
metodu getProjectInfo si přesuň do nějaké modelové třídy a tu
modelovou třídu si nainjectuj do všch presenterů, kde to otřebuješ.
nebo si udělej komponentu, kterou budeš mít na více stránkách.
pokud máš tu metodu v basePresenteru a voláš ji z potomků, musí být ta
metoda protected, ne private.
- kazlik
- Člen | 19
Hodil jsem to do basePresenteru
namespace App\Presenters;
use Nette;
use App\Model;
/**
* Base presenter for all application presenters.
*/
abstract class BasePresenter extends Nette\Application\UI\Presenter
{
private $database;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
}
//...
}
use Nette\Application\UI\Control;
class ProjectControl extends Nette\Forms\Controls\BaseControl
{
protected function getProjectInfo($project){
return $this->database->table('project')->where('shortcut_url', $project)->limit(1)->fetch();
}
// ...
}
a na stránce mi
$this->template->project = $this->ProjectControl->getProjectInfo($project);
hodí chybu:
Nette\MemberAccessException
Cannot read an undeclared property App\Presenters\RozpisPresenter::$ProjectControl.
Asi to tam mám blbě vložené, ale takhle mě to napadlo nejlíp :/
Editoval kazlik (17. 10. 2015 23:03)
- greeny
- Člen | 405
Udělej si na to nějakou modelovou třídu (ne komponentu ani control), např.:
namespace App\Model;
use Nette\Database\Context;
class ProjectRepository
{
/** @var Context */
private $database;
public function __construct(Context $database)
{
$this->database = $database;
}
public function getProjectByUrl($projectUrl)
{
return $this->database->table('project')
->where('shortcut_url', $project)
->limit(1)
->fetch();
}
}
Tu třídu zaregistruj do config.neon do služeb (abys mohl využít DI):
services:
- App\Model\ProjectRepository
A v každém presenteru kde tuhle třídu potřebuješ, si jednoduše
předáš ProjectRepository
:
namespace App\Presenters;
use App\Model\ProjectRepository;
class FooPresenter extends BasePresenter
{
/** @var ProjectRepository */
private $projectRepository;
public function __construct(ProjectRepository $projectRepository)
{
$this->projectRepository = $projectRepository;
}
public function renderDefault($project)
{
$this->template->project = $this->projectRepository->getProjectByUrl($project);
}
}
Zkus celý ten kód nekopírovat ale spíš se z něj inspirovat. Tímto způsobem (nebo podobnými způsoby) je řešen model v každém větším projektu. Je to mnohem čistější způsob než z presenteru přistupovat přímo k databázi.
Snad to pomůže :)
- greeny
- Člen | 405
Volání parenta mi uteklo, za to se omlouvám. Ale v presenterech je naprosto běžné si předávat věci přes konstruktor. Když bys to dělal inject metodama, tak buď máš metodu stejně obsáhlou jako konstruktor a nebo jich máš více a je to méně přehledné. A anotace tě zase nutí mít ty property public.
- Šaman
- Člen | 2666
Doporučovaný způsob je používat konstruktor u konkrétních (final) presenterů a anotaci u všech abstraktních předků. Resp. doporučovaný kým? K tomuto řešení jsme dospěli kdysi v nějakém vláknu jako nejlepší poměr akademické čistoty versus předejití nebezpečí constructor hell.
Ale anotace je kratší na zápis a běžně se tedy všechny závislosti předávají pomocí anotace, i když je to ten nejošklivější způsob (přímý zápis do public property).
- F.Vesely
- Člen | 369
Pokud nechces mit property public, tak zkus Kdyby/Autowired + je tam podpora pro injectovani tovarnicek primo do createComponent funkci, coz je naprosto uzasny. :)
- greeny
- Člen | 405
@Šaman proto nejradši používám „nejčistější“ metodu: v BasePresenterech injectuju pomocí metod (inject***) do protected / private properties a v ostatních presenterech používám konstruktor.
@F.Vesely sice je to „úžasný“, ale taky je to temná magie, která by v čistém kódu neměla co dělat (sám Filip o tom píše v dokumentaci).
- David Kudera
- Člen | 455
@Šaman jednou jsem se na to tady ptal: https://forum.nette.org/…o-presenteru
a můj tehdejší dotaz vůbec nepomohl musím říct. Jak jsem psal již tam, chtěl jsem to vědět kvůli tomu, abych věděl (ideálně i ostatní), co odpovídat zde na fóru dalším lidem. Několik různých best practices od různých lidí totiž začátečníkům určitě moc nepomáhá. Škoda myslím…
- Oli
- Člen | 1215
@greeny nepíše tam nic o tom, že to nemáš používat. Z mého pohledu spíš naopak
Just keep in mind, that is not a clean approach – it's pragmatic.
Přecejenom nejsme na škole aby to muselo být naprosto dokonalé. V prsenteru autowire používám v podstatě všude. Prostě proto, protože jsem línej :-)
- Šaman
- Člen | 2666
Asi to nemá cenu o moc víc rozebírat. Každý přístup má něco do sebe (čistotu, nebo rychlost) a je na osobních preferencích každého programátora, který zvolí.
Proti Kdyby magii mám víc argumentů, ale začátečníkovi bych ji nedoporučoval hlavně proto, že to není běžný Nette postup, se kterým se potká v příkladech a tutoriálech. Tam se nejčastěji potká v presenterech s anotací @inject (nejrychlejší Nette zápis), mimo presentery se pak povinné závislosti předávají konstruktorem.
Předávat konstruktorem i v presenterech je snaha o čistější kód, přejít na magii je snaha o kratší zápis všude, i mimo presentery. Programátor by měl ale při práci s magií vědět proč to dělá.
- Oli
- Člen | 1215
@greeny no, já se snažím psát čistě, takže pro mě to byl víceméně ekvivalent. U mě to není jen o čase, ale líp se mě to i čte/edituje.
@Šaman můžeš to trochu rozvést? Jestli jsme hodně OT, tak klidně založit nový téma s pros/cons? Já to totiž vnímám jako @inject anotaci jen lepší, protože není public. To s těma továrníčkama je hlavně strašně pohodlný a vítězí lenost :-D (ale zdůrazňuju jen v presenterech)
- Šaman
- Člen | 2666
@oli: Offtopic to je, ale to bychom museli přesunout půlku vlákna.
Tak jen ve stručnosti co mám proti Kdyby/Autowired
:
- je to nová závislost, pokud teda v projektu nepoužíváš
Kdyby
i na něco jiného - private property není součástí veřejného rozhraní, takže ta závislost je zvenku vlastně skrytá
- je to magie, takže pro někoho WTF když začne přemýšlet jak se vlastně ta závislost dostala zvenku do private
- a jak jsem už psal, pro nováčky bych doporučil začít používat Nette způsob, dokud sami nezačnou cítit potřebu hledat jinou cestu