Formatowanie łańcuchów znaków w języku PHP często jest mało użyteczne, a sam zapis takiego kodu niezbyt przejrzysty.
W Pythonie realizowane jest to znacznie lepiej i przykładowy kod takiego rozwiązania wygląda tak:
print "Hello %(name)s. Your %(name)s has just been created!" % { 'name' : 'world' } # Hello world. Your world has just been created!
W powyższym przykładzie widać, że argumenty, które mają zostać zamienione na podany przez nas łańcuch znaków są nazwane i wielokrotne ich występowanie nie przysparza żadnego problemu.
W PHP by osiągnąć podobny efekt musielibyśmy napisać coś takiego:
sprintf("Hello %s. Your %s has just been created!", 'world', 'world'); // Hello world. Your world has just been created!
Zgodzicie się pewnie ze mną, że gdyby powyższy przykład zawierał kilka zdań więcej i wielokrotne występowanie różnych argumentów, to tworzenie takiego kodu oraz jego czytelność pozostawiałyby wiele do życzenia, a na pewno sprawiały trudności podczas późniejszej modyfikacji.
Możemy wprawdzie użyć takiej konstrukcji:
printf('Hello %1$s. Your %1$s has just been created!', 'world');
.., ale tutaj także nie mamy argumentów nazwanych.
Jednak takie rozwiązanie jest osiągalne i przykład takiego kodu znalazłem w oficjalnej dokumentacji PHP na stronie: http://www.php.net/manual/en/function.vsprintf.php
W tym wypadku wykorzystana zostanie funkcja vsprintf, która różni się tym od funkcji sprintf, że zamiast podawania bezpośredniego argumentów po przecinku, przyjmuje ona tablicę takich argumentów.
function dsprintf() { $data = func_get_args(); // pobieramy wszystkie argumenty przekazane do funkcji $string = array_shift($data); // nasz lancuch znakow jest pierwszym argumentem if (is_array(func_get_arg(1))) { // jezeli drugim argumentem jest tablica - uzywamy jej $data = func_get_arg(1); } $used_keys = array(); // pobieramy argumenty z lancucha znakow i przekazujemy je do naszej kolejnej funkcji $string = preg_replace('/\%\((.*?)\)(.)/e', 'dsprintfMatch(\\'$1\\',\\'$2\\',\\$data,$used_keys)', $string); $data = array_diff_key($data,$used_keys); // diff the data with the used_keys return vsprintf($string,$data); // yeah! } function dsprintfMatch($m1,$m2,&$data,&$used_keys) { if (isset($data[$m1])) { // sprawdzamy czy dany klucz istnieje w przekazanej tablicy argumentow $str = $data[$m1]; $used_keys[$m1] = $m1; // nie usuwamy wystapienia - moze wystepowac wiele razy return sprintf("%".$m2,$str); // uzywamy sprintf na lancuchu znakow, wiec %s lub %d dzialaja tak jak powinny } else { return "%".$m2; // w przeciwnym wypadku uzywamy %s lub %d - w zaleznosci od wykorzystania } } $str = <<<HITHERE Hello, %(firstName)s, I know your favorite funcion is %(functionName)s. HITHERE; $dataArray = array( 'firstName' => 'PHP', 'functionName' => 'var_dump()', ); echo dsprintf($str, $dataArray); // Hello, PHP, I know your favorite function is var_dump().