Inject databazy do filtra

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

Ako injectnut instanciu databazy do Filters triedy ?

Podla navodu som spravil generic filter loader

class Filters
{
    public static function common($filter, $value)
    {
        if (method_exists(__CLASS__, $filter)) {
            $args = func_get_args();
            array_shift($args);
            return call_user_func_array(array(__CLASS__, $filter), $args);
        }
    }
}

a teraz by som potreboval vytvorit filter ktory bude pouzivat databazu a takisto objekt aplikacie pre vytvaranie liniek.

2.0.nieco som to mal spravene v Helpery takto ale teraz uz pouzivam 2.3.0

class Helper extends Nette\Object
{
    /** @var Nette\Application\Application */
    protected $application;

    /** @var App\Repository */
    protected $repository;

    public function __construct(Nette\Application\Application $application)
    {
      $this->application = $application;
      $this->repository = $this->application->getPresenter()->getContext()->repository;
    }

    public function linkifyDog($text)
    {
        $pattern = "/(\[dog\])(\w+)(\[\/dog\])/";
        $application = $this->application;
        $repository = $this->repository;
        return preg_replace_callback($pattern, function ($text) use ($application, $repository) {
                            $dog = $repository->getTable('dogs')->select('fullName AS name')->where('nickname', $text[2]);

                            if(count($dog) > 0)
                            {
                                return '<a href="' . $application->getPresenter()->link('Page:dog', $text[2]) . '">' . $dog[0]->name . '</a>';
                            } else {
                                return 'unknown dog';
                            }
                        }, $text);
    }
}

Dakujem.

Editoval aRagornol (26. 3. 2015 10:46)

greeny
Člen | 405
+
0
-

Tohle se spíš řeší přes filtry v routě, viz dokumentace

aRagornol
Člen | 17
+
0
-

nie chcem vytvorit filter ktory po aplikovani na text vytvori zo stringov linky. teda ak budem mat text
„Vystava 10.3.2015. [dog]random[/dog] obhajil prvenstvo.“, filter podla nicku random vytiahne z databazy full name a zaroven vytvori na psa linku.

usage {text|linkifyDog} v sablone

Editoval aRagornol (26. 3. 2015 10:32)

Filip Klimeš
Nette Blogger | 156
+
+1
-

Netuším jak to udělat, snad odpoví někdo jiný. Mám ale tušení, že to jde těžko, protože se to tak dělat nemá.

Jaký benefit těžíš z toho, že se budeš dotazovat do DB až při vykreslování šablony? Je případná změna modelu dostatečně dobrým důvodem pro změnu helperu v šabloně? Data o pejscích znáš určitě dříve než v šabloně, proto s nimi také můžeš pracovat dříve. Osobně bych doporučoval nějakou metodu v repozitáři nebo service. Poté předáš do šablony již připravená data a v šabloně z nich jen vytvoříš odkaz.

Btw lepší by bylo

class Helper extends Nette\Object
{
    /** @var Nette\Application\Application */
    protected $application;

    /** @var App\Repository */
    protected $repository;

    public function __construct(Nette\Application\Application $application, App\Repository $repository)
    {
      $this->application = $application;
      $this->repository = $repository;
    }

	...

Editoval Filip Klimeš (26. 3. 2015 10:36)

aRagornol
Člen | 17
+
0
-

ano upravit model je jedno z rieseni na ktore som myslel. cisto z teoretickeho hladiska ma zaujimalo ci by to bolo mozne spravit aj inak. samozrejme nie je problem v modely spravit replace pred poslanim dat do sablony. – btw pouzivam uz 2.3.0 takze ten Helper som musel vymazat / uviedol som ho len na ukazku.

greeny
Člen | 405
+
0
-

Vyrob si službu, nějak takhle:

class TextParser
{
	private $linkGenerator;
	private $dogRepository;

	public function __construct(LinkGenerator $linkGenerator, DogRepository $dogRepository) {
		$this->linkGenerator = $linkGenerator;
		$this->dogRepository = $dogRepository;
	}

	public function parse($text) {
		$dogRepository = $this->dogRepository;
		$linkGenerator = $this->linkGenerator;
		Strings::replace('~\[dog\](\w+?)\[\\dog\]~', function ($matches) use ($dogRepository, $linkGenerator) {
			$dog = $dogRepository->find($matches[1]);
			if (!$dog) {
				return 'Unknown dog ' . $matches[1];
			} else {
				return Html::el('a', [
					'href' => $linkGenerator->link(':Dog:detail', ['id' => $dog->id]),
				])->setText($matches[1]);
			}
		}
	}
}

Tu si zaregistruj do config.neon pod services.

Potom tím protáhni ten text ještě před předáním do šablony.

Editoval greeny (26. 3. 2015 10:42)

Filip Klimeš
Nette Blogger | 156
+
0
-

Doporučuju jít cestou modelu. Je to čistější a z dlouhodobého hlediska udržitelnější.

Jasně, jen jsem chtěl demonstrovat, že bys neměl přistupovat přes aplikaci na presenter, pak přes presenter na context a přes context až k repozitáři (porušuješ Dependency inversion principle). Raději si o služby řekni napřímo v konstruktoru. (a jestli už jsi na 2.3, můžeš používat LinkGenerator místo Application).