ORM设计

首希望本文的读者拥有一定的ORM框架设计经验,或者熟悉ORM原理,最好是自己动手实现过ORM映射
如果没有请参考Doctrine或者Zend DB实现
在传统的ORM框架中都会有这样一个需求:"将一个一维数组或二维数组插入或替换到数据库中"
关于一维数组的处理这里不讨论,这里只关心二维数组
如下一个二维数组(这里使用php编码比较通俗易懂),假设某张表有三个字段 a,b,c
$arr=array(
array(
'a'=>1,
'b'=>2,
),
array(
'a'=>3,
'b'=>4,
)
);
这种数组每一维键和键顺序完全相同 只要取出第一维键值作为 INSERT INTO `table_name`(#####) 括号里的键值 然后把所有维的值拼起来作为
VALUES部分就解决了,问题是不是所有程序员都会遵循使用规则,有可能传给你一个这样的数组
$arr=array(
array(
'a'=>1,
'b'=>2,
),
array(
'a'=>3,
'b'=>4,
'c'=>5,
)
);
这样就会导致那个SQL初学者常见的columns does not match values错误,这时候我们应该使用一个函数判断一个函数是否是完全符合二维数组标准,类似如下
function is_standard_2darray($array)
{
$current=current($array);
//第一维必须为数组
if(is_array($current))
{
//这里使用crc32作为唯一校验,当然也可以不用
$crc=crc32(join('', array_keys($current)));
foreach ($array as $k=>$v)
{
$lcrc=crc32(join('', array_keys($v)));
if($lcrc!=$crc)
{
return FALSE;
}
}
}else{
return FALSE;
}
return TRUE;
}
这样可以检测到数组是否是标准二维数组,如果是那直接用第一种方法处理,如果不是那就需要将数组进行按键值分类,使用类似如下函数
function classify($array) {
$ret = array ();
$current = current ( $array );
if (is_array ( $current )) {
foreach ( $array as $k=>$v )
{
$lcrc = crc32 ( join ( '', array_keys ( $v ) ) );
//按数组键值CRC进行分类可以保证顺序也是对的
!isset($ret[$lcrc])&&$ret[$lcrc]=array();
$ret[$lcrc][]=$v;
}
}
return $ret;
}
这样将一个二维数组变成一个三维数组,其中每个第二维都是一个整理好的可以一次性插入而数据库不会报错的数据
然后遍历该数组将每一维作为参数再调用一下自身
完美解决PS
BTW
原本的框架设计原则是 "在易用性和可扩展性之间寻找一个平衡",关于这点我很佩服BOOST那伙人.
因为我们一开始并不知道一个系统最终是什么样子的,所以我们没办法对系统做更高程度的抽象(其实就是重构啦)
如此做的结果是虽然框架很智能,但这在耗费性能的同时还把风险留给了程序员,本来应该遵守数据一致性的原则会变的不那么严谨
姑且也算找到一个平衡点吧

This entry was posted in 默写. Bookmark the permalink.