Jak nejlíp nahradit $GLOBALS v Nette

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

Zdravím, upgraduju CMS z Nette 2.0 beta na 2.0.10 a snažím se o striktní DI. Konkrétně řeším, čím nahradit $GLOBALS, které se v aplikaci zatím používaly, a to pokud možno tak, aby to bylo co nejčistší, ale zároveň nebylo nutné kvůli tomu předávat všude celý container. Napadají mě dva způsoby řešení:

  1. Použít container[‚parameters‘] – pro každou původně globální proměnnou přidat nový parametr, který by byl defaultně prázdný a naplnil se až za běhu. Nevím ale, nakolik se tohle řešení shoduje s účelem containeru, připadá mi, že parameters by měly sloužit spíš k načtení konfigurace než k předávání proměnných mezi moduly.
  2. Použít služby – pro každou původně globální proměnnou napsat třídu (je jich jen pár a jsou to všechno objekty, takže by to snad nebyla až taková zvrhlost jako psát třídu třeba pro nějaký string). (Nebo případně jednu službu, která by uchovávala všechny původně globální proměnné, ale to už je asi prakticky totéž jako použít $GLOBALS, ne?). To by se mi i celkem líbilo, nebýt toho, že pokud se nepletu, k volání služby potřebuju mít dostupný container a předávat celý container všude, kde se původně používaly globální proměnné, se mi nechce.

Jaké by bylo v tomhle případě nejlepší řešení? Uvažuju správným směrem? Nebo mi něco uniká?

Filip Procházka
Moderator | 4668
+
0
-

Chápu správně, že jsi měl v globals parametry a objekty? Měl by jsi je nahradit službami, tyto služby registrovat do DI Containeru a předávat si je do konkrétních objektů.

Takže né

class Article
{
	function save($title, $content)
	{
		$GLOBALS['db']->insert(...);
	}
}

ani

class Article
{
	private $container;

	public __construct($container)
	{
		$this->container = $container;
	}

	function save($title, $content)
	{
		$this->container->db->insert(...);
	}
}

ale tohle

class Article
{
	private $db;

	public __construct(DibiConnection $database) // například
	{
		$this->db = $database;
	}

	function save($title, $content)
	{
		$this->db->insert(...);
	}
}
chikeet
Člen | 160
+
0
-

Sakra, tohle mi nějak nedocvaklo :-) Vytáhnout si službu z containeru na úrovni, kde mám dostupný container, a pak už jen předávat tu službu. Netřeba předávat celý container. Takže 2) je v podstatě správně.

ViPEr*CZ*
Člen | 817
+
0
-

A ještě doplním, že je třeba možno udělat z Article taky službu. A tzv. autowire se postará o to, aby při vytváření služba Article dostala jinou službu (v tomto příkladu například spojení na databázi).
A pokud by konstruktor Article měl namísto parametru instanci na objekt jen nějakou proměnnou (například řetězec), tak si ho tam můžu taktéž vztříknout v configu při vytváření služby ze třídy Article.