今天在老王的技术手册看到一个问题:
代码如下 | 复制代码 |
<?phpif ($a = 100 && $b = 200) { var_dump($a, $b);} |
输出是什么?
这个问题, 咋一看或许觉得简单, 但其实仔细推敲并不简单,
如果说布尔与之前的部分, 是由于优先级的问题, 但是如果仅仅是优先级的问题的话, 那么结果应该是:
代码如下 | 复制代码 |
$a = (100 && $b) = 200 |
而实际上的结果, 确实高优先级的&&让步给次优先级的=, 让 $b = 200 先结合了.
究其原因, 是因为PHP并不完全遵守优先级的定义, 这个在PHP的手册中也有说明:
Note: Although = has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.
这样的设计, 个人不发表看法, 反正在C语言中, 这样类似的语句是判定为语法错的. PHP采用这样的设计, 很可能是历史原因,
有好奇的同学, 会想知道到底为什么, 之前jayeeliu网友也问过:
laruence你好:
问一个php运算符优先级的问题
代码如下 | 复制代码 |
$t == 1 && $tt = 2 |
按照php运算符优先级应该是
代码如下 | 复制代码 |
(($t == 1) && $tt) = 2 |
这个顺序执行,但实际上应该是
代码如下 | 复制代码 |
($t == 1) && ($tt = 2) |
我有些不太理解。
其实也简单, 运算符优先级是在存在二义性文法的时候的一种规约规则选择的手段, 而PHP的语法分析文件定义中, 却让等号和T_BOOLEAN_AND(&&)之前不存在了规约冲突:
代码如下 | 复制代码 |
expr_without_variable: |
最后, 顺便说一下, PHP对应于T_BOOLEAN_AND 还定义了 T_LOGICAL_AND(and) 和 T_LOGICAL_OR(or) , 这俩个的优先级都低于等号, 于是就会有了, 很多PHP入门教材示例代码中经典的:
代码如下 | 复制代码 |
$result = mysql_query(*) or die(mysql_error()); |
类似的还可以用or来实现三元操作符(?:)的功能:
代码如下 | 复制代码 |
$person = $who or $person = "laruence"; |
//等同于:
代码如下 | 复制代码 |
$person = empty($who)? "laruence" : $who; |
结合方向 |
运算符 |
---|---|
左 | , |
左 | or |
左 | xor |
左 | and |
右 | |
右 | = += -= *= /= .= %= &= |= ^= ~= <<= >>= |
左 | ? : |
左 | || |
左 | && |
左 | | |
左 | ^ |
左 | & |
无 | == != === !== |
无 | < <= > >= |
左 | << >> |
左 | + - . |
左 | * / % |
右 | ! ~ ++ -- (int) (float) (string) (array) (object) @ |
右 | [ |
无 | new |
今天我们来研究下PHP验证码,我们通过简单的数字验证码来实现,首先来写一个生成验证码的代码:
代码如下 | 复制代码 |
<?php //随机生成一个4位数的数字验证码 $num=”"; for($i=0;$i<4;$i++){ $num .= rand(0,9); } //4位验证码也可以用rand(1000,9999)直接生成 //将生成的验证码写入session,备验证页面使用 Session_start(); $_SESSION["Checknum"] = $num; //创建图片,定义颜色值 Header(“Content-type: image/PNG”); srand((double)microtime()*1000000); $im = imagecreate(60,20); $black = ImageColorAllocate($im, 0,0,0); $gray = ImageColorAllocate($im, 200,200,200); imagefill($im,0,0,$gray); //随机绘制两条虚线,起干扰作用 $style = array($black, $black, $black, $black, $black, $gray, $gray, $gray, $gray, $gray); imagesetstyle($im, $style); $y1=rand(0,20); $y2=rand(0,20); $y3=rand(0,20); $y4=rand(0,20); imageline($im, 0, $y1, 60, $y3, IMG_COLOR_STYLED); imageline($im, 0, $y2, 60, $y4, IMG_COLOR_STYLED) //在画布上随机生成大量黑点,起干扰作用; for($i=0;$i<80;$i++) { imagesetpixel($im, rand(0,60), rand(0,20), $black); } //将四个数字随机显示在画布上,字符的水平间距和位置都按一定波动范围随机生成 $strx=rand(3,8); for($i=0;$i<4;$i++){ $strpos=rand(1,6); imagestring($im,5,$strx,$strpos, substr($num,$i,1), $black); $strx+=rand(8,12); } ImagePNG($im); ImageDestroy($im); ?> |
在reg.php页面我们写一个表单:(此处省去了其他的HTML代码)
代码如下 | 复制代码 |
<tr> <td>验证码 :</td> <td><input type=”text” name=”yzm”style=”width:60px;height:20px;” /><img" width=100% src=”code.php” onclick=”javascript:this.src=’code.php?’+Math.random();”></img></td> </tr> <tr> <td colspan=’2′><input type=”submit” value=”注册”/></td> <td>验证码 :</td> </tr> |
因为我们是用post提交的,所以我们用$_POST来获取(在接受页面做验证码的验证:post.php页面)
代码如下 | 复制代码 |
Session_start(); //back_alert()验证码输入错误的时候,弹出错误信息 function back_alert($yzm){ echo “<script type=’text/javascript’>alert(‘$yzm’);history.back();</script>”; } //禁止恶意调用(禁止直接在浏览器打开post.php页面) if($_POST["yzm"]==null){ back_alert(‘你都木有输入验证码,有木有???’); } // 禁止恶意注册 if(!($_POST["yzm"]==$_SESSION["Checknum"])){ back_alert(‘验证码不正确’); } echo $_POST["yzm"]; |
例
代码如下 | 复制代码 |
<?php $a=12;
echo '$a='.$a//输出结果 ?> 输出的结果:$a=24 |
总结:在函数体内定义的global变量,函数体外可以使用,在函数体外定义的global变量不能在函数体内使用,
代码如下 | 复制代码 |
$glpbal $a; function f() //再看看下面一例 function f() f(); |
上面的实例只是基本的global全局变量知识,下面我们看看复杂点的:
代码如下 | 复制代码 |
//A.php 文件 <?php $a = 0 ; //B.php 文件 <?php |
为什么输出的却是0?!!
在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内(包括include 和 require 导入的文件内的变量)!
解释:A.php文件的内Test_Global是定义好的第三方函数,该函数用include导入了B.php文件内的$a的global全局变量,所以$a被限制在Test_Global局部函数范围内,所以B.php文件内的$a的作用范围都在Test_Global内,而不是作用了整个A.php内….
解决方案:
1. 冲出局部函数
代码如下 | 复制代码 |
//A.php 文件 <?php //B.php 文件 <?php |
global问题解析:
question:我在config.inc.php中定义了一些变量($a),在别的文件中函数外部 include("config.inc.php"),函数内部需要使用这些变量$a,如果没有声明的话,echo $a是打印不出来任何东西的。因此声明global $a,但是有很多函数和很多变量,总不能不断重复的这样声明吧?有什么好的解决办法,请指点。
answer1:先在config.inc.php里定义常量:define(常量名,常量值)
再在其他需要用到的地方require 'config.inc.php',
然后就能在这个文件里直接使用这个常量了。
answer2:我也有个办法,就是定义数组,如$x[a],$x,那样就只要声明global $x一个了。
answer3:我试了你的这个方法,不行啊。
answer4:改你的php.ini文件。
① 创建数组第一种方法
$arr[0]=123;
$arr[1]=90;
….
概念:
[0] -> 这个我们称为下标,或者称为 关键字
$arr[0] -> 这个称为数组的一个元素.
$arr[0]=123; 123 表示该$arr[0]元素对应的值
$arr –》这个是该数组的名称.
☞在php数组中,元素存放的值可以是任意数据数据类型
② 创建数组的第二种方法
基本语法
$数组名=array(值1,值2,.......);
举例说明:
$arr=array(1,90,"helllo",89.5);
③ 第三种方式创建数组(在默认情况下,我们的元素的下标,是从0开始给你编号,但是实际上,也可以自己指定)
基本语法$arr[‘logo’]=”北京”;
$arr[’hsp’]=123;
....
或者
$arr=array(”logo”=>”北京”,”hsp”=>123,4=>678);
数组的遍历方法:
注: 如果使用 for while do..while 要确定该数组的下标是从 0开始顺序排放
数组共有多少个元素,可以使用系统函数count
//
代码如下 | 复制代码 |
for循环遍历方法 //while循环遍历方法 //do..while //foreach 遍历方法 |
php的数组相关的函数
① count 函数
基本用法是
count($数组名); 可以统计该数组共有多少元素.
② is_array
③ print_r 和 var_dump
④ explode 对字符串进行分割
案例:
$str="浙江&台州&杭州";
//在实际开发中,涉及到字符串的拆分,可以考虑
$arr=explode("&",$str);
print_r($arr);
数组查找
例子:
代码如下 | 复制代码 |
<?php |
例子输出结果如下:
键名为:0
array_key_exists()函数
如果在一个数组中找到一个指定的键,函数array_key_exists()返回true,否则返回false。其形式如下:
boolean array_key_exists(mixed key,array array);
下面的例子将在数组键中搜索apple,如果找到,将输出这个水果的颜色:
代码如下 | 复制代码 |
$fruit["apple"] = "red"; |
执行这段代码得到的结果:
apple's color is red
合并数组
array_merge()函数将数组合并到一起,返回一个联合的数组。所得到的数组以第一个输入数组参数开始,按后面数组参数出现的顺序依次迫加。其形式为:
Php代码
array array_merge (array array1 array2…,arrayN)
这个函数将一个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面。返回作为结果的数组。
如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值。然而,如果数组包含数字键名,后面的值将不会覆盖原来的值,而是附加到后面。
如果只给了一个数组并且该数组是数字索引的,则键名会以连续方式重新索引。
代码如下 | 复制代码 |
<?php // output |
2. 追加数组
array_merge_recursive()函数与array_merge()相同,可以将两个或多个数组合并在一起,形成一个联合的数组.两者之间的区别在于,当某个输入数组中的某个键己经存在于结果数组中时该函数会采取不同的处理方式.array_merge()会覆盖前面存在的键/值对,替换为当前输入数组中的键/值对,而array_merge_recursive()将把两个值合并在一起,形成一个新的数组,并以原有的键作为数组名。还有一个数组合并的形式,就是递归追加数组。其形式为:
Php代码
array array_merge_recursive(array array1,array array2[…,array arrayN])
程序实例如下:
代码如下 | 复制代码 |
<?php // output |
现在键 apple 指向一个数组,这个数组由两个颜色值组成的索引数组。
3. 连接数组
array_combine()函数会得到一个新数组,它由一组提交的键和对应的值组成。其形式为:
array array_combine(array keys,array values)
注意,两个输入数组必须大小相同,不能为空。示例如下
代码如下 | 复制代码 |
// output
|
4. 拆分数组 array_slice()
array_slice()函数将返回数组中的一部分,从键offset开始,到offset+length位置结束。其形式:
Php代码
array array_slice (array array, int offset[,int length])
offset 为正值时,拆分将从距数组开头的offset 位置开始;如果offset 为负值,则拆分从距数组末尾的offset 位置开始。如果省略了可选参数length,则拆分将从offset 开始,一直到数组的最后一个元素。如果给出了length 且为正数,则会在距数组开头的offset+length 位置结束。相反,如果给出了length且为负数,则在距数组开头的count(input_array)-|length|位置结束。考虑一个例子:
代码如下 | 复制代码 |
<?php $fruits = array("Apple", "Banana", "Orange", "Pear", "Grape", "Lemon", "Watermelon"); // output |
数组排序(下面方法用于一维数组)
•sort() 函数用于对数组单元从低到高进行排序。
•rsort() 函数用于对数组单元从高到低进行排序。
•asort() 函数用于对数组单元从低到高进行排序并保持索引关系。
•arsort() 函数用于对数组单元从高到低进行排序并保持索引关系。
•ksort() 函数用于对数组单元按照键名从低到高进行排序。
•krsort() 函数用于对数组单元按照键名从高到低进行排序。
多维数组排序
比如有个多为数组:
代码如下 | 复制代码 |
$arr = array( |
需要对二维数组中的 age 项排序。
需要用到PHP的内置函数 array_multisort(),可以看手册。
自定义函数:
代码如下 | 复制代码 |
function multi_array_sort($multi_array,$sort_key,$sort=SORT_ASC){ //处理 echo “<pre/>”; //输出 Array [b] => Array [a] => Array [d] => Array ) |
written by 大宇
在php中循环语句包括了很多,如有:for,foreach,while,do while,goto语句,下面我来给大家简单的介绍这些循环语句结构用法。for 循环控制
for(循环初值; 循环的条件; 步长){
//执行语句;
}
例
代码如下 | 复制代码 |
FOR ($i = 0; $i <= 2; $i++) |
输出值
value is now 0
value is now 1
value is now 2
在第一循环,$i=0,这意味着表达,($i<= 2),为ture。因此,打印语句执行时,$i得到加1,变成1。
在第二循环,$ = 1,这意味着表达,($i<= 2),为ture。因此,打印语句执行时,$i得到加1,变成2。
在第三迭代,$i= 2,这意味着表达,($i<= 2),为ture。因此,打印语句执行时,$i递增,成为1 3。
在第四迭代,$i= 3,这意味着表达,($i<= 2),是假的。因此,PHP不去执行循环,不执行打印语句。
while循环
基本语法结构是
while(循环条件){
//执行语句;
//循环条件值变化,不添加的话会成为死循环
}
例
代码如下 | 复制代码 |
<html><body> |
还是举个简单的例子,一看就明白了。下面这个例子,使用到了 while 循环语句,它的意思是,当变量 $a 小于等于5的情况下,执行一次循环,该循环执行连个语句,一是输出 $a 的值,二是给 $a 的值加1,直到 $a 小于等于 5 为 FALSE,即 $a > 5才停止循环。
do..while循环控制
基本语法结构
do{
//执行语句;
//循环条件值变化,不添加的话会成为死循环
}while(循环条件);
例
示例如下,该示例中,先执行一次循环,即 $i 加 1,然后输出 $i 的值,执行完第一次循环之后,检查条件 $i < 5,如果符合条件,则再执行一次循环,直到 $i < 5 为 FALSE 为止。
代码如下 | 复制代码 |
<html><body> |
循环相关的语句-break
基本的概念: 表示结束当前的 for 、 while 、do..while 、switch, 流程, 可以给一个数字,表示退出到第几层.
1. break语句 默认跳出 1层
2. break语句 后面带的数字,不能超过实际可以跳出的循环层数,否则,会报fatal error
循环相关的语句-continue
基本概念: continue 用于结束本次循环剩余代码,从新开始新的一次循环(如果条件为真,就继续执行), continue 后面也可以带数字,表示从第几次循环重新开始
goto语句
基本概念: 通过goto语句我们可以将程序跳转到指定的地方去执行.
goto 标签;
标签:
语句;
快速入门案例:
代码如下 | 复制代码 |
goto a; echo 'aa'; a: echo 'bb'; |
php中常量
说明:
所谓常量,我们可以理解成就是特殊的变量: 体现在
1. 定义常量前面不需要 $
2. 常量一旦定义,则不能修改其值
3. 常量在定义的时候,就需要它赋初值.
4. 常量可以通过 define 或者 const
5. 常量的名称,我们一般说是 全部大写,然后用下划线间隔
6. 什么时候需要使用常量: 在程序中我们不希望某个值变化,则考虑使用常量,比如圆周率,税率....
快速入门案例:
代码如下 | 复制代码 |
<?php
define("TAX_RATE",0.08); //第二种方法(php5.3) const TAX_RATE2=0.1; ?> |