Write-once properties pomocí Nette\Object

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Filip Procházka
Moderator | 4668
+
0
-

Davide,
na phpfashion jsi psal o úžasné technice, kterou by čím dál víc lidí strašně rádo vidělo v Nette.

Plánuješ to do Nette? Je s tím nějaký konkrétní problém? Nebo jenom není čas?

pawouk
Člen | 172
+
0
-

Také se přikláním. Sám jsi psal že injektování metodami znamená spousta psaní kodu navíc (souhlasím) a zdá se, že nette se tímto směrem vydává. Proč? už jsem na to narážel zde: https://forum.nette.org/…enterfactory

Jan Endel
Člen | 1016
+
0
-

+1

jtousek
Člen | 951
+
0
-

Souhlasím, také se mi složité injektování přes metody moc nezamlouvá. Navíc by šlo implementovat i podporu lazy vytváření služeb až když jsou opravdu potřeba (ne při vytváření objektu, který je potřebovat může).

EDIT: Druhá možnost je aby ty inject metody přidával RobotLoader pomocí filteru.

Editoval jtousek (20. 9. 2012 12:45)

pawouk
Člen | 172
+
0
-

Druho možnost teda moc nechápu… kde bych jako definoval závislosti a jak?

jtousek
Člen | 951
+
0
-

U property bys měl anotaci @inject a RobotLoader by k tomu vygeneroval inject metody. Ale nejsem si úplně jistý jestli by to opravdu šlo – ty inject metody nepoužívám.

vvoody
Člen | 910
+
0
-

islo, ten filter som si vytvoril ale nemyslim ze by to mal byt doporucovany sposob injectovania v nette

$rl->filters['php'] = function($input){
	$code = '';
	$class = '';
	$var = '';
	$findNextVariable = false;
	$skipNextToken = false;
	$injectServiceFormat ='

	public function inject%s(%s $service)
	{
		$this->%s = $service;
	}';

	foreach (@token_get_all($input) as $token) {

		// skip semicolon
		if($skipNextToken){
			$skipNextToken = false;

		// nonspecial tokens
		}elseif(!is_array($token)){
			$code .= $token;

		// comment with @inject
		}elseif($token[0] == T_DOC_COMMENT && strpos($token[1],'@inject')!==FALSE){
			$code .= $token[1];
			if(1 === preg_match('/@var\s+(?<class>\\\?[a-zA-Z]+(\\\[a-zA-Z]+)*)\s*\n/',$token[1],$matches)){
				$class = $matches['class'];
				$findNextVariable = true;
			}

		// first variable after @inject comment
		}elseif($findNextVariable && $token[0] == T_VARIABLE){
			$code .= $token[1];
			if (1 === preg_match('/\s*\$(?<var>[a-zA-Z]+)\s*/', $token[1], $matches)) {
				$var = $matches['var'];
				$findNextVariable = false;
			}
			$code .= ';';
			$code .= sprintf($injectServiceFormat, ucfirst($var),$class,$var);
			// skip already added semicolon
			$skipNextToken = true;

		// other tokens
		}else{
			$code .= $token[1];
		}
	}
	return $code;
};
David Grudl
Nette Core | 7569
+
0
-

Kliknul jsem na odkaz a musím říct, že design phpFashion vypadá fakt moc dobře!

ad injektáž: zůstal bych u konstruktoru. Berte to tak, že 99 % lidí DI nerozumí a nejprve by měli zvládnou konstruktor injection, až potom přidávat zkratky. Navíc to není bezproblémové.

pidiclovek
Člen | 91
+
0
-

Všichni shodli na tom, že konstruktor injection nelze používat vždy. Dle mého by byla ideální a transparentní, bez nutné magie, možnost anotovat @inject jen veřejné properties, nevidím v tom problém. DI spousta lidí nechápe, pravda. DI znamená více psaní, to je také pravda, ale tohle by opravdu pomohlo. Co by člověk potřeboval do privátní, musel by si napsat sám.

A phpFashion opravdu dobře vypadá :))

/** @edit */
Což by ale taky asi vedlo k tomu, že by všichni rvali závislosti do veřejných fieldů. To taky neni ideální. Co myslíte?

Editoval pidiclovek (20. 9. 2012 17:40)

jtousek
Člen | 951
+
0
-

Přesně tak, používání těch public proměnných myslím nikoho nezmate. Ta „magie“ pod tím by jen zajistila neměnnost a typovou kontrolu.

Davide, tím, že to není bezproblémové máš na mysli tu nemožnost přepsání konstruktoru s nižší viditelností v poděděné třídě? To bych jako problém opravdu neviděl. Statické třídy jako Nette\Strings stejně používají final public __construct, vyhazující Exception. A pokud máš na mysli vytváření objektu pouze pomocí statické továrny ve stejné třídě tak to mi nepřipadá moc čisté, takže bych to stejně nikde nepoužil.

Pokud jsi myslel něco jiného, není mi jasné co.