Archive for the '技术 Technology' Category


Category: PHP     Comments    

在Zend Framework 中使用 PDO_ODBC

其实只需要小改一下Zend_Db_Adapter_Pdo_Mssql就可以支持ODBC

function _dsn()

判断PDO Type 的时候加多一个

case 'odbc':
$this->_pdoType = 'odbc';
break;

再增加一個方法

public function quote($value)
{
if (is_int($value) || is_float($value)) {
return $value;
}
return "'".addslashes($value)."'";
}

然后,传递参数的时候参考下面的例子:

// 数据库连接参数
$params = array(
'SERVER' => "192.168.1.2"
'DATABASE' => "king",
'username' => "king",
'password' => "kingpsw",
'dbname' => "king",
'pdoType' => "odbc",
'DRIVER' => "SQL Server",
);
// 单件模式
if (!Zend_Registry::isRegistered("db")) {
$db = Zend_Db::factory('Pdo_Mssql', $params);
Zend_Registry::set("db", $db);
}else {
$db = Zend_Registry::get("db");
}

使用上面的参数会生成类似
odbc:DRIVER=SQL Server;SERVER=192.168.1.2;DATABASE=king;
这样的Data Source Name (DSN) 串,这样就会通过ODBC连接数据库了,当然要记得打开 php_pdo_odbc.dll 扩展

虽然使用ODBC驱动可以避免SQL SERVER 中VARCHAR长度超过255的限制,但是也并不是这样就可以解决问题,PDO_ODBC存在一个BUG:
http://bugs.php.net/bug.php?id=40452 上面有些评论可以参考一下
当INSERT的时候DATETIME字段会出现以下错误:

[Microsoft][ODBC 驅動程式管理員] 函數順序錯誤
Fatal error: Uncaught exception 'PDOException' with message
'SQLSTATE[HY010]: Function sequence error: 0 [Microsoft][ODBC Driver
Manager] Function sequence error (SQLExecute[0] at
ext\pdo_odbc\odbc_stmt.c:133)'

參考:http://framework.zend.com/issues/browse/ZF-905

Category: PHP     Comments    

关于Zend_Db_Adapter_Pdo_Mssql最后一分页问题的解决方法

Zend framework (我当前使用的版本是1.5) 中的MSSQL(SQL SERVER)PDO Adapter(Zend_Db_Adapter_Pdo_Mssql)分页是有问题的,多数情况最后一页总会和n-1页的记录重叠,经测试Zend Framework 1.7.0里面的Zend_Db_Adapter_Pdo_Mssql同样存在此问题

当有LIMIT的时候,分析ZF_DB生成的SQL语句:

SELECT * FROM
(
SELECT TOP 30 * FROM (
SELECT TOP 60 "package_id", "title_eng"
FROM "hotel_package" ORDER BY "package_id" DESC
) AS inner_tbl ORDER BY "package_id" ASC
)
AS outer_tbl ORDER BY "package_id" desc

上面的SQL是PAGE=2,是每页30笔记录,30就相当于MYSQL中的LIMIT,60就是OFFSET

看不懂上面的SQL的话可参考这里:
http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html

Zend_Db_Select中limitPage方法中有如下代码:

$this->_parts[self::LIMIT_COUNT]  = (int) $rowCount;
$this->_parts[self::LIMIT_OFFSET] = (int) $rowCount * ($page - 1);

显然,这个SQL的结果是每一页都是30笔,最后一页也是。
当 “hotel_package” 中有31笔记录的时候,一共有2页,翻到第2页的时候也显示30条记录是不对的
当然这不太影响使用,但是挑剔的人会提出质疑,这也无可厚非,但是怎么ZEND也不重视这个问题
或者说ZEND并不重视ZF中的MSSQL

由于ZF本身的问题,所以不得不修改ZF的代码,这种情况是在万不得已经的情况下才去做…

首先考虑是修改 Zend_Db_Adapter_Pdo_Mssql 这个类,因为是Adapter所以可以自己另存一个,改一下类和文件名,是最好的方法并不影响到ZF以后的升级更新,不过另存修改Zend_Db_Adapter_Pdo_Mssql并不现实,因为传给limit的参数有限:
limit($sql, $count, $offset = 0)
没法判断是否最后一页是否小于limit,没办法,只能把目光转移到Zend_Db_Select中的limitPage
修改如下:

public function limitPage($page, $rowCount, $tail = NULL)
if ($tail > 0 && !is_bool($tail)) {
$this->_parts[self::LIMIT_COUNT]  = (int) $tail;
}else {
$this->_parts[self::LIMIT_COUNT]  = (int) $rowCount;
}

然后在自己的分页类中,添加一个tail的返回值

// pagerInfo 保存关于分页信息的数组
$pagerInfo['_tail'] = NULL;
// 判断是否最后一页
if ($page == $pagerInfo['pagesCount']) {
// 获取余数
$tail = $rows_count % $rowCount;
if ($tail != 0)   $pagerInfo['_tail'] = $tail;
}

在目前最新的Zend Framework 1.7.0 中增加这样这两个特性
Zend_Db_Table_Select adapater for Zend_Paginator
Support for custom adapters in Zend_Paginator
看来是一个分页功能,不知道是怎样处理上面的问题的,下次再去了解一下

Category: Javascript     Comments    

MSN SPACE 图片摆放效果

研究了一下MSN SPACE好友相册更近的更新列表中的图片摆放效果,IE是用DXImageTransform.Microsoft.Matrix这个Filter去实现,代码较简单,Firefox就用了HTML5标准规范中的Canvas标签实现,代码较复杂,其它浏览器没试,不过奇怪的是微软处理不同浏览器的手法好像是不同的浏览器就调用不同的模板,就这个效果而言,相关代码是完全不一样的,肯定不是同一个模板!

花了点时间把代码提取并精简,点击这里查看

Category: PHP     Comments    

关于PHP只能读取MsSQL的char/varchar字段前256个字符的问题

很不幸地用PHP操作MsSQL(SQL Server)数据库的时候,如果您的char或者varchar字段长度超过256的话只能读取到前256个字符的内容,后面的会被无情的CUT掉,无论你用最基本的MSSQL DB库还是PDO_MSSQL,或者自己写一个专门的MSSQL DB扩展也无济于事,因为PHP操作MSSQL都是通过微软提供的SQL Server Client Library工作,也就是ntwdblib.dll 这个文件,目前“最新”版本是2000.80.194.0(需要自行去搜索下载),就算最新版本(PHP 5.3 alpha2)的PHP自带的都是这个98年的版本2000.2.8.0,“最新” 版本估计是2000年的产物(根据这个判断© 1988-2000 Microsoft Corp. 保留所有权利。)难怪2001年提交的这个BUG至今还没有被FIX

http://bugs.php.net/bug.php?id=11593

调整php.ini中的 mssql.textlimit 和 mssql.textsize 也没用,这两个参数形同虚设…

鉴于这个库的版本太老,用PHP+MsSQL这种鸡肋组合的同志们要小心了…

解决办法就是使用ODBC驱动,请参考:
在Zend Framework 中使用 PDO_ODBC

Category: Javascript     Comments    

下拉菜单手动输入

oShopZ 在线商城系统后台截图

oShopZ 在线商城系统后台截图

有时候下拉框的选项不能满足需要时需要手工输入,这情况可以在旁边再放一个INPUT和文字说明,但是比较难理解,也不美观。
我的解决办法是选择最后一个选项(option)“手工输入>>”后,此下拉框(select)就会变成文本输入框(input)

实现思路很简单,选项(option)“手工输入>>”的值是就是下拉框(select)的id名
onchage的时候调用cinput函数当检查到this.value = this.id就隐藏select加入input,点击input旁边的“x”就还原。

调用示例:

<select onchange=“cinput(this)” id=”example”>
<option value=”1″>xxxxx</option>
<option value=”example”>手工输入>></option>
</select>

当有缺省值的情况下直接调用函数

cinput($(”#example”).get(0), “ooo”);

本文章所有代码是基于JQUERY,DEMO请点击这里

// 全局变量,保存位置
var fn = {};
// item 是 select 对像
// val 是可选参数,有缺省值的时候用到
function cinput(item, val)
{
if(item.id != item.value && !val) {
// 保存原始位置
fn[item.id] = item.selectedIndex;
return;
}
// 先保存ID
var id = item.id.toString();
// 隐藏select
$("#"+id).hide();
// 获取父TAG对像用以加入input
var p = $("#"+id).parent();
// 避免冲突把select的id和name更名
$("#"+id).get(0).name = id + "_bak";
$("#"+id).get(0).id = id + "_bak";
// 追加input和取消按钮
var html = '<input size="5" id="'+id+'" name="'+id+'"/>';
html += '<input id="'+id +'_return" type="button" value="x" />';
p.append();
if(val) $("#"+id).val(val);
// 设置取消按钮onclick事件
$("#"+id+"_return").click(function(){
// 移除input
$("#"+id).remove();
$("#"+id+"_return").remove();
// 恢复Select
var t = $("#"+id+"_bak").get(0);
t.name = id;
t.id = id;
$(t).show();
// 恢复原来的位置
t.selectedIndex = fn[item.id];
});
}

Next Page »

Copyright © 2005-2009 kingchan.net, All rights reserved, Wordpress-Theme by Felix Krusch 粤ICP备09019789号