|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
到现在,对排版还是不很熟练,经常会排不好。创立|数据|数据库 function errorMessage($dbcode)
前往DB毛病文本信息。
function &raiseError($code = DB_ERROR, $mode = false, $level = false,$debuginfo = false, $nativecode = false)
抛出一个毛病。这个函数由DB来挪用。
function setFetchMode($fetchmode)
设置缺省的fetch形式。
fetchmod有以下几种:
DB_FETCHMODE_DEFAULT :利用缺省的形式
DB_FETCHMODE_ORDERED :每笔记录的数据列利用数字索引,从0入手下手
DB_FETCHMODE_ASSOC :每笔记录的数据列利用字段名索引,同查询中的字段名分歧
DB_FETCHMODE_FLIPPED:假如了局集是多维的,多笔记录多个字段,普通来讲前往一个2维数组,第一维是纪录号,标明是第几笔记录,第2维的数组则利用字段名或数字索引。DB_FETCHMODE_FLIPPED则会互换这个按次,也就是说,第一层是字段名,第2维才是纪录号.
function setOption($option, $value)
设置后端数据库选项。$options,$value分离是选项名和响应的值。
普通不必直接挪用,在DB_Common及其子类的构建函数中会挪用这个函数。
function getOption($option)
获得某个option的值
function prepare($query)
为execute()筹办编译一个查询。关于某些后端数据库,这是经由过程仿真来完成的。前往编译后的查询句柄,失足则前往一个DB_Error对象。
function execute($stmt, $data = false)
履行编译后的查询。$stmt是由prepare前往的句柄。$data是参数数据,假如你利用的是参数查询,$data将要包括每一个?参数的值
例子:
<?php
/**
* 上面是履行一个删除查询,从文章表中将指定用户的文章纪录删除
*/
$sql = "delete from artilce where article.userid =$userid";
$qh = $db->prepare($sql);
if(DB::isError($qh)){
return $qh;
}
$result = $db->execute($qh);
return $result;
?>
function executeEmulateQuery($stmt, $data = false)
前往一个实践的查询字符串,供仿真prepare,execute的时分利用,外部函数。假如失足,则前往DB_Error对象
function executeMultiple( $stmt, &$data )
在统一个查询句柄上履行多个查询。$data必须是一个从0入手下手的数组,这个函数将 顺次利用数组中的每行数据来挪用execute。这个函数普通用于参数查询。你可履行一次 查询的编译,然后将分歧的参数值放入$data数组,然后便可一次同时履行查询了。需求注重,假如两头某个查询失足,残剩的查询不会持续停止而是前往毛病。
function modifyQuery($query)
外部函数,用于后端数据库修改查询,后端数据库完成这个函数,然后前往停止优化和修改后查询串。例子:这是DB_mysql的完成,
<?php
function modifyQuery($query)
{
if ($this->options['optimize'] == 'portability') {
// "DELETE FROM table" gives 0 affected rows in MySQL.
// This little hack lets you know how many rows were deleted.
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
?>
function &query($query)
履行一个查询,查询胜利,假如是有了局集的查询,则回一个DB_Result对象,假如没有了局集的查询则前往DB_OK。
失足则前往DB_Error对象。
function &getOne($query, $params = array())
履行查询,并前往了局集中第一行第一列的数据。$params是参数值,假如后端数据库撑持,将挪用prepare/execute来利用这些参数。
例子:
<?php
$sql = "select id,date from article where userid= $userid orderby date";
$last = $db->getOne($sql);
if(DB::isError($last)){
echo "失足:".DB::errorMessage($last);
}
echo "id:".$last;
?>
function &getRow($query, $fetchmode = DB_FETCHMODE_DEFAULT, $params = array())
履行查询,请前往了局集的第一笔记录。
$fetchmod 指定fetch形式,假如省略,利用缺省形式。
例子:
<?php
$sql = "select * from articles order by date desc";
$row = $db->getRow($sql);
if(DB::isError($row)){
echo "失足:".DB::errorMessage($row);
}
for($i=0;$i<count($row;$i++){
echo "<td>$row[$i]</td>";
}
?>
function &getCol($query, $col = 0, $params = array())
履行查询,并前往包括了局集中指定字段列的值的数组。
$col是要前往的列的索引,可所以整数,或是关头字段名。
例子:
<?php
$sql = "select id,userid,date from articles order by date desc limit 100";
//只前往用户列表
$row = $db->getCol($sql,1);
if(DB::isError($row)){
echo "失足:".DB::errorMessage($row);
}
for($i=0;$i<count($row;$i++){
echo "<tr>$row[$i]</tr>";
}
?>
function &getAssoc($query, $force_array = false, $params = array())
履行查询,并前往一个联系关系数组。
$force_arry 强迫前往数组。假如true,那末即便你的了局集里只要2个字段,那末关头字段对应的值也是一个只要一个元素的
数组。假如false,那末关头字段对应的值是一个标量了。
注重,这个联系关系数组有些出格:
假如你查询的是"select userid,name,reg_date from user",纪录集是:
userid name reg_date
test testor 2001-07-05
test2 teest2 2001-07-06
那末前往的数组是如许的:
array( 'test' => array('testor','2001-0705'),
'test2'=> array('teest2','2001-07-06'
)
例子:
<?php
$sql = "select userid,name,reg_date,last_login from users limit 100";
$userinfo = $db->getAssoc($sql);
if(DB::isError($userinfo)){
die "毛病!".DB::errorMessage($userinfo);
}
if(empty($userinfo)){
echo "warning:NO users!";
return;
}
/*如今,userinfo外面保留有效户的信息*/
function getUserInfo($user_id=''){
$info = $userinfo[$user_id];
if (empty($info){
echo "没有这个用户信息!";
}
return $info;
}
?>
function &getAll($query, $fetchmode = DB_FETCHMODE_DEFAULT, $params = array())
前往包括了局集中全体纪录的数组。注重,假如你的了局集很大,不要利用这个函数。
例子:
<?php
$sql ="select * from users limit 1000";
$list = $db->getAll($sql);
if(DB::isError($list)){
die "数据库毛病:".DB::errorMessage($list);
}
for ($i=0;$i<count($list);$i++){
$user = $list[$i];
echo "<tr>";
for($j=0;$j<count($user);$j++){
echo "<td>".$user[$j]."</td>";
}
echo "</tr>";
}
?>
function autoCommit($onoff=false)
指定是不是主动提交事务。有的后端数据库不撑持。
function commit()
提交以后事务
function rollback()
回滚以后事务
function numRows($result)
前往了局集中的纪录数
function affectedRows()
前往上一次查询操作的纪录数
function nextId($seq_name, $ondemand = true)
前往指定的sequence的下一个值
function createSequence($seq_name)
创立一个Sequence
function dropSequence($seq_name)
删除一个Sequence
5、 更进一步,创立你本人的两头数据库使用层
到此,咱们关于DB类的功效已有了更深的懂得。咱们可以基于DB类来创立你本人的数据库使用层了。或许你会问,我为何还要创立新的类,直接在我的使用法式中利用DB欠好么?谜底是,固然可以,然而我不保举。
起首,固然DB的功效很壮大,然而依然是过于底层的,你的类应当是面向使用的。你的这个数据库层应当屏障不需求利用的功效和函数,同时,也要供应一些更'初级'的办法,好比,你的使用法式不该该去联接数据库,释放资本,这些应当是通明的。那末这些任务就要由你的这个类来完成了。
其次,DB仍有一些缺点,一旦找到比它更好的,你可以敏捷地晋级。你所要改的只是这个类的办法若何完成,你的使用法式的其他模块不会为此遭到影响。
在你设计本人的类的时分,但愿可以一些原则:
供应根基的自在的查询接口。包含query,execute.分离对应有了局集和无了局集的查询。
不要利用特定命据库的某些特征,即便由于保持利用这些特点会给你增添很多的代码量。
尽可能屏障一些数据库的操作细节,好比毗连数据库,释放资本等等。
6、 DB的缺乏
下面咱们会商了DB的长处和一些利用的办法与技能。然而,任何事物都不是浑然一体的,DB类更是如斯,因为DB甚至PEAR的开辟工夫其实不长,因而DB并没有终究全体完成,个中也或多或少地存在一些BUG或设计上的成绩,需求咱们在利用中去发明和修改。
MYSQL的成绩
成绩1:前段我在开辟一个项目中,发明DB的MYSQL类有一个成绩,那就是当你connect的时分,MYSQL类主动将以后数据库设置为$DSN中的数据库名。今后利用query的时分,都是利用以后数据库。上面是本来connect的代码:
if ($dsninfo["database"]) {
if (!mysql_select_db($dsninfo["database"], $conn)) {
return $this->raiseError(); // XXX ERRORMSG
}
}
这招致了一个后来令我隐晦的成绩:
我的项目需求我毗连2个数据,假定分离是user和test。test是我的次要数据库,然而我要从第一个数据库中user中获得用户信息,同时test中保留用户的权限信息。我为此做了一个两头的类CV_DB,用来完成我的数据库层。在CV_DB的创立函数中,我毗连到指定的数据库,从而我可以如许利用:
$db1 = new CV("user");
$db2 = new CV("test");
前面当我履行,查询某个用户的信息的时分,呈现了"该表不存在"的DB毛病。但实践上这个表是存在的。最初,我发明本来是DB/mysql.php的成绩,由于它的查询利用的是,mysql_query,而不是mysql_db_query,当我毗连到第2个数据库的时分,MYSQL确当前数据库酿成了第2个,这时候我再履行针对第一个数据库的查询,固然会失足。
处理体例有2个,在创立CV的时分不毗连到数据库,查询的时分毗连,查询终了后断开。或,修正DB/Mysql.php。我选择后者,我将下面几行正文,然后将SimpleQuery中的mysql_query 交换成mysql_db_query.
成绩2:mysql没有execute,因而它承继利用了DB_common中摹拟体例,然而不幸地是,这带来了新的成绩,在一些更新查询中,所要更新的数据有? &这2个特别字符的时分,会呈现成绩,由于prepare以为这是参数查询的字符,将停止剖析,招致没法更新数据。
处理体例也有2个:交换?和&,然而如许要思索的工作良多。或:直接利用simpleQuery或query。
我选择后者,因为我的其他类只和CVDD我这个两头数据库使用类打交道,因而,我在CV的execute办法中做了判别,假如是后端数据库是mysql,那末我直接挪用simpleQuery,不然,挪用后端数据库的prepare和execute。如许,实践的后端数据库关于我项目中的其他使用类是通明的,我可以复杂地做响应的调剂,这也是我设计数据库使用层的初志。
DB的开辟形态
DB今朝仍在不休地开辟傍边,在DB/上面有一个文件STATUS,它描写了DB类的功效和各个后端数据库的完成情形,上面是PHP4.0.6这个宣布中的开辟情形:
"x" - 已完成,但还没有测试implemented, but without tests
"t" - 已完成,然而一个或多个测试没有经由过程implemented, but one or more tests fail
"T" - 完成并经由过程全体测试implemented, passing all tests
"e" - 仿真完成,没有测试emulated, without tests
"E" - 仿真完成,经由过程全体测试emulated, passing all tests
"n" - 前往 "not capable",没有这个才能供应该项功效
"-" - 没有完成
fbsql ifx mssql oci8 pgsql
FEATURE | ibase | msql | mysql | odbc | sybase
simpleQuery x x x x x T T x T x
numCols x x x x x T T x T x
numRows x n n x x T E n T n
errorNative x n x n n T x x T n
prepare/execute e x e e e E T e E e
sequences e n n n n E T n T n
affectedRows x n x n n T T n T n
fetch modes x x x x x T T x T x
fetch absolute rows x n x x x x n x x x
transactions x x n n n n x x x n
auto-commit x x n n n n x x x n
error mapping x - e - - T T x E -
tableInfo x n n n n T n n n n
7、参考资本
ADODB另外一个十分好把持数据库的PHP法式,DB的绝好的替换者
关于作者
潘凡(Night Sailer):北京赛迪数据无限公司工程师。次要研讨乐趣是Perl,PHP与XML的使用,PHP的MVC开辟形式,PERL-GTK的利用。您可以经由过程 E-mail:nightsailer@hotmail.com 跟他接洽。
总的来说,在这一个月左右的时间中,学到的不少,但是也遇到不少的问题,比如批量图片的上传,一直到现在也不懂,如何实现动态的增加上传图片的数量。 |
|