Komponenty a předávání závislostí

Fakjo
Člen | 7
+
0
-

Zdravíčko,

chtěl bych se zeptat spíše na námět, jak to řešíte. V podstatě se ptám na BasePresenter vs. BaseKomponenta.

Ukážu na příkladu (berte to jenom demonstračně):

use App\Helper\ImportantService;

abstract class BasePresenter extends App\Presenters\BasePresenter
{
	/** @var ImportantService @inject */
    public $importantService;
}

class AnotherPresenter extends BasePresenter
{
	public function doAny(): void
	{
		$this->importantService->doAny(); // Je dostupná v pohodě a nemusí se dělat okliky přes konstruktor
	}
}

Jenže komponenta:

use App\Helper\ImportantService;

abstract class BaseControl extends UI\Control
{
	/** @var ImportantService @inject */
    protected $importantService;

	public function __construct(ImportantService $importantService)
	{
		$this->importantService = $importantService;
	}
}

class AnotherControl extends BaseControl
{
	// Jak udělat, abych si v této komponentě injectnul nějakou nedůležitou službu, kterou bude používat jen tato třída?
}

Dokáži si představit, že buď všechno nasypu do BaseControl, jenže to je prasárna. Jak teď jednoduše si vyžádám jednu nedůležitou službu a zároveň budu mít dostupnou i tu důležitou z té BaseControl?

Co třeba takto (nezkoušel jsem, jen myšlenka):

use App\Helper\NonImportantService;

class AnotherControl extends BaseControl
{
	/** @var NonImportantService @inject */
    protected $nonImportantService;

	public function __construct(NonImportantService $nonImportantService)
	{
		parent::__construct();
		$this->nonImportantService = $nonImportantService;
	}

	public function doAny(): void
    {
        $this->importantService->doAny(); // bude OK?
		$this->nonImportantService->doAny(); // bude OK?
    }
}

Je to správný postup, idea? Nebude to házet chybu při volání toho rodičovského konstruktoru bez parametru?

Děkuji předem za odpovědi.

Editoval Fakjo (22. 8. 2019 18:34)

Ondřej Kubíček
Člen | 494
+
0
-

volání parent::__construct(); bez toho parametru ti samozřejmě vyhodí error

Ondřej Kubíček
Člen | 494
+
0
-

jinak teda ty si můžeš povolit inject přes annotaci

-
    class: AnotherControl
    inject: true

takže můžeš pak jak v presenteru a nepotřebuješ constuctor

	/** @var NonImportantService @inject */
public $nonImportantService;

ale jako neříkám že to je nejlepší řešení

Fakjo
Člen | 7
+
0
-

Chápu, ale spíše bych se vyhnul tomu konfigu..

use App\Helper\ImportantService;
use App\Helper\NonImportantService;

public function __construct(NonImportantService $nonImportantService)
{
	parent::__construct(ImportantService $importantService);
	$this->nonImportantService = $nonImportantService;
}

Takže takhle jo? To je dost nepohodlné.

Editoval Fakjo (22. 8. 2019 18:54)

filsedla
Člen | 101
+
0
-

Jak tvoříš komponenty? Nějak bez configu?

Editoval filsedla (22. 8. 2019 19:29)

CZechBoY
Člen | 3608
+
+1
-

Co to je za službu že ji potřebuješ v každý komponentě? Já mám BaseComponent jen kvůli zjišťování cesty k šabloně, jinak tam nic jinýho nemám.

MajklNajt
Člen | 470
+
0
-

Fakjo napsal(a):

Chápu, ale spíše bych se vyhnul tomu konfigu..

use App\Helper\ImportantService;
use App\Helper\NonImportantService;

public function __construct(NonImportantService $nonImportantService)
{
	parent::__construct(ImportantService $importantService);
	$this->nonImportantService = $nonImportantService;
}

Takže takhle jo? To je dost nepohodlné.

takto ti to nebude fungovať, musíš si v podedenom konštruktore vyžiadať obe závislosti:

<?php
public function __construct(ImportantService $importantService, NonImportantService $nonImportantService)
{
    parent::__construct($importantService);
    $this->nonImportantService = $nonImportantService;
}
?>

Editoval MajklNajt (22. 8. 2019 19:43)

Gappa
Nette Blogger | 198
+
0
-

Nehodil by se tady decorator?

Fakjo
Člen | 7
+
+1
-

CZechBoY napsal(a):

Co to je za službu že ji potřebuješ v každý komponentě? Já mám BaseComponent jen kvůli zjišťování cesty k šabloně, jinak tam nic jinýho nemám.

Ahoj, například nějaký Logger pro storage dat. Nebo já nevím třeba \Kdyby\Translation\Translator. Tohle všechno se mi hodí pro používání ve všech komponentách :)

Fakjo
Člen | 7
+
0
-

MajklNajt napsal(a):

Fakjo napsal(a):

Chápu, ale spíše bych se vyhnul tomu konfigu..

use App\Helper\ImportantService;
use App\Helper\NonImportantService;

public function __construct(NonImportantService $nonImportantService)
{
	parent::__construct(ImportantService $importantService);
	$this->nonImportantService = $nonImportantService;
}

Takže takhle jo? To je dost nepohodlné.

takto ti to nebude fungovať, musíš si v podedenom konštruktore vyžiadať obe závislosti:

<?php
public function __construct(ImportantService $importantService, NonImportantService $nonImportantService)
{
    parent::__construct($importantService);
    $this->nonImportantService = $nonImportantService;
}
?>

No právě a tomuhle se chci vyhnout, když si to představím, že to používám u X komponent. :-/

Fakjo
Člen | 7
+
0
-

Gappa napsal(a):

Nehodil by se tady decorator?

Ahoj, zkus navázat příkladem na to mé, ať vidíme to použití. Není to co psal Ondřej Kubíček?

Fakjo
Člen | 7
+
+2
-

CZechBoY napsal(a):

Co to je za službu že ji potřebuješ v každý komponentě? Já mám BaseComponent jen kvůli zjišťování cesty k šabloně, jinak tam nic jinýho nemám.

Zároveň si myslím, že tvořit ,,BaseKomponentu" je tak trochu anti-pattern (špatný návrh) …

Editoval Fakjo (23. 8. 2019 10:56)

Gappa
Nette Blogger | 198
+
0
-

Fakjo napsal(a):

Gappa napsal(a):

Nehodil by se tady decorator?

Ahoj, zkus navázat příkladem na to mé, ať vidíme to použití. Není to co psal Ondřej Kubíček?

Tak trochu, ale ne úplně – prostě se tam předá přesně daná závislost.

abstract class BaseControl extends Control
{
	/** @var MyService */
	protected $myService;


	public function setMyService(MyService $myService): void
	{
		$this->myService = $myService;
	}
}

config.neon

services:
	myService: App\MyService


decorator:
   	BaseControl:
        setup:
            - setMyService(@myService)

Píšu to po paměti bez testování, tak to nemusí nutně fungovat na první dobrou :)

CZechBoY
Člen | 3608
+
0
-

Prekladac se da jeste chapat (na to pouzivam decorator di extension). logger je statickej v nette, nebo mas na mysli jinou uroven logovani?

Fakjo
Člen | 7
+
0
-

CZechBoY napsal(a):

Prekladac se da jeste chapat (na to pouzivam decorator di extension). logger je statickej v nette, nebo mas na mysli jinou uroven logovani?

Vlastní řešení, které loguje speciálně entity.