PHP format() function with named placeholders
Goal
Format a string by merging it with provided values using named placeholders.
Instead of writing a string with %s
placeholders using PHP's printf()
and having to line up the values in order in an array,
I would like to have named placeholders for clarity,
just like if it was a Smarty-like template,
and feed it an associative array for values.
Using %s placeholders
$string = <<<SQL
CREATE DATABASE IF NOT EXISTS %s;
GRANT ALL PRIVILEGES ON %s.* TO '%s'@'%s';
SET PASSWORD = PASSWORD('%s');
SQL;
$args = ["people", "people", "staff", "localhost", "asdf123"];
vprintf($string, $args);
printf($string, ...$args);
echo vsprintf($string, $args);
echo sprintf($string, ...$args);
Result:
CREATE DATABASE IF NOT EXISTS people;
GRANT ALL PRIVILEGES ON people.* TO 'staff'@'localhost';
SET PASSWORD = PASSWORD('asdf123');
Using named placeholders
I would prefer doing this:
$string = <<<SQL
CREATE DATABASE IF NOT EXISTS {{database}};
GRANT ALL PRIVILEGES ON {{database}}.* TO '{{user}}'@'{{host}}';
SET PASSWORD = PASSWORD('{{pass}}');
SQL;
$kwargs = ["database"=>"people", "user"=>"staff", "pass"=>"asdf123", "host"=>"localhost"];
echo format($string, $kwargs);
Advantages
- No need for duplicate values.
- Values don't have to be ordered.
Ruby's format() with named placeholders
https://docs.ruby-lang.org/en/2.5.0/Kernel.html#method-i-format
puts format("Coordinates: %{latitude}, %{longitude}", latitude: '37.24N', longitude: '-115.81W')
kwargs = {latitude: '37.24N', longitude: '-115.81W'}
puts format("Coordinates: %{latitude}, %{longitude}", **kwargs)
Result:
Coordinates: 37.24N, -115.81W
Python's format() with named placeholders
https://docs.python.org/3.5/library/string.html#format-examples
print 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
kwargs = {'latitude': '37.24N', 'longitude': '-115.81W'}
print 'Coordinates: {latitude}, {longitude}'.format(**kwargs)
Result:
Coordinates: 37.24N, -115.81W
PHP's format() with named placeholders
<?php
function format($string, array $kwargs, $pattern='/\{\{(\w+)\}\}/') {
return preg_replace_callback($pattern, function ($matches) use ($kwargs) {
return @$kwargs[$matches[1]] ?: $matches[0];
}, $string);
}
echo format("Coordinates: {{latitude}}, {{longitude}}", ['latitude'=>'37.24N', 'longitude'=>'-115.81W']);
Try with Ruby-like %{}
placeholders by changing the regex pattern (the 3rd function argument).
echo format("Coordinates: %{latitude}, %{longitude}", ['latitude'=>'37.24N', 'longitude'=>'-115.81W'], '/\%\{(\w+)\}/');
Try with Ruby-like symbol placeholders by changing the regex pattern.
echo format("Coordinates: :latitude, :longitude", ['latitude'=>'37.24N', 'longitude'=>'-115.81W'], '/:(\w+)/');
Try with Python-like single curly bracket placeholders by changing the regex pattern.
echo format("Coordinates: {latitude}, {longitude}", ['latitude'=>'37.24N', 'longitude'=>'-115.81W'], '/\{(\w+)\}/');
Result:
Coordinates: 37.24N, -115.81W
Missing value or placeholder key doesn't exist in kwargs:
echo format("Coordinates: {{latitude}}, {{longitude}}, {{timezone}}", ['latitude'=>'37.24N', 'longitude'=>'-115.81W']);
Result:
Coordinates: 37.24N, -115.81W, {{timezone}}