0 概述
<?php //整型数0 var_dump( empty(0));// bool(true) //双精度型数0.0 var_dump( empty(0.0));//bool(true) //空字符串 var_dump( empty(''));//bool(true) //字符串0 var_dump( empty('0'));//bool(true) //布尔值false var_dump( empty(false));//bool(true) //空数组 var_dump( empty([]));//bool(true) //NULL var_dump( empty(NULL));//bool(true) //数字 000 var_dump( empty(000));//bool(true) //没有属性的对象???? $obj = new class{}; var_dump($obj); var_dump( empty($obj));//bool(false) //字符串00 var_dump( empty("00"));//bool(false) // 空格字符串 var_dump( empty(' '));//bool(false) ?>
1 消除==和=的困扰
<?php $dwarves = 12; //会把==右边的,强制转化为左边的类型 if( 12 ==$dwarves){ echo __LINE__; } //不转化数据类型的比较 if( 12 === $dwarves){ echo __LINE__; } //会报错,常量数字12无法赋值 if( 12 = $dwarves){ echo __LINE__; } ?>
2 为变量设定默认值
<?php $vehicles = ['cars'=>null]; $rs = array_key_exists('cars',$vehicles); var_dump($rs); $rs = isset($vehicles['cars']); var_dump($rs); $x = 75; $y = 25; function addition() { $GLOBALS['z'] = $GLOBALS['x'] + $GLOBALS['y']; } addition(); echo $z; $enperors=['秦始皇','秦二世'] ; $defaults = array( 'enperors'=>['Rudolf II','Caligula'], 'vegetable'=>'celery', 'acres'=>15 ); function aa($defaults) { foreach($defaults as $k=>$v){ if(!isset($GLOBALS[$k])){ $GLOBALS[$k] = $v; } } var_dump($enperors);//NULL } aa($defaults); var_dump($GLOBALS['enperors']);//秦始皇" function bb($defaults) { foreach($defaults as $k=>$v){ if(!isset($$k)){ $$k = $v; } } var_dump($enperors);//"Rudolf II" } bb($defaults); var_dump($GLOBALS['enperors']);//"秦始皇" ?>
3 不使用临时变量而实现变量值的交换
<?php $a = 4; $b = 5; $a = $a^$b; $b = $a^$b; $a = $a^$b; var_dump($a); var_dump($b); $a = 4; $b = 5; list($a,$b) = [$b,$a]; var_dump($a); var_dump($b); $country = '中国'; $city = "郑州"; $state = "河南"; $event = "富士康"; $result = compact("event", ["city", "state"],'country'); print_r($result); ?>
4 动态创建变量名
<?php $donkeys[12] = 'cc'; $$donkeys[12] = 'aa'; var_dump($cc); ${$donkeys[12]} = 'aa'; var_dump($cc); $donkeys = 'cc'; $$donkeys[12] = 'aa'; var_dump($cc); ${$donkeys}[12] = 'aa'; var_dump($cc); ?>
5 使用静态变量
<?php function track_time_called() { static $i ; $i++; return $i; } $i = track_time_called(); var_dump($i);//1 $i = track_time_called(); var_dump($i);//2 $i = track_time_called(); var_dump($i);//3 /* 在这个示例中,无论创建多少个 MyClass 的实例,staticCounter 都是同一个变量,它的值会随着每个新实例的创建而增加。而 instanceCounter 是一个实例变量,它对每个实例都是独立的。 */ class MyClass { // 静态变量 static public $staticCounter =100 ; // 实例变量 public $instanceCounter = 100; public function myFun() { self::$staticCounter ++; $this->instanceCounter++; } } $myObj = new MyClass(); $myObj->myFun(); var_dump(MyClass::$staticCounter);//int(101) var_dump($myObj->instanceCounter);//int(101) $myObj->myFun(); var_dump(MyClass::$staticCounter);//int(102) var_dump($myObj->instanceCounter);//int(102) $myObj2 = new MyClass(); $myObj2->myFun(); var_dump(MyClass::$staticCounter);//int(103) var_dump($myObj2->instanceCounter);//int(101) ?>
6 在进程间共享变量
6.1 shmop
6.2 System V
<?php exec('ipcs -m', $output); // 输出命令执行结果 foreach ($output as $line) { echo $line . PHP_EOL; } echo '************'; echo PHP_EOL; //////////////////////////////////////////////////////// //信号id $semKey = ftok(__FILE__,'s'); //获取一个与我们想取得的共享内存关联的信号的句柄 $sem = sem_get($semKey,1,0644); if($sem===false){ die('返回信号量标识符失败'); } //确保对信号的独占访问 $semRs = sem_acquire($sem) or die("获取信号量发生错误"); // get a handle to our shared memory segment if($semRs === false){ die('获取信号量失败'); } /////////////////////////////////////////////////////// $shmKey = ftok(__FILE__, 'c' ); //1024 内存大小 //0644 权限 //获取内存 //获取共享内存片段的句柄 //内存大小。若没有提供,缺省为 sysvshm. init_mem in the php. ini,否则为 10000 字节 //返回一个共享内存段标识符。 $shm = shm_attach($shmKey, 1024, 0644) or die('打开或创建内存段发生错误'); if ($shm === false){ die('打开或创建内存段失败'); } //从内存中存入变量 $population_1 = shm_get_var($shm,1); //初始化人口数据 $population_1 = intval($population_1); $births = 2;//出生人口 $immigrants = 1;//移入人口 $deaths = 2;//死亡人口 $emigrants= 0;//移出人口 $population_1 += ($births + $immigrants - $deaths - $emigrants); //存放变量到内存中 //shm_put_var 第二个参数必须是int类型,不支持字符串类型!!!! $putRs = shm_put_var($shm,1,$population_1); if(!$putRs){ echo '添加数据失败'.PHP_EOL; } $hasRs = shm_has_var($shm,1); if(!$hasRs){ echo 'variable_key为1的内存数据不存在' .PHP_EOL; } $population_1 = shm_get_var($shm,1); var_dump($population_1); //释放对共享内存的句柄 /*$rs1 = shm_detach($shm); if ($rs1 === false){ echo '释放共享内存失败'.PHP_EOL; }*/ //使用时以下3段代码的注释要去掉 /*//移除共享内存 $rs2 = shm_remove($shm); if($rs2 === false){ echo '移除共享内存失败'.PHP_EOL; } //释放信号,以便其他进程可以捕获它 $rs3 = sem_release($sem); if ($rs3 === false){ echo '释放信号失败'.PHP_EOL; } //删除信号,其他进程也不能捕获它 $rs4 = sem_remove($sem); if ($rs4 === false){ echo '删除信号失败'.PHP_EOL; }*/ exec('ipcs -m', $output2); // 输出命令执行结果 foreach ($output2 as $line) { echo $line . PHP_EOL; } echo '##############'; echo PHP_EOL; ?>
7 把复杂的数据类型压缩到一个字符串中
7.1 serialize和unserialize的用法
$pantry = array('糖果'=>'2 盒','黄油'=>'3 块'); if(!is_dir('tmp')){ mkdir('tmp',0777); } $fp = fopen('tmp/pantry','w') or die('无法打开食品盒'); fputs($fp,serialize($pantry)); fclose($fp); $newPantry = unserialize(file_get_contents('tmp/pantry')); var_dump($newPantry);
7.2 magic_quotes_gpc 魔术引号开关 此功能php5.4之后的版本,包括5.4,不可用!!!
7.2.1 魔术引号开关的功能:
如果输入的数据有单引号 ' 、双引号 " 、反斜杠 \ 、和空字符 %00
会自动加上反斜杠,
Get/Post/Cookies获得的数据将会更安全,以防sql注入等恶意代码
7.2.2 开启此功能
在php.ini中设置
magic_quotes_gpc = On
7.2.3 使用方式:
$shopping_cart = array("芝麻饼干\'小饼干"=>2, '原味坚果'=>1, '鱼子酱'=>4 ); print '<a href="next.php?cart='.urlencode(serialize($shopping_cart)).'">Next</a>';
next.php
$is = get_magic_quotes_gpc(); var_dump($is); $cart = $_GET['cart']; var_dump($cart); $cartOn = unserialize($cart); var_dump($cartOn);
结果
直接用unserialize解码会返回错误
这时需要使用stripslashes函数先去掉多余的反斜杠
$cartOff = unserialize(stripslashes( $cart)); var_dump($cartOff);
即可正确解析:
最佳使用方式:为了代码的通用性:
function stripslashesed($content) { if (get_magic_quotes_gpc()) { return stripslashes($content); } return $content; } $cartNew = unserialize(stripslashesed($cart)); var_dump($cartNew);
7.3 magic_quotes_sybase 魔术引号开关 此功能php5.4之后的版本,包括5.4,不可用!!!
7.3.1 功能:
和magic_quotes_gpc差不多,转义结果略有差别
7.3.2 使用方法:
echo '<br />'; $gpc = get_magic_quotes_gpc(); var_dump($gpc); //http://localhost/5-07.php?a=%27%22\%00 $a = $_GET['a']; echo $a;
7.4 magic_quotes_runtime 魔术引号开关 此功能php5.4之后的版本,包括5.4,不可用!!!
7.4.1 功能
如果输入的数据有单引号 ' 、双引号 " 、反斜杠 \ 、和空字符 %00
方便 从文件中读取的数据 或 从数据库查询得到的数据时 合理解析。
7.4.2 启用方式
在php.ini中设置
magic_quotes_runtime = On
7.4.3 使用方式
7.4.3.1 读取文件
//查看是否开启 $runtime = get_magic_quotes_runtime(); var_dump($runtime); //test里存储的是:"芝麻饼干\'小饼干" $txt = file_get_contents('test.txt'); var_dump($txt); //string(30) "\"芝麻饼干\\\'小饼干\" " //读取时要加stripslashes var_dump(stripslashes($txt)); //string(26) ""芝麻饼干\'小饼干" "
test.txt里保存的是:"芝麻饼干\'小饼干"
读取时候要加上stripslashes 才能正确解析。
7.4.3.2 写入文件
$txt2 = "\"芝麻饼干\'小饼干\""; $fp2 = fopen('test2.txt','w'); fputs($fp2,$txt2); //test2.txt的保存的是:"芝麻饼干'小饼干" fclose($fp2); //写入时需用addslashes $fp3 = fopen('test3.txt','w'); fputs($fp3,addslashes($txt2)); //test3.txt的保存的是:"芝麻饼干\'小饼干" fclose($fp3); /** * 为了代码通用性 * @param $content * @return mixed|string */ function quotes($content) { if (get_magic_quotes_runtime()) { return addslashes($content); } return $content; } $fp4 = fopen('test4.txt','w'); fputs($fp4,quotes($txt2)); //test4.txt的保存的是:"芝麻饼干\'小饼干" fclose($fp4);
test3和test4加了addslashes之后,能正确写入。
7.4.3.3 从数据库中读取序列化的数据
懒得写代码了。反正现在有更好的方法,已经用不到此功能了。
7.5 magic_quotes_gpc/magic_quotes_sybase 、magic_quotes_runtime 区别
- magic_quotes_gpc/magic_quotes_sybase的设定值将会影响通过Get/Post/Cookies获得的数据
- magic_quotes_runtime的设定值将会影响从文件中读取的数据或从数据库查询得到的数据
magic_quotes_sybase 如果打开的话,将会使用单引号对单引号进行转义而非反斜线,此选项会完全覆盖 magic_quotes_gpc。
如果同时打开两个选项的话,单引号将会被转义成 ''。而双引号、反斜线 和 NULL 字符将不会进行转义。 如何取得其值参见 ini_get()。
具体参考 https://blog.wpjam.com/article/php-magic-quotes-and-wordpress/