Jak předávat model vnořeným komponentám

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

Dejme tomu že mám tři komponenty.
BandListControl
AlbumListControl
TrackListControl
Jedna vypisuje kapely, druhá alba a třetí tracky

a každé k životu stačí jeden vlastní model:
BandRepository
AlbumRepository
TrackRepository

A teď jsem tak nějak pochopil jak použít jednu v komponentu v druhé, ale pokud chci v bandlistu vypsat alba a v nich jednotlivé tracky, tak jak to dělám teď, tak se mi to moc nelíbí. Teď bandlistu předám všechny tři modely(2 zbytečně), abych je mohl předávat dalším vnořeným komponentám.

Jak to dělám teď:

class BandListControl extends Nette\Application\UI\Control {
    private $albumRepository;
    private $bandRepository;
    private $trackRepository;

    private $displayAlbums = FALSE; // pokud chci ke každé kapele vypsat alba

    public function __construct($selected, $albumRepository, $bandRepository, $trackRepository) {
        parent::__construct();
        $this->albumRepository = $albumRepository; // tohle tu mám jenom kvůli vnořené komponentě
        $this->bandRepository =  $bandRepository;
        $this->trackRepository = $trackRepository; // tohle tu mám jenom kvůli vnořené komponentě ve vnořené komponentě
    }
		.
		.
		.
    public function createComponentAlbumList(){
        return new Multiplier(function ($name){
        	.
		.
		.
		// zbytečné předávání trackRepository
        return new AlbumListControl($selected, $this->albumRepository, $this->trackRepository);
        });

    }

}

BandList.latte

<div n:if="$displayAlbums"><b>Seznam alb:
{control "albumList2-$band->id"}
</div>

Jde komponentám nějak rozumněji předávat model? Kdybych měl v sobě 5 komponent a každá vypisovala data na základě rodiče, tak v té nejvyšší budu mít 4 zbytečné modely.

Editoval newbie (12. 3. 2013 6:14)

David Matějka
Moderator | 6445
+
0
-

pro kazdou komponentu si vytvor tovarnu, kterou registrujes jako sluzbu (v dev verzi muzes pouzit DI factories, ktery ti to zjednoduseji). priklad:

//BandListControlFactory.php
//tuhle factory si injectnej do presenteru a v createComponent metode das akorat return $this->bandListControlFactory->create();

class BandListControlFactory extends Object
{

	protected $bandRepository;
	protected $albumListControlFactory;
	public function __construct(BandRepository $bandRepository, AlbumListControlFactory $albumListControlFactory)
	{

	....
	}

	public function create()
	{
		return new BandListControl($this->bandRepository, $this->albumListControlFactory);
	}
}

//BandListControl.php
class BandListControl extends Control
{

	protected $bandRepository;
	protected $albumListControlFactory;
	public function __construct(BandRepository $bandRepository, AlbumListControlFactory $albumListControlFactory)
	{
		....
	}

	public function createComponentAlbumList()
	{
		return new Multiplier($this->createAlbumListControl);
	}

	public function createAlbumListControl($name)
	{
		....
		return $this->albumListControlFactory->create($selected);
	}

}


//AlbumListControlFactory.php

class AlbumListControlFactory extends Object
{

	protected $albumRepository;
	protected $trackListControlFactory;
	public function __construct(AlbumRepository $albumRepository, TrackListControlFactory $trackListControlFactory)
	{
		...
	}

	public function create($selected)
	{
		return new AlbumListControl($selected, $this->albumRepository, $this->trackListControlFactory);
	}
}

a tak dal, cely to sem psat nebudu :) ten kod je pak mnohem lepe spravovatelnej, kdyz treba TrackListControl bude potrebovat dalsi zavislost, jen ji pridas do jeho factory

v neonu registrujes vsechny factory jako sluzby:

services:
	bandListControlFactory: BandListControlFactory
	.....

takhle ma kazda komponenta jen zavislosti na tom, co bude primo pouzivat, tzn. bandlistcontrol pouziva jen bandrepository a vytvari albumlistcontrol, o zavislosti albumlistcontrolu at se postara AlbumListControlFactory atd. :)

Editoval matej21 (12. 3. 2013 12:22)

pawouk
Člen | 172
+
0
-

Matej21 ti to napsal pěkně, jen doplním že jde o základní princip Dependency injection, tedy: nestarej se o závislosti, závislosti řeší někdo dříve. Tedy tak jak to píšeš ty prostě řešíš ty závislosti pozdě. Za druhé snaž se aby v tvém kódu bylo co nejméně slovo new. Vlastně by tam nemělo být vůbec. Výjimku tvoří Exception a třeba ArrayHash, to je defakto to samé jako array. Když si uvědomíš, že závislosti musíš řešit dříve mohl bys předávat hotové objekty a model do nich strčit už na začátku aplikace, ale to by bylo neefektivní, takže je lepší dělat továrny a tím je zjištěno že se vytvářejí až když jsou skutečně potřeba.

newbie
Člen | 31
+
0
-

Tušil jsem, že to bude něco s továrnami, ale v dokumentaci jsem nenašel snad nic. Jenom tu a tam nějaká informace v diskuzích, co si začátečník moc nedá dohromady. Moc pěkně napsané a vysvětlené. Díky.

Filip Procházka
Moderator | 4668
+
0
-

Tohle nepomohlo? :)

ViPEr*CZ*
Člen | 817
+
0
-

Filip Procházka napsal(a):

Tohle nepomohlo? :)

Si myslím, že na planette ty lidi ze začátku moc nechodí… spíš to hledáš v dokumentaci jako takový, když se něco učíš. Navíc to je návod pro 2.1-dev a někteří lidi prostě rádi slyší na něco jako stable, i když spousta místních bere 2.1-dev jako samozřejmost.
(osobní názor)