我最近使用mssql驱动程序将一个大型php应用程序从使用mssql_
函数移动到PDO函数。
我写了simple library,允许替换。考虑到这一切似乎都很好。
然而有一点令人讨厌的是数字的默认格式,特别是在数据库中定义为钱的数字。
我以前的大多数智能模板页面只输出数据来自数据库,因此某些平衡可能会显示为
125.00
但是,由于更改为PDO,因此返回
125.0000
这有点令人烦恼,但是显然不是世界末日。
我的问题。是否有解决方法/技巧/格式化常量或方法,我可以使用它来使PDO以不同的方式格式化值,或者我是否需要在整个应用程序中为每个模板中的每个数字手动设置格式?
答案 0 :(得分:1)
基本上,我要做的是创建表示每个表的结果集的模型,并使用PDO::FETCH_CLASS
将数据加载到相应类的实例中。例如:
class UserTable //extends AbstractTable <-- see below
{
protected $id = null;
protected $name = null;
protected $email = null;
protected $money = null;
}
然后添加格式化/验证数据的getter和setter,例如:
public function getMoney()
{
return sprintf('%.2f', $this->money);//check if not null first, obviously
}
接下来,为这些模型提供一个抽象类,并在其中实现the ArrayAccess
interface。例如,使用简单的映射数组:
protected $getterMap = [
'email' => 'getEmail',
'id' => 'getId',
'money' => 'getMoney',
];
在每个孩子中定义一个量身定制的地图,然后让抽象类像这样使用它:
//in abstract class AbstracTable implements ArrayAccess
public function offsetGet($offset)
{
if (!isset($this->getterMap[$offset])) {
throw new RuntimeException(
sprintf('%s not a member of %s', $offset, get_class($this));
);
}
$getter = $this->getterMap[$offset];
return $this->{$getter}();//use the getter, it formats the data!
}
对界面中的所有4种方法执行类似的操作,现在可以使用它:
$row = $stmt->fetch(PDO::FETCH_CLASS, 'User');
$row['money'];//will call getMoney, and return the formatted number
更完整的例子:
abstract class AbstractTable implements ArrayAccess
{
protected $id = null;//very likely to be defined in all tables
protected $getterMap = [
'id' => 'getId',
];
protected $setterMap = [
'id' => 'setId',
];
//force child classes to define a constructor, which sets up the getter/setter maps
abstract public function __construct();
public offsetExists($offset)
{
return isset($this->getterMap[$offset]);
//optionally, check if value if not null: isset($arr['keyWithNullVal']) returns null, too:
return isset($this->getterMap[$offset]) && $this->{$offset} !== null;
}
public offsetGet ( mixed $offset )
{
if (!isset($this->getterMap[$offset])) {
throw new RuntimeException('member does not exist');
}
$getter = $this->getterMap[$offset];
return $this->{$getter}();
}
public offsetSet($offset, $value )
{
if (!isset($this->setterMap[$offset])) {
throw new RuntimeException('Trying to set non-existing member');
}
$setter = $this->setterMap[$offset];
$this->{$setter}($value);
}
public offsetUnset ($offset)
{
//same as setter, but call:
//or just leave blank
$this->{$setter}(null);
}
}
class UserTable extends AbstractTable
{
//protected $id = null; in parent already
protected $name = null;
protected $email = null;
protected $money = null;
public function __construct()
{
$fields = [
'name' => 'etName',
'email' => 'etEmail',
'money' => 'etMoney',
];
foreach ($fields as $name => $method) {
$this->getterMap[$name] = 'g' . $method;
$this->setterMap[$name] = 's' . $method;
}
}
}
显然,您必须为所有字段编写getter和setter。不过不用担心:大多数IDE只需点击一下按钮就可以帮助生成预定义属性的getter和setter