In daily development, we often use the sprintf function to format strings, such as outputting numbers with fixed decimal points, aligning the output content, etc. However, if we can "automate" this formatting logic, that is, automatically formatting through the object's meta-information (such as the class's properties and format description), it will greatly improve the flexibility and maintainability of the code.
PHP's Reflection API provides a mechanism to analyze classes, properties, and methods at runtime. Combined with the powerful formatting capabilities of sprintf , we can implement an "automatic formatting tool", which can format and output objects based on annotations or naming conventions in class properties.
We want to achieve the following effects:
$user = new User('Alice', 5, 1234.5678);
echo AutoFormatter::format($user);
The output result is similar to:
Name: Alice | Level: 005 | Balance: $1234.57
Where the format is determined by the definition of the class, rather than hard-coded in the formatting function.
We use PHP 8 Attributes to add formatting instructions to the attributes of the class.
#[Attribute]
class Format {
public function __construct(public string $format) {}
}
class User {
#[Format('%-10s')] // Left aligned,occupy10Bit
public string $name;
#[Format('%03d')] // Integer,Replenish zero to3Bit
public int $level;
#[Format('$%.2f')] // 保留两Bit小数,And add the dollar sign
public float $balance;
public function __construct($name, $level, $balance) {
$this->name = $name;
$this->level = $level;
$this->balance = $balance;
}
}
We use reflection to read properties, their corresponding formats, and generate formatted strings.
class AutoFormatter {
public static function format(object $obj): string {
$refClass = new ReflectionClass($obj);
$values = [];
$formats = [];
foreach ($refClass->getProperties() as $prop) {
$prop->setAccessible(true);
$value = $prop->getValue($obj);
$attrs = $prop->getAttributes(Format::class);
if (!empty($attrs)) {
$formatAttr = $attrs[0]->newInstance();
$formats[] = $formatAttr->format;
$values[] = $value;
}
}
$formatString = implode(' | ', $formats);
return sprintf($formatString, ...$values);
}
}
$user = new User('Alice', 5, 1234.5678);
echo AutoFormatter::format($user);
// Output:Name: Alice | Level: 005 | Balance: $1234.57
If you want to apply on the web interface, you just need to return the formatted result:
header('Content-Type: text/plain');
echo AutoFormatter::format(new User('Bob', 42, 98765.4321));
You can also use these formats for logging, template rendering, or API response. For example:
file_put_contents('https://gitbox.net/logs/user.log', AutoFormatter::format($user), FILE_APPEND);
By combining PHP's sprintf and Reflection , we can extract the formatting logic from the application code to achieve highly decoupled and configurable automatic formatting functions. This not only makes the code more elegant, but also provides great convenience for future format changes.
This method is especially suitable for scenarios such as logging, exporting, and reporting that require unified format output.