分类目录归档:PHP

PHP学习总结

PHP 时间处理

1.计算两个日期的时间差

2.获得某一天之后n天的日期

 

PHP和Javascript数据类型转换总结

在做项目的过程中数据类型的转换是经常要面对的工作,每次一遇到转换,就到处搜网页,很是麻烦。今天就想把PHP和Javascript中的数据转换的方法总结一下,写到一起,方便查阅。

PHP数据类型转换
PHP的数据类型转换属于强制转换,允许转换的PHP数据类型有:
•(int)、(integer):转换成整形
•(float)、(double)、(real):转换成浮点型
•(string):转换成字符串
•(bool)、(boolean):转换成布尔类型
•(array):转换成数组
•(object):转换成对象

PHP数据类型有三种转换方式:
•在要转换的变量之前加上用括号括起来的目标类型
•使用3个具体类型的转换函数,intval()、floatval()、strval()
•使用通用类型转换函数settype(mixed var,string type)

第一种转换方式: (int) (bool) (float) (string) (array) (object)
第二种转换方式: intval() floatval() strval()
第三种转换方式: bool settype ( mixed &$var , string $type )
详细的使用方法参见php.net

JS 数据类型转换
方法主要有三种
转换函数、强制类型转换、利用js变量弱类型转换。

1. 转换函数:
js提供了parseInt()和parseFloat()两个转换函数。前者把值转换成整数,后者把值转换成浮点数。只有对String类型调用这些方法,这两个函数才能正确运行;对其他类型返回的都是NaN(Not a Number)。
在判断字符串是否是数字值前,parseInt()和parseFloat()都会仔细分析该字符串。parseInt()方法首先查看位置0处的字符,判断它是否是个有效数字;如果不是,该方法将返回NaN,不再继续执行其他操作。但如果该字符是有效数字,该方法将查看位置1处的字符,进行同样的测试。这一过程将持续到发现非有效数字的字符为止,此时parseInt()将把该字符之前的字符串转换成数字。
例如,如果要把字符串”1234blue”转换成整数,那么parseInt()将返回1234,因为当它检测到字符b时,就会停止检测过程。字符串中包含的数字字面量会被正确转换为数字,因此 字符串”0xA”会被正确转换为数字10。不过,字符串”22.5″将被转换成22,因为对于整数来说,小数点是无效字符。一些示例如下:

parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。基是由parseInt()方法的第二个参数指定的,所以要解析十六进制的值,需如下调用parseInt()方法:

在这段代码中,两行代码都把字符串 “010 “解析成了一个数字。第一行代码把这个字符串看作八进制的值,解析它的方式与第二行代码(声明基数为8)相同。最后一行代码声明基数为10,所以最后等于10。

parseFloat()方法与parseInt()方法的处理方式相似,从位置0开始查看每个字符,直到找到第一个非有效的字符为止,然后把该字符之前的字符串转换成数字。不过,对于这个方法来说,第一个出现的小数点是有效字符。如果有两个小数点,第二个小数点将被看作无效的,parseFloat()方法会把这个小数点之前的字符串转换成数字。这意味着字符串”22.34.5″将被解析成22.34。
使用parseFloat()方法的另一不同之处在于,字符串必须以十进制形式表示浮点数,而不能用八进制形式或十六进制形式。该方法会忽略前导0,所以八进制数0908将被解析为908。对于十六进制数0xA,该方法将返回NaN,因为在浮点数中,x不是有效字符。此外,parseFloat()也没有基模式。

下面是使用parseFloat()方法的示例:

2. 强制类型转换

还可使用强制类型转换(type casting)处理转换值的类型。使用强制类型转换可以访问特定的值,即使它是另一种类型的。

ECMAScript中可用的3种强制类型转换如下:
Boolean(value)——把给定的值转换成Boolean型;
Number(value)——把给定的值转换成数字(可以是整数或浮点数);
String(value)——把给定的值转换成字符串。
用这三个函数之一转换值,将创建一个新值,存放由原始值直接转换成的值。这会造成意想不到的后果。
当要转换的值是至少有一个字符的字符串、非0数字或对象(下一节将讨论这一点)时,Boolean()函数将返回true。如果该值是空字符串、数字0、undefined或null,它将返回false。
可以用下面的代码段测试Boolean型的强制类型转换。

Number()的强制类型转换与parseInt()和parseFloat()方法的处理方式相似,只是它转换的是整个值,而不是部分值。parseInt()和parseFloat()方法只转换第一个无效字符之前的字符串,因此”4.5.6″将被转换为”4.5″。用Number()进行强制类型转换,”4.5.6″将返回NaN,因为整个字符串值不能转换成数字。如果字符串值能被完整地转换,Number()将判断是调用parseInt()方法还是调用parseFloat()方法。下表说明了对不同的值调用Number()方法会发生的情况:
用法结果

最后一种强制类型转换方法String()是最简单的,因为它可把任何值转换成字符串。要执行这种强制类型转换,只需要调用作为参数传递进来的值的 toString()方法,即把1转换成”1″,把true转换成”true”,把false转换成”false”,依此类推。强制转换成字符串和调用toString()方法的唯一不同之处在于,对null或undefined值强制类型转换可以生成字符串而不引发错误:

3. 利用js变量弱类型转换
举个小例子,一看,就会明白了。

 

目前常用的其他字符串操作的函数

 

参考文章:
PHP数据类型转换 (转)http://www.blogjava.net/zuofei-bie/archive/2010/03/31/317092.html
JS 数据类型转换http://www.cnblogs.com/446557021/archive/2011/10/13/2211043.html

web应用用户权限的验证方案

浏览网站时,有的时候,会告诉你,无权进入一些页面。例如:一些技术性的论坛,刚进去的时候,只能看看贴子,并且只能在一定的区域看,不能发贴等。做电子商务时,电子商务的后台是一个比较大的系统,不同的人进去会看到不同的页面,如果能看到同一个页面,也许允许的操作也不一样,这些机制是怎么实现的呢。我们现在做的系统也是有权限限制的,系统里有四种角色,每种角色的用户都需要登录后,才能访问各自的资源。在做这个权限管理时,参考了他人系统上的一些方案,最终做成了我们现在的方案。这篇文章,记录了我在做权限管理是学到的知识。
通常权限管理都会有一下几种方法:
一.session控制
实现原理:
用户登录后台,输入用户名和密码,对用户的用户名和密码进行验证,验证通过后,可以把用户的一些基本信息放到session里面当用户访问后台的其他页面时,去判断一下session是否存在,并且没有过期。
方法:
1.后台页面共用的基本类,我们可以在基本类的里加以判断,或者在基本类外面在extends一层,加以判断,去check一下session。
2.直接写一个check_login.php每个后台页面都包涵这个页面,通过这个页面加以判断,check一下session。
3.其他方法。
二.cookie控制
cookie控制的原理与方法都和session控制类似,不同的是验证码是存在了浏览器的cookie里。
三.菜单控制
其实最开始想的就是用这种方法,先判断用户是否登录,登录了就对用户的权限进行限制,不同角色的用户看到的菜单和按钮是不一样的,因此可以实现对用户操作的限制。但是,再用户登录的情况下,他直接输入url进入本来不是他可访问或可操作的页面呢?这时候这种权限的控制就形同虚设了。
当然,这个问题是可以解决的,而且解决的方法也很轻松。建立一个用户和菜单内容的关系表,把用户所能看到的内容放到数据库内,就行了,仅此而已。当要显示菜单的地方,从数据库进行读取,如果用户是通过输入url进入的话,我们也可以根据用户和url,到关系表中进行查找,如果没有找到的话,就不准许访问页面或执行操作。这样就避免了上面所说的用户可以通过url肆无忌惮的访问系统的问题。
这种方法适用于前端模块是按操作分开的,用户的页面是根据功能把前端模块组合起来的这样一种前端架构。如wordpress,robin用的就是这一种。

我的项目的做法
考虑到我的项目的实际情况,前端模块划分可以说是严格按用户角色划分的,也就是不同用户的前端页面属于不同的模块。因此我没有必要用菜单控制这种较复杂的权限控制方法,二来用菜单控制也似乎没用,因为每种角色的前端页面的菜单与操作相对与后端来说是静态的。我选的是cookie验证,至于为什么不选session,其实原因并不明显,因为这两者用起来区别并不大。硬要说点区别的话,session是存储在服务器上,那么用session会增加的服务器的负担,cookie存储在浏览器中,导致的一个不良影响就是一个浏览器只能同时登录一个账号。我像做一个轻后端的应用,所以选择了cookie。
具体做法如下:
在用户登录是,在用户浏览器端的cookie里存一个验证码md5($row[‘password’].$salt),密码加盐($salt)当然是为了提高安全性。这个$salt是随机生成的。

当用户需要页面跳转时,需要先通过下面这个验证函数,

通过这个验证函数才能继续访问,不能通过验证的话,就会跳转到登录页面。目前这个验证函数还只是写在model里,也就是每个跳转的方法里都必须调用这个方法。我所用的CodeIgniter框架是可以定义钩子的,我想把权限验证放到钩子里去,但是也遇到一个问题,如果我有一些方法的访问是不需要权限的,我怎样把这些方法从钩子的作用域里去掉?这也是我目前还没有把验证写成钩子的原因了。
参考文章:http://blog.51yip.com/php/983.html
CodeIgniter用户指南:钩子-扩展框架的核心http://codeigniter.org.cn/user_guide/general/hooks.html
参考系统:robin(本实验的产品)

管理系统后台模块设计探索

  这段时间在做一个以CRUD操作为主的webApp,这是我第一次做项目,因此还处在一个蹒跚学步的阶段。幸好有曾总,张迪和肖微等几位大神的指导,还有夏威夷和我一起做。我才得以在这个项目上不断深入下去。
  我接到需求之后,从需求分析做起,到原型设计,到数据设计,其中遇到了各种问题,每个阶段的设计稿也是几经修改,终成定稿。而在做到详细设计时发现数据库设计还得修改。
  目前项目已经进行到编码阶段,前端是由张迪师兄设计http://www.storagelab.org.cn/zhangdi/2013/07/23/angularjs_for_actual_project/,而后台模块的划分主要由我来设计。

  模块化是软件设计和开发的基本原则和方法,是概要设计最主要的工作。模块的划分应遵循一定的要求,以保证模块划分合理,并进一步保证以此为依据开发出的软件系统可靠性强,易于理解和维护。根据软件设计的模块化、抽象、信息隐蔽和局部化等原则,可直接得出模块化独立性的概念。所谓模块独立性,即:不同模块相互之间联系尽可能少,应尽可能减少公共的变量和数据结构;一个模块应尽可能在逻辑上独立,有完整单一的功能。
  模块独立性(Module independence)是软件设计的重要原则。具有良好独立性的模块划分,模块功能完整独立,数据接口简单,程序易于实现,易于理解和维护。独立性限制了错误的作用范围,使错误易于排除,因而可使软件开发速度快,质量高。
  软件工程学引入模块的内聚度和模块的耦合度这两个概念,来定性地度量模块独立性的程度。一般来讲,在模块划分时,应当尽量使用数据耦合,少用控制耦合(尽量转成数据耦合),限制公共耦合的范围,完全不用内容耦合。同时应该尽量做到高内聚,并且能够辨别出低内聚的模块,加以修改提高其内聚度降低耦合度。

  当模块划分这样一个实际问题摆在我面前时,我情不自禁地找到了上面三段的内容,这些选摘自软件工程教材,它概况性地阐述了模块化的概念以及原则。现在我的任务就有两个,一是将模块划分出来,二是使划分的模块满足“高内聚,低耦合”的原则。
  下面先来看看我手头的项目的实际情况。
  报修系统这个应用采用现在流行的CodeIgniter框架,这个框架是一个典型的MVC框架。根据项目的需求,系统里的用户分为四种角色,分别是:管理员、维修人员、服务台人员和普通用户,而他们的操作主要是增删改查。系统的信息分为两大类,一类是系统的设置信息,如人员设置、组设置、工单内容设置等,一类是与工单操作有关的控制信息,如创建工单信息、转单信息、结单信息等。此外还有知识库,在线咨询和报表统计等功能,后期可能还会加短信邮件发送功能等。

1.模块按功能来划分

  许多人可能有过经验,面对一堆功能性需求,多个不同的需求可能要放到同一个模块里,而某个需求又需要分解到多个模块里去实现。比如一个词典软件(类似金山词霸的软件),通常有查询词典的功能需求和添加用户词库的功能需求,显然不可能简单地为这两个功能各分解一个模块。查询界面和添加用户词库的界面处理部分会被划成一个模块,而对词典的数据管理(查询,添加等)部分会被划分成另外一个模块。
  通过对以上词典软件的模块划分的分析,可以得出模块并不是简单地按功能来划分的结论,因此按功能来分解模块并不是一个任何情况下都可行的方案。
应用于我们这个项目,很明显增删改查和工单操作等功能是可以分为单独的模块,它们是松耦合的。但是每个角色的操作都不少而且不同角色的操作不尽相同,增删改查和工单操作这两个模块写起来会很肥胖,所以不倾向于这种划分。而登陆功能,搜索功能,报表统计功能是可以作为独立的模块的,因为每个用户的操作都是相同的。

2.模块按用户来分解

  当系统的用户角色不只有一种,而且每一种角色的操作都不尽相同时,我们可以考虑按用户角色来划分模块。用户角色分的模块的内聚度很高。当不同用户角色的操作完全不同或相同操作很少时,按用户角色划分的模块的耦合度也很低。
  鉴于此,报修系统这个项目也决定给没给用户角色一个独立的模块。也就是普通用户,管理员,维修人员,工作台值班人员四种角色各一个模块,分别负责各自的查看信息,设置信息,工单操作等任务。但是有一个问题,维修人员和工作台值班人员的查看信息部分有很大的相似度,几乎接近的操作,所以维修人员和工作台值班人员模块会出现公告耦合,同时也会出现重复的代码。解决的办法是模块分层,也就是在维修人员和工作台值班人员模块在抽象出一层它们的公共模块,用于实现它们共同的功能,而它们作为这个公共模块的子模块出现。基于目前的水平,我还是选择先不做多层模块,先把维修人员模块和工作台值班人员模块做好再说。

3.模块按专业领域进行分解

  仔细观察上面所说的词典软件的模块分解就会发现,所划分的两个模块属于不同的专业领域,一个是交互领域(图形界面),另一个是数据管理领域(数据结构与算法)。这样看来模块划分是按专业领域来划分的了,是不是所有的模块划分都是或者应该按照专业领域来进行划分呢?
  通过观察大量的软件的模块分解情况,其实可以发现绝大部分模块都是按照专业领域来分解的,这些专业领域包括软件公共领域的各个子领域,软件所处理业务的专业领域及其子领域等。
  软件公共领域常见的子领域有数据结构算法,图形界面,IO处理,网络通信,数据库,加密,安全,图像处理,数学算法等,当然这些子领域还可以进一步划分出更小的子领域来。
  软件所处理业务的专业领域则是指具体的业务方面所属的专业领域,如财务软件的业务包括了财务专业领域,CAD软件业务包括了机械制图方面的专业领域等。
  这些不同专业领域内的内容都是被划分到不同的模块里,没有人会在同一个模块里同时实现网络通信和数据结构算法的功能。这样可以得到模块分解的一个最基本的原理:
  不能在同一模块中实现两个不同专业领域的内容
  上面这句话的意思其实和模块按专业领域进行分解是一回事,只不过意思更明确一些。注意这里说的是“实现”,有许多的模块中需要用到许多不同专业领域的接口来进行处理,即在同一模块中可能会调用许多不同专业领域的接口来进行处理,调用接口并不属于“实现”。
  模块按专业领域来分解只是一个原理,无法证明它的正确性,因此看一下它会不会与已有的一些设计特性有冲突呢,比如常说的“高内聚,低耦合”,可复用性,可扩展性等是否会产生冲突。
  a.按专业领域分解的模块是“高内聚,低耦合”的
  为什么说按专业领域分解的模块事“高内聚,低耦合”的呢?专业的划分都是人们经过长期的实践和探索划分出来的,专业领域本身就是“高内聚,低耦合”的, 比如数据结构算法专业和网络专业耦合就很小,但每个专业的内部都是高内聚的。
  b.按专业领域分解的模块是可复用的
  这点很容易理解,模块按专业领域分解完后,显然任何两个不同的模块都不会有重复的内容,因此满足可复用的特性。
  c.按专业领域分解的模块是可扩展的
  当有新增需求时,只要将新增需求分解成各个专业领域的内容,新增的内容可以分为三类:
  (1)、在已有模块里已经有对应的实现,
  (2)、属于已有模块的领域,但是没有对应的实现
  (3)、不属于已有模块的领域
  对第1种情况中,显然不需要对已有模块做任何修改和添加;对第2种,需要在已有模块里添加相应的接口来实现对应的内容;对第3种,需要增加新的模块来实现对应的内容。
  所有这三种情况,都符合软件设计中的可扩展特性,因此按专业领域分解的模块是可扩展的。
  d.按专业领域分解的模块是可维护的
  这点可以由模块高内聚,低耦合,可扩展性的特性得出。

  按专业领域划分模块比较复杂,我一时也没法深入理解,项目暂时也不需要这样划分模块。写在这里,也许以后可以用到。

  综合上面的分析,报修系统的模块划分如下:

  admin(负责管理员的操作)
  customer(负责普通用户的操作)
  repaier(负责维修人员的操作)
  helpdesk(负责工作台值班人员的操作)
  main(负责用户登录认证)
  knowledge(负责知识库的操作)
  onlineQandA(负责在线问答的操作)
  statistics(统计报表模块)

  admin,customer,repaier,helpdesk是按用户角色划分的,main,knowledge,onlineQandA,statistics是按功能划分的,后面的四个模块与前面的四个模块之间会存在公告耦合,因为它们之间有公共操作的数据,比如说,main模块验证管理员时需要用到管理员用户的信息,admin模块也会用到管理员用户的信息。当然这个是可以接受的,共享的数据变量只有admin模块会写数据,其他模块都只是读数据。所以这样的设计符合“高内聚,低耦合”的原则。

参考:http://qiusuoge.com/7917.html

php替代语法

1.替代 Echo
正常的echo输出一般是这样的形式:<? echo $variable ; ?>
使用替代语法,可以改成这样:<? =$variable ?>

2.控制结构
像if,for,foreach和while也可以写成简化的形式。
<ul>
<php foreach($todo as $item): ?>
<li><?=$item?></li>
<?php endforeach;?>
</ul>
      注意,这里没有大括号。相反,结束大括号被替换成了endforeach。上面列出的每一个控制结构也有相似的关闭语法:endif,endfor,endforeach,endwhile。
并且在每个结构以后注意不要使用分号(除了最后一个),用冒号。这是很重要的!
这有另一个例子,使用 if/elseif/else。注意冒号:
<?php if ($username == ‘sally’): ?>
<h3>Hi Sally</h3>
<?php elseif($username==’joe’):?>
<h3>Hi Joe</h3>
<?php else:?>
<h3>Hi unknown user</h3>
<?php endif; ?>