Použití jedné funkce na více stránkách

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

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
+
0
-

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.

greeny
Člen | 405
+
+1
-

A navíc místo toho cyklu můžeš použít

$this->template->project = $this->database->...->limit(1)->fetch();

Značně se ti tím zpřehlední kód.

kazlik
Člen | 19
+
0
-

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
+
+4
-

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 :)

kazlik
Člen | 19
+
0
-

Super, děkuji moc, takhle mi to už stačí a už to sviští :)

kejlicz
Člen | 201
+
0
-

Jen bych to do presenteru nepředával přes konstruktor, ale anotací nebo inject motodou. Konstruktory mívají dost závislostí a když je to všechno v konstruktoru, je to pak fuj :-). A když už se použije konstruktor, mělo by se použít i

parent::__construct();
greeny
Člen | 405
+
0
-

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.

Mysteria
Člen | 797
+
0
-

Právě že v presenterech je doporučována @inject anotace, protože při používání konstruktorů, když budeš potřebovat něco přidat do BasePresenter konstruktoru, tak budeš přepisovat i všechny v jeho potomcích.

Šaman
Člen | 2666
+
0
-

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
+
0
-

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
+
0
-

@Š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
+
+1
-

@Š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
+
+1
-

@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 :-)

greeny
Člen | 405
+
0
-

@Oli nepsal jsem, že se to nemá používat, ale že v čistém kódu by to nemělo co dělat :) já radši oželím deset vteřin času a napíšu to čistěji, než to mít sice krátký, ale nečistý :)

Šaman
Člen | 2666
+
0
-

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
+
0
-

@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
+
+1
-

@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