[置顶]分页的思路以及在ZF中的使用
posted @ 2012-05-30 17:59 MarcoFly 阅读(103) 评论(2) 编辑
posted @ 2012-05-30 17:59 MarcoFly 阅读(103) 评论(2) 编辑
posted @ 2012-01-15 16:02 MarcoFly 阅读(499) 评论(0) 编辑
posted @ 2012-01-12 21:24 MarcoFly 阅读(457) 评论(2) 编辑
posted @ 2012-01-12 21:17 MarcoFly 阅读(655) 评论(2) 编辑
posted @ 2011-12-29 19:33 MarcoFly 阅读(228) 评论(1) 编辑
分页思路:
只需要得到两个变量就成功了一半:
有了以上两个变量,我们就可以得出 共有几页了$pageCount
然后通过for循环,比如总共有13个页面,那么很容易就能通过for循环输出页数
$nav='';//用来保存页数的一个变量
for ($i=1;$i<=13;$i++)
{
$nav.="<a href='index.php?page=".$i."'>第".$i."页</a> ";
}
以上的for循环将输出如
第1页,第2页,第3页,第4页,第5页,第6页,第7页,第8页,第9页,第10页,第11页,第12页,第13页
如果我们只想每次只显示十个页面呢?比如1-10页,11-20页
很简单,只要稍微修改下for循环即可实现
$step= floor(($pageNow-1)/10)*10+1;
for ($i=$step;$i<=$step+10;$i++)
{
$nav.="<a href='index.php?page=".$i."'>第".$i."页</a> ";
}
比如,当前页面$pageNow如何在1~10之间的话,那么$step=0
当前页面$pageNow如何在11~20之间的话,那么$step=10
当前页面$pageNow如何在21~30之间的话,那么$step=20
参考具体的实现过程的代码,我们不难发现,for循环的第二个条件只需要加上10就可以实现每次只显示10也的情况了,我们将这一步分装在fenyePage类中的getLink()方法中
话又说回来,如何才能得到$pageSize和$rowCount两个变量的值呢?
$pageSize可以又程序员自己指定,$rowCount可以借助一个简单的执行sql语句的函数就能得到
1 <?php 2 /** 3 * $sql语句:①获取数据②获取总记录数 4 */ 5 class fenyePage{ 6 public $pageSize=5;//每页显示的数量-->程序员指定的 7 public $rowCount;//这是从数据库中获取的(形如SELECT COUNT(id) FROM TABLE)用来保存总共有多少条记录 8 public $pageNow;//通过$_GET['page']获取的,用来保存当前所在的页码 9 public $pageCount;//计算得到的,用来保存总共有多少页 10 public $res_arr;//用来保存要显示到页面的数据(比如保存SELECT * FROM TABLE LIMIT 0,10 检索的数据) 11 public $nav;//显示第几页第几页的导航条 12 13 /** 14 * 取得当前页面的超链接 15 * 16 * @author 小飞 2012/5/30 17 */ 18 public function getLink() 19 { 20 $this->nav=''; 21 $this->pageCount=ceil(($this->rowCount/$this->pageSize)); 22 $step= floor(($this->pageNow-1)/10)*10+1; 23 if ($this->pageNow>10) 24 { 25 $this->nav.=" <a href='index.php?page=".($step-1)."'> << </a> ";//整体每10页向前翻 26 } 27 if ($this->pageNow!=1) 28 { 29 $this->nav.="<a href='index.php?page=".($this->pageNow-1)."'> 上一页</a> "; 30 } 31 if ($this->pageNow!=1) 32 { 33 $this->nav.="<a href='index.php?page=1'>首页</a> "; 34 } 35 for ($start=$step;$start<$step+10 && $start<=$this->pageCount;$start++) 36 { 37 $this->nav.="<a href='index.php?page=".$start."'>".$start."</a> "; 38 } 39 if ($this->pageNow!=$this->pageCount) 40 { 41 $this->nav.="<a href='index.php?page=".$this->pageCount."'>末页</a> "; 42 } 43 if ($this->pageNow!=$this->pageCount) 44 { 45 $this->nav.=" <a href='index.php?page=".($this->pageNow+1)."'>下一页</a>"; 46 } 47 if ($this->pageCount>10 && $this->pageNow<$this->pageCount-8){ 48 $this->nav.=" <a href='index.php?page=".($step+10)."'> >> </a>";//整体每10页向后翻 49 } 50 $this->nav.="/共有".$this->pageCount."页"; 51 } 52 } 53 ?>
由于zf中操作数据库的任务由model层来完成,所以,我将获取$rowCount的值的函数放在了对应的表model中
比如:我是操作order表的
那么当我要显示所有订单信息的时候,我通过order类中的showorder()方法取得$rowCount的值,并将其付给分页类中的$rowCount属性
同样,将要显示在页面上的数据信息也一并付给了分页类中的$res_arr属性
这样,我们就可以很容易的通过实例化一个分页类(fenyePage),然后将其通过参数传给showorder()函数,由该函数完成以下动作:
①要显示在页面上的信息
②表中总共有多少条记录
1 /** 2 * 根据指定的用户id,查询该用户的历史订餐记录 3 * 4 * @author 小飞 2012/5/30 5 * @param $id 用户id 6 * @param $fenye 实例化的一个对象,用来处理分页 7 * @todo $sql1语句 "select * from table where * limit 0,10" 该sql语句主要用来检索数据库中的数据,用以显示在view层 8 * @todo $sql2语句 "select count(id) from table" 该sql语句用来得出总的数据量 9 */ 10 public function showorder($id=null,$fenye=null) 11 { 12 $db = $this->getAdapter(); 13 14 $select=$db->select(); 15 $select->from(array('o' => 'order'),array('o.id','o.user_id','o.user_name','o.food_name','o.food_price','o.order_time','o.order_state')); 16 if ($id!=null){ 17 $select->where('o.user_id=?',$id); 18 } 19 $select->join(array('d'=>'department'),'o.dep_id = d.id','d.dep_name'); 20 if($fenye!=null){ 21 $select->limit($fenye->pageSize,($fenye->pageNow-1)*$fenye->pageSize); 22 } 23 $sql1=$select->__toString(); 24 //该sql语句主要用来计算总的数据量 25 $sql2="SELECT COUNT(id) FROM `order`"; 26 $fenye->res_arr=$db->fetchAll($sql1);//将要显示的数据存储到分页类的$res_arr属性当中,方便调用 27 $rowCount=$db->fetchAll($sql2);//将表中的总数据量保存到分页类的rowCount属性当中 28 $fenye->rowCount=$rowCount[0]['COUNT(id)']; 29 $fenye->getLink(); 30 return $fenye->res_arr; 31 }
至此,分页类的功能就已经实现了
原创文章:WEB开发_小飞
转载请注明出处:分页的思路以及在ZF中的使用
posted @ 2012-05-30 17:59 MarcoFly 阅读(103) 评论(2) 编辑
PHP面向对象分析设计的61条军规
(1)所有数据都应该隐藏在所在的类的内部。
(2)类的使用者必须依赖类的共有接口,但类不能依赖它的使用者。
(3)尽量减少类的协议中的消息。
(4)实现所有类都理解的最基本公有接口[例如,拷贝操作(深拷贝和浅拷贝)、相等性判断、正确输出内容、从ASCII描述解析等等]。
(5)不要把实现细节(例如放置共用代码的私有函数)放到类的公有接口中。
如果类的两个方法有一段公共代码,那么就可以创建一个防止这些公共代码的私有函数。
(6)不要以用户无法使用或不感兴趣的东西扰乱类的公有接口。
(7)类之间应该零耦合,或者只有导出耦合关系。也即,一个类要么同另一个类毫无关系,要么只使用另一个类的公有接口中的操作。
(8)类应该只表示一个关键抽象。
包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包影响,则将对包中的所有类产生影响,而对其他的包不 造成任何影响 .
(9)把相关的数据和行为集中放置。
设计者应当留意那些通过get之类操作从别的对象中获取数据的对象。这种类型的行为暗示着这条经验原则被违反了。
(10)把不相关的信息放在另一个类中(也即:互不沟通的行为)。
朝着稳定的方向进行依赖.
(11)确保你为之建模的抽象概念是类,而不只是对象扮演的角色。
(12)在水平方向上尽可能统一地分布系统功能,也即:按照设计,顶层类应当统一地共享工作。
(13)在你的系统中不要创建全能类/对象。对名字包含Driver、Manager、System、Susystem的类要特别多加小心。
规划一个接口而不是实现一个接口。
(14)对公共接口中定义了大量访问方法的类多加小心。大量访问方法意味着相关数据和行为没有集中存放。
(15)对包含太多互不沟通的行为的类多加小心。
这个问题的另一表现是在你的应用程序中的类的公有接口中创建了很多的get和set函数。
(16)在由同用户界面交互的面向对象模型构成的应用程序中,模型不应该依赖于界面,界面则应当依赖于模型。
(17)尽可能地按照现实世界建模(我们常常为了遵守系统功能分布原则、避免全能类原则以及集中放置相关数据和行为的原则而违背 这条原则) 。
(18)从你的设计中去除不需要的类。
一般来说,我们会把这个类降级成一个属性。
(19)去除系统外的类。
系统外的类的特点是,抽象地看它们只往系统领域发送消息但并不接受系统领域内其他类发出的消息。
(20)不要把操作变成类。质疑任何名字是动词或者派生自动词的类,特别是只有一个有意义行为的类。考虑一下那个有意义的行为是 否应当迁移到已经存在或者尚未发现的某个类中。
(21)我们在创建应用程序的分析模型时常常引入代理类。在设计阶段,我们常会发现很多代理没有用的,应当去除。
(22)尽量减少类的协作者的数量。
一个类用到的其他类的数目应当尽量少。
(23)尽量减少类和协作者之间传递的消息的数量。
(24)尽量减少类和协作者之间的协作量,也即:减少类和协作者之间传递的不同消息的数量。
(25)尽量减少类的扇出,也即:减少类定义的消息数和发送的消息数的乘积。
(26)如果类包含另一个类的对象,那么包含类应当给被包含的对象发送消息。也即:包含关系总是意味着使用关系。
(27)类中定义的大多数方法都应当在大多数时间里使用大多数数据成员。
(28)类包含的对象数目不应当超过开发者短期记忆的容量。这个数目常常是6。
当类包含多于6个数据成员时,可以把逻辑相关的数据成员划分为一组,然后用一个新的包含类去包含这一组成员。
(29)让系统功能在窄而深的继承体系中垂直分布。
(30)在实现语义约束时,最好根据类定义来实现。这常常会导致类泛滥成灾,在这种情况下,约束应当在类的行为中实现,通常是在 构造函数中实现,但不是必须如此。
(31)在类的构造函数中实现语义约束时,把约束测试放在构造函数领域所允许的尽量深的包含层次中。
(32)约束所依赖的语义信息如果经常改变,那么最好放在一个集中式的第3方对象中。
(33)约束所依赖的语义信息如果很少改变,那么最好分布在约束所涉及的各个类中。
(34)类必须知道它包含什么,但是不能知道谁包含它。
(35)共享字面范围(也就是被同一个类所包含)的对象相互之间不应当有使用关系。
(36)继承只应被用来为特化层次结构建模。
(37)派生类必须知道基类,基类不应该知道关于它们的派生类的任何信息。
(38)基类中的所有数据都应当是私有的,不要使用保护数据。
类的设计者永远都不应该把类的使用者不需要的东西放在公有接口中。
(39)在理论上,继承层次体系应当深一点,越深越好。
(40)在实践中,继承层次体系的深度不应当超出一个普通人的短期记忆能力。一个广为接受的深度值是6。
(41)所有的抽象类都应当是基类。
(42)所有的基类都应当是抽象类。
(43)把数据、行为和/或接口的共性尽可能地放到继承层次体系的高端。
(44)如果两个或更多个类共享公共数据(但没有公共行为),那么应当把公共数据放在一个类中,每个共享这个数据的类都包含这个类。
(45)如果两个或更多个类有共同的数据和行为(就是方法),那么这些类的每一个都应当从一个表示了这些数据和方法的公共基类继承。
(46)如果两个或更多个类共享公共接口(指的是消息,而不是方法),那么只有他们需要被多态地使用时,他们才应当从一个公共基类 继承。
(47)对对象类型的显示的分情况分析一般是错误的。在大多数这样的情况下,设计者应当使用多态。
(48)对属性值的显示的分情况分析常常是错误的。类应当解耦合成一个继承层次结构,每个属性值都被变换成一个派生类。
(49)不要通过继承关系来为类的动态语义建模。试图用静态语义关系来为动态语义建模会导致在运行时切换类型。
(50)不要把类的对象变成派生类。对任何只有一个实例的派生类都要多加小心。
(51)如果你觉得需要在运行时刻创建新的类,那么退后一步以认清你要创建的是对象。现在,把这些对象概括成一个类。
(52)在派生类中用空方法(也就是什么也不做的方法)来覆写基类中的方法应当是非法的。
(53)不要把可选包含同对继承的需要相混淆。把可选包含建模成继承会带来泛滥成灾的类。
(54)在创建继承层次时,试着创建可复用的框架,而不是可复用的组件。
(55)如果你在设计中使用了多重继承,先假设你犯了错误。如果没犯错误,你需要设法证明。
(56)只要在面向对象设计中用到了继承,问自己两个问题:(1)派生类是否是它继承的那个东西的一个特殊类型?(2)基类是不是派生类的一部分?
(57)如果你在一个面向对象设计中发现了多重继承关系,确保没有哪个基类实际上是另一个基类的派生类。
(58)在面向对象设计中如果你需要在包含关系和关联关系间作出选择,请选择包含关系。
(59)不要把全局数据或全局函数用于类的对象的薄记工作。应当使用类变量或类方法。
(60)面向对象设计者不应当让物理设计准则来破坏他们的逻辑设计。但是,在对逻辑设计作出决策的过程中我们经常用到物理设计准则。
(61)不要绕开公共接口去修改对象的状态。
posted @ 2012-05-15 11:45 MarcoFly 阅读(5) 评论(0) 编辑
【1】页面之间无法传递变量 get,post,session在最新的php版本中自动全局变量是关闭的,所以要从上一页面取得提交过来得变量要使用$_GET['foo'],$_POST['foo'],$_SESSION['foo']来得到。当然也可以修改自动全局变量为开(php.ini改为register_globals = On);考虑到兼容性,还是强迫自己熟悉新的写法比较好。
【2】Win32下apache2 用get方法传递中文参数会出错:
test.php?a=你好&b=你也好
传递参数是会导致一个内部错误
解决办法:"test.php?a=".urlencode(你好)."&b=".urlencode(你也好)
.............
【3】win32下的session不能正常工作
php.ini默认的session.save_path = /tmp
这显然是linux下的配置,win32下php无法读写session文件导致session无法使用,把它改成一个绝对路径就可以了,例如session.save_path = c:windows emp
【4】显示错误信息
当php.ini的display_errors = On并且error_reporting = E_ALL时,将显示所有的错误和提示,调试的时候最好打开以便纠错,如果你用以前php写法错误信息多半是关于未定义变量的。变量在赋值以前调用会有提示,解决办法是探测或者屏蔽。
例如显示$foo,可以if(isset($foo)) echo $foo 或者echo @$foo
【5】Win32下mail()不能发送电子邮件
在linux下配置好的sendmail可以发送,在win32下需要调用smtp服务器来发送电子邮件,修改php.ini的SMTP = ip //ip是不带验证功能的smtp服务器(网上很难找到)
php发送邮件的最好解决方法是用socket直接发送到对方email服务器而不用转发服务器。
【6】初装的mysql如果没有设置密码,应该使用update mysql.user set password="yourpassword" where user="root" 修改密码
【7】header already sent
这个错误通常会在你使用HEADER的时候出现,他可能是几种原因:
1.你在使用HEADER前print或者echo了
2.你当前文件前面有空行
3.你可能include了一个文件,该文件尾部有空行或者输出也会出现这种错误。!
【8】更改php.ini后没有变化
重新启动web server,比如IIS,Apache等等,然后才会应用最新的设置。
【9】php在2003上面安装(ISAPI的安装方法恳请高手指教)
PHP4的php4isapi.dll好像和2003有些冲突,只能用CGI模式安装
步骤一,先www.php.net 下在一个安装程序,我是装的是:php-4.2.3-installer.exe,你也可以去找最新的版本,在安装php-4.2.3-installer.exe之前保证你的IIS6.0启动了,并能够访问。安装好以后,在默认网站-->应用程序配置。
步骤二:点击 web服务扩展 -->新建web服务扩展。
步骤三: 扩展名-->php,然后添加
步骤四:找到php.exe的路径添加上去。
步骤五: 确定就可以了!
步骤六: 选择php的服务扩展,然后点击允许。
【10】有时候sql语句不起作用,对数据库操作失败,最简便的调试方法,echo那句sql,看看变量的值能得到不。
【11】include和require的区别
两者没有太大的区别,如果要包含的文件不存在,include提示notice,然后继续执行下面的语句,require提示致命错误并且退出。
据我测试,win32平台下它们都是先包含后执行,所以被包含文件里最好不要再有include或require语句,这样会造成目录混乱。或许*nux下情况不同,暂时还没测试。
如果一个文件不想被包含多次可以使用include_once或require_once 读取,写入文档数据。
function r($file_name) {
$filenum=@fopen($file_name,"r");
@flock($filenum,LOCK_SH);
$file_data=@fread($filenum,filesize($file_name));
@fclose($filenum);
return $file_data;
}
function w($file_name,$data,$method="w"){
$filenum=@fopen($file_name,$method);
flock($filenum,LOCK_EX);
$file_data=fwrite($filenum,$data);
fclose($filenum);
return $file_data;
}
【12】isset()和empty()的区别
两者都是测试变量用的,但是
isset()是测试变量是否被赋值
empty()是测试一个已经被赋值的变量是否为空。
如果一个变量没被赋值就引用在php里是被允许的,但会有notice提示,如果一个变量被赋空值,$foo=""或者$foo=0或者 $foo=false,那么empty($foo)返回真,isset($foo)也返回真,就是说赋空值不会注销一个变量。
要注销一个变量,可以用 unset($foo)或者$foo=NULL
【13】mysql查询语句包含有关键字
php查询mysql的时候,有时候mysql表名或者列名会有关键字,这时候查询会有错误。例如表名是order,查询时候会出错,简单的办法是sql语句里表名或者列名加上`[tab键上面]来加以区别,例如select * from `order`
【14】通过HTTP协议一次上传多个文件的方法
有两个思路,是同一个方法的两种实现。具体程序还需自己去设计。
1、在form中设置多个文件输入框,用数组命名他们的名字,如下:
<form action="" method=post>
<input type=file name=usefile[]>
<input type=file name=usefile[]>
<input type=file name=usefile[]>
</form>
这样,在服务器端做以下测试:
echo "<pre>";
print_r($_FILES);
echo "</pre>";
2、在form中设置多个文件输入框,但名字不同,如下:
<form action="" method=post>
<input type=file name=usefile_a>
<input type=file name=usefile_b>
<input type=file name=usefile_c>
</form>
在服务器端做同样测试:
echo "<pre>";
print_r($_FILES);
echo "</pre>";
posted @ 2012-05-15 10:51 MarcoFly 阅读(20) 评论(0) 编辑
posted @ 2012-05-10 10:47 MarcoFly 阅读(18) 评论(0) 编辑
今天,总监跟我说,由于客户需要,让我针对zencart进行些简单的二次开发。
大体功能如下:
最终的效果如下:

<!-----------------库存警告 start--> <?php $sql="SELECT products_id,products_name,(SELECT count('products_id') FROM ".TABLE_PRODUCTS." WHERE ".TABLE_PRODUCTS.".products_quantity=0) AS unit FROM ".TABLE_PRODUCTS_DESCRIPTION." WHERE products_id IN (SELECT products_id FROM ".TABLE_PRODUCTS ." WHERE products_quantity=0)"; $res=$db->Execute($sql); $units=$res->fields['unit']; ?> <div class="reportBox"> <div class="header"><font color="Red">库存商品警告数量:<?php echo $units;?></font></div> <div class="row"><font color="Red"><span class='left'>产品名称</span><span class="rigth">产品ID</span></font></div> <?php while(!$res->EOF){ echo "<div class='row'><span class='left'>".$res->fields['products_name']."</span><span class='rigth'>".$res->fields['products_id']."</span></div>"; $res->MoveNext(); } ?> </div> <!---------------库存警告 end-->
将以上代码加入到后台目录的index.php文件中,即可
要计算库存数量为0的商品总数,需要使用到聚集函数count(),但是如果以上sql语句写成:
SELECT count('products_id') AS unit,products_id,products_name FROM ".TABLE_PRODUCTS_DESCRIPTION." WHERE products_id IN (SELECT products_id FROM ".TABLE_PRODUCTS ." WHERE products_quantity=0)
这样只能检索出一条结果,因为SELECT count() 仅对一个结果进行计数。
为了对每个结果进行都能进行count(*)计算,应该将count(*)作为子查询
posted @ 2012-04-25 22:31 MarcoFly 阅读(98) 评论(0) 编辑
今天写了一段Python多线程处理文件的代码,用以比较单线程和多线程在处理较大文件时的速度差异
代码解释:
1-3行:导入需要用到的模块os,threading,ctime
4-11行:从列表list中取得文件名,并计算出该文件的行数
15-22行:取得当前工作路径下的所有文件,并从中筛选出txt文件
28-33行:创建线程
34-35行:调用start()函数,一起启动线程:同步性
注意:在读取文件的时候,我没有使用read分批读入,而是使用readlines,所有运行的时候,可能会比较卡,读者也可以修改下代码的第9行
单线程和多线程处理较大文件的速度对比:


每个文本文件的行数大约都在100万行左右,通过以上的对比,我们从中就能很明显的发现多线程处理大文件的优势所在
代码如下:
1 import os 2 import threading 3 from time import ctime 4 def loop(loops,list):#list存放着每个线程需要处理的文本文件名 5 print '线程%d处理的文件列表%s\n'%(loops+1,list) 6 list_len=len(list) 7 for i in range(list_len): 8 f=open(list[i]) 9 rows=len(f.readlines())#此处,我直接将整个文件读入,所以会比较卡,可以在此设置每次读入的大小 10 f.close() 11 print '文件%s__%d行\n'%(list[i],rows) 12 13 def main(): 14 print 'all start at:',ctime() 15 cwd=os.getcwd() 16 dir_list=os.listdir(cwd) 17 file_list=[] #该列表用来存放当前目录下的所有txt文件 18 print '当前文件夹下的所有txt文件:' 19 for l in dir_list: 20 if l.rfind('txt')>=0: 21 print ' ',l 22 file_list.append(l) 23 threads=[] 24 threads_num=4 #线程数 在此处修改下线程数就可以比较多线程与单线程处理文件的速度差异 25 print '共有线程数:%d个'%threads_num 26 per_thread=len(file_list)/threads_num #每个线程处理的文本数量 27 print per_thread 28 for i in range(threads_num): 29 if threads_num-i==1: #最后一个线程,分担余下的所有工作量 30 t=threading.Thread(target=loop,args=(i,file_list[i*per_thread:])) 31 else: 32 t=threading.Thread(target=loop,args=(i,file_list[i*per_thread:i*per_thread+per_thread])) 33 threads.append(t) 34 for i in range(threads_num): 35 threads[i].start() 36 for i in range(threads_num):#等待所有的线程结束 37 threads[i].join() 38 print 'all end at:',ctime() 39 if __name__=='__main__': 40 main()
原创文章:WEB开发_小飞
转载请注明出处:http://www.cnblogs.com/hongfei/archive/2012/04/14/python-multithread-document.html
posted @ 2012-04-14 21:37 MarcoFly 阅读(346) 评论(0) 编辑
posted @ 2012-03-29 13:54 MarcoFly 阅读(306) 评论(0) 编辑
posted @ 2012-03-29 13:46 MarcoFly 阅读(209) 评论(2) 编辑
posted @ 2012-03-18 11:16 MarcoFly 阅读(26) 评论(0) 编辑
posted @ 2012-01-15 16:02 MarcoFly 阅读(499) 评论(0) 编辑