Perhaps you could use anonymous functions, such that the free variables are bound as parameters in the anonymous function, which returns a string with the values populating the free variables. This would work well in conjunction with the extract function inside a closure, wherein the keys from your array become real variables within a local scope necessary to evaluate the variables referenced in the format string.
Or there is probably a relatively simple version using eval
(this is just an illustration, not tested code):
function named_printf ($format_string, $values) {
extract($values);
$result = $format_string;
eval('$result = "'.$format_string.'";');
return $result;
}
echo named_printf ('Hello $msg', array('msg'=>'World'));
PHP's scope control mechanisms are a bit scary, so you may want to verify that this isn't going to leak variables into scope all over the place. It'd also be worth santising input.