Co takhle datový typ String (a hezky s Fluent interface)?

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

Určitě jste již někdy dospěli do stavu, kdy jste psali něco podobného:

<?php

return str_replace(array('<', '>'), array('&lt;', '&gt;'),
		preg_replace('#\n{3,}#', "\n\n",
		preg_replace('#[ ]*[\n][ ]*#', "\n",
		preg_replace('#<.*?>#', "\n",
		preg_replace('#<script.*?</script>#sm', '',
		preg_replace('#<a.*?href=\"(.*?)\".*? >#', "\n\n$1\n\n",
	(string) $str
	))))));
?>

Fuj! Chci-li pak třeba zakomentovat jeden řádek, tak musím na konci odmazávat koncové závorky a vůbec je to celé ošklivé.

Všimněte si prosím také tohoto příkladu:

<?php

function foo(string $string) {
	return $string;
}

foo('Ahoj světe!');
?>

PHP bude celé nešťastné, že $string není třídy ‚string‘, ale že je pouze ‚string‘.

Co si tedy takhle implementovat Fluent třídu String, která podobné problémy řeší?

https://gist.github.com/1613895

Wow! Nyní tedy můžeme psát:

<?php
return String::from($str)
	->pregReplace('#<a.*?href=\"(.*?)\".*? >#', "\n\n$1\n\n")
	->pregReplace('#<script.*?</script>#sm', '')
	->pregReplace('#<.*?>#', "\n")
	->pregReplace("/[ ]*[\n][ ]*/", "\n")
	->pregReplace("/\n{3,}/", "\n\n")
	->replace(array('<' => '&lt;', '>' => '&gt;'));

?>

Volání funkcí:

<?php

function foo(String $string) {
	return $string->replace('mastná', 'nemastná');
}

$foo = foo(String::from('Vlhká, mastná.'));

?>

Což kompilátoru už nevadí!

Všimněte si proměnné $classInjection, kterou je možné do třídy předat třídu, která bude magicky volána v případě, že methoda není implementována. Tedy například:

<?php
$string = '      Tahle vyvinutá Britka patří mezi oblíbenkyně Hugha Hefnera. Podívejte se na její perfektní tělíčko   ';

$string = String::from($string)
	->replace(array('patří' => 'nepatří', 'Podívejte' => 'Nedívejte'))
	->pregReplace('#B.*?tka#', 'Američanka')
	->trim()
	->toAscii();

echo $string;
?>

Trim a toAscii jsou methody implementované v Nette\Utils\Strings a tímto způsobem je možné se jich velice snadným způsobem domoci!

Není problém doimplementovat jakoukoliv metodu, zatím na zkoušku jsem střelil pouze replace, pregReplace a iconv. Asi to chce ještě trochu učesat a ohlídat, ale jinak pěkné, že?

Editoval knyttl (15. 1. 2012 3:21)

llook
Člen | 407
+
0
-

Já bych především ten první příklad nepsal tímhle LISPovským stylem, kdo se má pak v těch závorkách vyznat:

$out = preg_replace('#<a.*?href=\"(.*?)\".*? >#', "\n\n$1\n\n", (string) $str);
$out = preg_replace('#<script.*?</script>#sm', '', $out);
$out = preg_replace('#<.*?>#', "\n", $out);
// atd.
return $out;

Jinak budeš muset dávat pozor, jestli na daném místě používáš string nebo String, mimo jiné kvůli knihovnám třetích stran. Zaneseš si kód spoustou (string) a String::from, což na přehlednosti nepřidá. Jedinou výhodu vidím v tom type hintingu, ale typ se nakonec vždycky dá zkontrolovat uvnitř funkce, pokud je ta potřeba.

22
Člen | 1478
+
0
-

Určitě jste již někdy dospěli do stavu, kdy jste psali něco podobného:

Nedospěl..

Patrik Votoček
Člen | 2221
+
0
-

knyttl napsal(a):

Určitě jste již někdy dospěli do stavu, kdy jste psali něco podobného

Nedospěl… A i kdyby tak nebudu prasátko a budu to psát tak jak píše llook.

Co se týká typehintu v metodách tak bych tě rád odkázal do příslušného vlákna v PHP internals. Kde se řešilo proč to v PHP není a nebude. Ale nemůžu ho najít :-(

a jinak tě odkážu sem https://forum.nette.org/…g-byla-trida