Ako preniest do komponenty model, popripade dalsiu sluzbu

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

Zdravim, viete mi poradit? Ako viem preniest do komponenty model alebo nejaku spuzbu bez predavania v tovarnicke presenteru? Problem je v tom ze ked sa to snazim pridat do neonu ako:

userFormControl: UserFormControl(@users)

tak to neprejde lebo mi stale da na zaciatok:

$control = new \UserFormControl($this, $name);

Presenter

protected function createComponentEditUser($name) {
    $control = new \UserFormControl($this, $name);
    return $control;
}

Komponenta

class UserFormControl extends BaseFormControl {
// a sem by som potreboval dostat
//\Nette\Mail\SmtpMailer
// Users
}

Neon

common:
	parameters:
		smtp:
			smtp: true
			host: 'smtp-....'
			username: 'admin@....'
			password: '......'
			secure: 'ssl'
	nette:
		mailer: %smtp%
	services:
		users: Users
David Ďurika
Člen | 328
+
0
-

neon

services:
	favoritePanelComponent: Components\Front\FavoritePanel

prezenter

<?php
	/**
	 * @return \Components\Front\FavoritePanel
	 */
	protected function createComponentFavoritePanel()
	{
		return $this->getService('favoritePanelComponent');
	}
?>

componenta

<?php
class FavoritePanel extends Components\BaseControl {

	protected $favorite;
	protected $favoritesLists;

	public function __construct(Models\Favorite $favorite, Models\FavoritesLists $favoritesLists) {
		list($this->favorite, $this->favoritesLists) = func_get_args();
		parent::__construct();
	}
}
?>

do somponenty nepredavaj $this a $name staci ak pouzijes tovarnicku

enumag
Člen | 2118
+
0
-

@achtan: Je v pořádku to getService? Připadá mi to totéž jako $this->context.

studna
Člen | 181
+
0
-

Ono když už máš tu komponentu jako službu v kontejneru, tak je na tobě, jestli použiješ ->getService a nebo inject* metodu v presenteru.

Použití kontextu je podle mě na místě, protože na službu/komponentu sáhneš až tehdy, kdy ji skutečně potřebuješ.

Editoval studna (16. 11. 2012 18:31)

leninzprahy
Člen | 150
+
0
-

Já jsem si v BasePresenteru přetížil createComponent() asi takto

/** @var \Nette\DI\Container */
private $container;

/**
 * @param \Nette\DI\Container $container
 */
public function injectContainer(\Nette\DI\Container $container)
{
	$this->container = $container;
}

/**
 * Component factory.
 *
 * @param  string      component name
 * @return IComponent  the created component (optionally)
 */
public function createComponent($name) {
	$component = parent::createComponent($name);

	foreach (array_reverse(get_class_methods($component)) as $method) {
		if (substr($method, 0, 6) === 'inject') {
			$this->container->callMethod(array($component, $method));
		}
	}

	return $component;
}

a v komponentě pak jde normálně používat (za předpokladu že komponentu vytváříš továrničkou)

class UserFormControl extends BaseFormControl {
	// a sem by som potreboval dostat
	//\Nette\Mail\SmtpMailer
	// Users

	/** @var Namespace\User */
	private $user;

	/** @var Nette\Mail\SmtpMailer */
	private $mailer;

	public function injectUser(Namespace\User $user)
	{
		$this->user = $user;
	}

	public function injectMailer(Nette\Mail\SmtpMailer $mailer)
	{
		$this->mailer = $mailer;
	}

}

Editoval leninzprahy (16. 11. 2012 19:01)

duskohu
Člen | 778
+
0
-

a ked chcem poslat komponente napr ID z presentra, tak cez setter?

David Ďurika
Člen | 328
+
0
-

@enumag: to bol len priklad snazim sa dodrziavat to ze nepouzivam context ani getService(), ale to co vravel @studna je tiez pravda…

@leninzprahy super napad!

enumag
Člen | 2118
+
0
-

@achtan: No právě – pokud to byl jenom příklad, jak bys to řešil bez toho? Osobně nevím.

David Ďurika
Člen | 328
+
0
-

@enumag bud si v prezentry injectnes tu componentu ale potom to uz nebude tak lazy… alebo si spravis factory na tu componentu, tym padom injectujes len factory a samotna componenta sa vytvory az v monente ked ju naozaj potrebujes…

enumag
Člen | 2118
+
0
-

@achtan: Řekl bych že jestli se injectuje továrna nebo samotná komponenta už vyjde celkem podobně (tedy samozřejmě záleží na závislostech té komponenty). :-) Díky, myslím, že v tomhle případě v klidu zůstanu u způsobu od @leninzprahy.

pekelnik
Člen | 462
+
0
-
public function __construct(Models\Favorite $favorite, Models\FavoritesLists $favoritesLists) {
	list($this->favorite, $this->favoritesLists) = func_get_args();
	parent::__construct();
}

Tak tohle jsem jeste nevidel ;)

David Ďurika
Člen | 328
+
0
-

co presne ? narazas na ten list? setri to miesto…

pekelnik
Člen | 462
+
0
-

nerad bych tady rozjizdel nejakej offtopic flame – takze jenom poznamka: citelnost mi prijde dulezitejsi nez uspora jednoho odradkovani…

David Ďurika
Člen | 328
+
0
-

@enumag az na to ze potom prides o lazy load tej componenty, v tom priklade co uvadza @leninzprahy je komponenta injectovana a inicializovana stale ked sa zavola prezenter… coz je zbytocne…

enumag
Člen | 2118
+
0
-

@achtan: Myslím, že sis špatně prohlédl ten zdroják. Do presenteru injectuje @container (což mi připadá zbytečné), ne komponentu.

Ve výsledku chci použít akorát tohle:

/**
 * Component factory.
 *
 * @param  string      component name
 * @return IComponent  the created component (optionally)
 */
public function createComponent($name) {
	$component = parent::createComponent($name);
	$this->context->callInjects($component); //vyžaduje Nette 2.1
	return $component;
}
David Ďurika
Člen | 328
+
0
-

jaj mas pravdu, prehliadol som to…

leninzprahy
Člen | 150
+
0
-

Je fakt že se tam ten container injektuje zbytečně, protože už tam je jako context…

v Base presenteru by to pak mohlo vypadat

/**
 * Component factory.
 *
 * @param  string      component name
 * @return IComponent  the created component (optionally)
 */
public function createComponent($name) {
    $component = parent::createComponent($name);

    foreach (array_reverse(get_class_methods($component)) as $method) {
        if (substr($method, 0, 6) === 'inject') {
            $this->context->callMethod(array($component, $method));
        }
    }

    return $component;
}

Jinak context->callInjects(...); vypadá dobře, po přechodu na 2.1 si to určitě upravím

enumag
Člen | 2118
+
0
-

Jojo, já mám tu (ne)výhodu, že jsem to čekání psychicky nevydržel a 2.1-dev už celkem dlouho používám. :-D A taky PHP 5.4. :-)

enumag
Člen | 2118
+
0
-

Má původní verze pro Nette 2.1 obsahuje bug, takže kdyby to někdo hledal tak takhle:

	/**
	 * Component factory.
	 *
	 * @param string $name
	 * @return IComponent
	 */
	protected function createComponent($name)
	{
		$component = parent::createComponent($name);
		if ($component) {
			$this->getContext()->callInjects($component);
		}
		return $component;
	}