遍历字符串
<?php
// 遍历字符串方法
// 方法1,优点:可以控制一次截取几个字符,可以灵活处理每一步。缺点:每次都得调用PHP函数,效率低(需测试)
// $l:一次截取几个字符,默认为0.
function str_split_unicode($str, $l = 0) {
$ret = array();
$len = mb_strlen($str, "UTF-8");
if($str !=null && $len>0){
for ($i = 0; $i < $len; $i += $l) {
$ret[] = mb_substr($str, $i, $l, "UTF-8");
}
}
return $ret;
}
$s = '中华人民abc共和\x01国';
echo '<pre>';
print_r(str_split_unicode($s));
echo '</pre>';
die;
// 方法2,最方便。推荐
// preg_replace 函数通过一个正则表达式分隔字符串。
// /u表示按unicode(utf-8)匹配,PREG_SPLIT_NO_EMPTY返回分隔后的非空部分
$str = '中华人民abc共和\x01国';
$result = preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
var_dump($result);die;
// 方法3
$str = '中华人民abc共和\x01国';
preg_match_all('/[\x{4e00}-\x{9fa5}]/u', $str, $chinese);
preg_match_all('/[^\x{4e00}-\x{9fa5}]/u', $str, $string);
$result = array_merge(current($chinese), current($string));
var_dump($result);die;
// 方法4://UTF8算法,其它编码自行转换
$tempaddtext = '中华人民abc共和\x01国';
$cind = 0;
$arr_cont = array();
for ($i = 0; $i < strlen($tempaddtext); $i++) {
if (strlen(substr($tempaddtext, $cind, 1)) > 0) {
if (ord(substr($tempaddtext, $cind, 1)) < 192) { //如果为英文则取1个字节
if (substr($tempaddtext, $cind, 1) != " ") {
array_push($arr_cont, substr($tempaddtext, $cind, 1));
}
$cind++;
} elseif(ord(substr($tempaddtext, $cind, 1)) < 224) {
array_push($arr_cont, substr($tempaddtext, $cind, 2));
$cind+=2;
} else {
array_push($arr_cont, substr($tempaddtext, $cind, 3));
$cind+=3;
}
}
}
print_r($arr_cont);
类型约束
php是一种弱类型的编程语言。在php程序中,变量的数据类型可以随着其值的不同而自动发生改变,php也不会对变量的数据类型进行强制检查或约束。
示例:
<?php
class Person {
}
$a = 1; //此时,$a为整数类型型(Integer)
var_dump($a);
$a = 1.0; //此时,$a为浮点类型(Float)
var_dump($a);
$a = 'CodePlayer'; //此时,$a为字符串类型(String)
var_dump($a);
$a = array('CodePlayer' => 'http://www.365mini.com'); //此时,$a为数组类型(Array)
var_dump($a);
$a = new Person(); //此时,$a为Person对象类型(Object)
var_dump($a);
$a = mysql_connect('localhost', 'username', 'password'); //此时,$a为资源类型(Resource)
var_dump($a);
大多数的函数参数都只期望是某种特定的数据类型。由于php并不是强类型的语言,也不会强制检查变量的类型,因此我们可以向函数中传递任意类型的参数,从而导致程序报错或逻辑出现异常。
php 5开始,我们就可以使用新增的类型约束机制来对函数参数的部分数据类型进行类型约束。
要使用php的类型约束机制非常简单,我们只需要在函数声明的参数变量前添加指定的类型名称即可。当我们调用该函数时,php会强制检查函数的参数是否为指定的类型,如果不是指定的类型则引发致命错误。
<?php
// 如下面的类
class MyClass {
public $var = 'Hello World';
}
/**
* 测试函数
* 第一个参数必须是 MyClass 类的一个对象
*/
function MyFunction (MyClass $foo) {
echo $foo->var;
}
// 正确
$myclass = new MyClass;
MyFunction($myclass);
值得注意的是,在php 5中,目前只有对象、接口、数组、callable类型的参数变量才能使用类型约束
注意:如果使用类型约束的参数变量没有声明其默认值为null,调用该函数时就不能给对应的参数变量传递null值,否则同样也会报错。
类型约束允许 NULL 值:
<?php
/* 接受 NULL 值 */
function test(stdClass $obj = NULL) {
}
test(NULL);
test(new stdClass);
for循环中++i和i++的区别
for (初始值; 条件; 增量)
{
要执行的代码;
}
参数:
- 初始值:主要是初始化一个变量值,用于设置一个计数器(在循环的开始被执行一次的代码)。
- 条件:循环执行的限制条件。如果为 TRUE,则循环继续。如果为 FALSE,则循环结束。
- 增量:主要用于递增计数器(在循环的结束被执行的代码)。如果代码块中是break退出循环操作,语句三不执行。(这就是循环中的++i和i++结果一样的原因,但是性能不一样,稍后解释)
注释:上面的初始值和增量参数可为空,或者有多个表达式(用逗号分隔)。
++i 和 i++ 的区别
i++和++i只有在直接使用的时候值才有区别,下次使用i值的时候,结果都是加一之后的值
$i = 1;
print_r($i++); // 1,先用后加,需要copy一份$i的值,因为此时$i可以做其它运算,保存一份$i的值,下次使用的时候+1;
$i = 1;
print_r(++$i); // 2,先加后用,$i的值已经是加过的值了,只需要保存此时的$i就行
//无论是i++,还是++i,下次使用i的值的时候,都已经加过1了,
$i = 1;
$i++;
echo $i; // 2,
$i = 1;
++$i;
echo $i; // 2
for循环中++i 和 i++ 的区别
for循环中 ++i 和 i++的结果是一样的,都要等代码块执行完毕才能执行语句3,此时i的值都是加过之后的值。
但是性能是不同的。在大量循环数据的时候++i的性能要比i++的性能好
for($i = 0; $i < 10000; ++$i){ }
i++由于是在使用当前值之后再+1,所以需要保存原值。要先copy变量$i,使用临时的变量来保存,用原来的 $i 继续其他运算,最后再把copy出来的 $ i 做个增加1的运算,然后返还给原来的变量i
<?php
$i = 1;
//先把$i=1赋值给一个临时变量$tmp保存,使用原值1进行运算+5,为6,然后取出$tmp做++运算
$a = $i++ + 5; //此时$i++的值为1,先用后加。
echo $a; // 6
echo $i;//2,此时i++已经生效。为2.
//而++i则是直接+1,省去了对内存的操作的环节,相对而言能够提高性能
<?php
$i = 1;
$a = ++$i + 5; //此时$i++的值为1,先用后加。
echo $a; // 2
echo $i;//2,++$i初次使用的时候就生效了,为2
PHP日期总结
默认时区
date_default_timezone_set(‘PRC’);
今天、昨天、明天 、上一周、下一周,strtotime不指定时间的话默认为当前时间
<?php
今天: date("Y-m-d",time())
昨天的: date("Y-m-d",strtotime("-1 day"))
明天的: date("Y-m-d",strtotime("+1 day"))
一周后: date("Y-m-d",strtotime("+1 week"))
一周零两天四小时两秒后: date("Y-m-d G:H:s",strtotime("+1 week 2 days 4 hours 2 seconds"))
半小时后 date('Y-m-d H:i:s',strtotime("+ 30 minutes"));
下个星期四: date("Y-m-d",strtotime("next Thursday"))
上个周一: date("Y-m-d",strtotime("last Monday"))
一个月前: date("Y-m-d",strtotime("last month"))
一个月后: date("Y-m-d",strtotime("+1 month"))
十年后: date("Y-m-d",strtotime("+10 year"))
指定的时间增加5天
$date1 = "2014-11-11";
echo date('Y-m-d',strtotime("$date1 +5 day"));zc91 //输出结果:2014-11-16
日期拼接
$value['startTime'] ='10:10';
$vtime = $value['startTime'];
$startT = date("Y-m-d $vtime:s"); //date函数里只能放一个变量,如果是$value['startTime']会报错
$expire_time = date('Y-m-d H:i:s',strtotime("$startT +60 minutes")); 直接时间加60分钟
这个月18号0点
这个月的第一天的日期
这个月的最后一天的日期:下个月一号前一天
date('Y-m-1',strtotime('next month')) //下个月的一号 2019-08-01
strtotime(date('Y-m-1',strtotime('next month')).'-1 day') //下个月一号前一天的时间戳
date('Y-m-d',strtotime( date('Y-m-1',strtotime('next month')).'-1 day') ) //将时间戳转换成2019-07-31
上个月第一天
date(‘Y-m-1’,strtotime(‘last month’));
上个月最后一天:这个月1号前一天
date(‘Y-m-d’,strtotime(date(‘Y-m-1’).’-1 day’));
下个月第一天
date(‘Y-m-1’,strtotime(‘next month’));
下个月的最后一天:下下个月1号前一天
date(‘Y-m-d’,strtotime(date(‘Y-m-1’,strtotime(‘next month’)).’+1 month -1 day’));
如何正确的获取上一个月份?
strtotime(“-1 month”) 会有bug,当上一个月或者下一个月没有今天的日时,会输出错误,比如今天是3月30号,但是2月份没有30号,此时date(‘Y-m-d’,strtotime(“-1 month”)); 输出的结果就是 2018-03-01
同理,当在3月31号/5月31号/7月31号/10月31号/12月31号执行date(‘Y-m-d’,strtotime(“-1 month”))时,得到的结果是 3月1号/5月1号//7月1号/10月1号/12月1号。
因为每月都有1号,如果需要获取上一个月的月份,可以获取当前月份1号的前一个月
date(‘Y-m’, strtotime(date(‘Y-m-01’) . “ - 1 month”));
日期可以直接比较大小:
if('2016-10-31 10:34:09' >'2017-10-31 10:34:09'){
echo 1; //输出 1;
}else{
echo 2;
}
返回一个月中的天数。
cal_days_in_month() 函数针对指定的年份和日历,
返回年
注意date参数的第二个参数为时间戳,不写的话默认为当前的时间戳
echo date(‘Y’,strtotime(‘2016-10-31 10:34:09’)); //2016
date第一个参数的格式分别表示:
a - "am" 或是 "pm"
A - "AM" 或是 "PM"
d - 几日,二位数字,若不足二位则前面补零; 如: "01" 至 "31"
D - 星期几,三个英文字母; 如: "Fri"
F - 月份,英文全名; 如: "January"
h - 12 小时制的小时; 如: "01" 至 "12"
H - 24 小时制的小时; 如: "00" 至 "23"
g - 12 小时制的小时,不足二位不补零; 如: "1" 至 12"
G - 24 小时制的小时,不足二位不补零; 如: "0" 至 "23"
i - 分钟; 如: "00" 至 "59"
j - 几日,二位数字,若不足二位不补零; 如: "1" 至 "31"
l - 星期几,英文全名; 如: "Friday"
m - 月份,二位数字,若不足二位则在前面补零; 如: "01" 至 "12"
n - 月份,二位数字,若不足二位则不补零; 如: "1" 至 "12"
M - 月份,三个英文字母; 如: "Jan"
s - 秒; 如: "00" 至 "59"
S - 字尾加英文序数,二个英文字母; 如: "th","nd"
t - 指定月份的天数; 如: "28" 至 "31"
U - 总秒数
w - 数字型的星期几,如: "0" (星期日) 至 "6" (星期六)
Y - 年,四位数字; 如: "1999"
y - 年,二位数字; 如: "99"
z - 一年中的第几天; 如: "0" 至 "365"
PHP抽奖代码
<?php
/*
* 最简单的方法:随机一次数即可
* 不同概率的抽奖原理就是把0到x(比重总数)的区间分块
* 分块的依据是物品占整个的比重,再根据随机数来产生0到x中的某个数
* 判断这个数是落在哪个区间上,区间对应的就是抽到的那个物品。
* 随机数理论上是概率均等的,那么相应的区间所含数的多少就体现了抽奖物品概率的不同。
如一等奖的概率是10%,记为10
二等奖的概率是百分之20,记为10到30,
三等奖的概率是百分之70,记为30到100,
然后mt_rand(1,100),产生随机数,判断在哪个区间中。
*/
/*
* 经典的概率算法,
* $proArr 奖项数组,假设数组为:array(10,20,30,40),中奖总份数是100
* 开始从1,100直接随机一个数;判断第一个数10是否在这个随机出的数的范围之内:<=
* 如果不在,则将中奖的总份数,100减去第一个中奖项的概率:100-10
* 也就是说第二个数是在1,90这个范围内筛选的。这样筛选到最终,总会有一个数满足要求。
* 就相当于去一个箱子里找东西,拿出第一个不是,第二个不是,第三个还不是,那最后一个一定是。
* 这个算法简单,而且效率非常高,
*/
function get_rand($proArr) {
$result = '';
//概率数组的总概率精度
$proSum = array_sum($proArr);
//概率数组循环
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum);
if ($randNum <= $proCur) {
$result = $key;
break;
} else {
$proSum -= $proCur;
}
}
unset ($proArr);
return $result;
}
/*
* 奖项数组
* 其中id表示中奖等级,prize表示奖品,v表示中奖概率。
* 注意其中的v必须为整数,你可以将对应的 奖项的v设置成0,即意味着该奖项抽中的几率是0,
* 数组中v的总和(基数),基数越大越能体现概率的准确性。
* 本例中v的总和为100,那么特等奖中奖概率就是1%,
* 如果v的总和是10000,那中奖概率就是万分之一了。
*/
$prize_arr = array(
array('id'=>0,'prize'=>'特等奖','v'=>10),
array('id'=>1,'prize'=>'一等奖','v'=>20),
array('id'=>2,'prize'=>'二等奖','v'=>30),
array('id'=>3,'prize'=>'没中奖','v'=>40)
);
/*
* 每次前端页面的请求,PHP循环奖项数组$prize_arr,将奖项id和中奖概率组成一个数组$arr
* 通过概率计算函数get_rand获取抽中的奖项id。
* 将中奖奖品保存在数组$res['yes']中,
* 而剩下的未中奖的信息保存在$res['no']中,
* 最后输出json个数数据给前端页面。
*/
foreach ($prize_arr as $key => $val) {
$arr[$val['id']] = $val['v'];
}
// 开始调用抽奖函数
$rid = get_rand($arr); //根据概率获取奖项id
$res['yes'] = $prize_arr[$rid]['prize']; //中奖项
unset($prize_arr[$rid]); //将中奖项从数组中剔除,剩下未中奖项
foreach ($prize_arr as $key => $val) {
$res['no'][$val['id']] = $val['prize'];
}
echo '<pre>';
print_r($res);
echo '</pre>';
die;
// 测试中奖概率,次数越多,越接近理想中的中奖概率
$testCount = 1000; //测试次数
$zj = array();
// 给奖项数组增加count下标,用于显示中奖次数
foreach ($prize_arr as $key => $value) {
$prize_arr[$key]['count'] = 0;
}
for ($i=0; $i < $testCount; $i++) {
$rid = get_rand($arr); //根据概率获取奖项id
$prize_arr[$rid]['count'] +=1; //测试中奖次数
}
// 增加概率统计
foreach ($prize_arr as $key => $value) {
$prize_arr[$key]['countV'] = ($value['count']/$testCount*100).'%';
}
echo '<pre>';
print_r($prize_arr);
echo '</pre>';
函数名不要用PHP关键字
PHP关键字作为函数名,在PHP7里不会报错
但是在低于PHP7的版本就会报错。如果本地开发环境和服务器开发环境不一样的话,就容易出问题。
所以不要使用PHP关键字作为函数名字
还有mysql中,也尽量不要使用mysql的函数 关键字作为字段和数据库名。
如果使用的话,查询的时候需要使用关键字
order 是表名的话,需要这样写:
select * from order
;
通过代码替换mysql group by
<?php
foreach ($testdrive as $key=>$value){
//if else形式可写成三元运算符
$data[$value->memberId]['count'] = !isset($data[$value->memberId]['count'])? 1:$data[$value->memberId]['count']+1;
//is elseif的形式,先赋初始值
if( empty($data[$value->memberId]['approved'])){
$data[$value->memberId]['approved']=0;
}
//然后如果是通过的,加1
if( $value->approve == 'approved'){
$data[$value->memberId]['approved']+=1;
}
}
header() 跳转函数
header(“location:group.php”);
header(“Location:group.php”)
一个开头大写的Location,一个小写,有什么区别?
在我写微信公众号的时候,用户分组管理的接口的时候,修改了分组名之后跳转到分组展示的页面。
使用Location,跳转回去不是更改之后的名称,还需要刷新一下。这个跳转不刷新。
使用location,跳转回去是显示的已经更改的名称。具有跳转刷新功能
//文件延迟转向:
header(‘Refresh: 10; url=http://www.jbxue.com/‘);
<?php
header('HTTP/1.1 200 OK'); // ok 正常访问
header('HTTP/1.1 404 Not Found'); //通知浏览器 页面不存在
header('HTTP/1.1 301 Moved Permanently'); //设置地址被永久的重定向 301
header('Location: http://www.ithhc.cn/'); //跳转到一个新的地址
header('Refresh: 10; url=http://www.ithhc.cn/'); //延迟转向 也就是隔几秒跳转
header('X-Powered-By: PHP/6.0.0'); //修改 X-Powered-By信息
header('Content-language: en'); //文档语言
header('Content-Length: 1234'); //设置内容长度
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT'); //告诉浏览器最后一次修改时间
header('HTTP/1.1 304 Not Modified'); //告诉浏览器文档内容没有发生改变
###内容类型###
header('Content-Type: text/html; charset=utf-8'); //网页编码
header('Content-Type: text/plain'); //纯文本格式
header('Content-Type: image/jpeg'); //JPG、JPEG
header('Content-Type: application/zip'); // ZIP文件
header('Content-Type: application/pdf'); // PDF文件
header('Content-Type: audio/mpeg'); // 音频文件
header('Content-type: text/css'); //css文件
header('Content-type: text/javascript'); //js文件
header('Content-type: application/json'); //json
header('Content-type: application/pdf'); //pdf
header('Content-type: text/xml'); //xml
header('Content-Type: application/x-shockw**e-flash'); //Flash动画
######
###声明一个下载的文件###
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="ITblog.zip"');
header('Content-Transfer-Encoding: binary');
readfile('test.zip');
######
###对当前文档禁用缓存###
header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
######
###显示一个需要验证的登陆对话框###
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Basic realm="Top Secret"');
######
###声明一个需要下载的xls文件###
header('Content-Disposition: attachment; filename=ithhc.xlsx');
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Length: '.filesize('./test.xls'));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: public');
readfile('./test.xls');
######
php中json和js中的json区别
php
正确写法:单引号括起来,json键名必须使用双引号。
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
多维json
$json = '
{
"button": [
{
"name": "3",
"type": "location_select",
"key": "rselfmenu_2_0"
},
{
"name": "3",
"type": "location_select",
"key": "rselfmenu_2_0"
//最后一个json,括号之后不能有逗号了,否则无法使用json_decode
}
]
}
';
取值:
需要转数组或者对象:
对象:
json_decode($json)
echo $json->name;
数组:
json_decode($json,true);
echo $json["name"];
js写法:
1:JSON对象:
var json = {"a":100,"b":200,"c":300,"d":400,"e":500};
取值:alert(json["b"]);
2:JSON字符串:
var json = '{"a":100,"b":200,"c":300,"d":400,"e":500}';
取值:
var obj = eval('(' + json + ')');//把字符串转成JS(可执行js代码),如果eval中的内容含有恶意脚本就麻烦了
var obj = JSON.parse(json);//ie7不支持,需要引入一个js文件,或者使用jq方法。
alert(obj["b"]);
alert(obj.b);
stringify() : 把json转化成字符串
php文件中不需要php结束标记的好处
在纯php文件中不加php结束符是一个好习惯,php结束符仅用于在php与html混写时标示php代码结束。对于纯php文件而言,这个文件结束了,代码就结束了,所以没必要加上结束符。
不加结束符可以让你避免向浏览器发送一些不必要的字符,因为我们非常有可能在结束符后面不小心打上一些空格或者制表符之类的不可见字符,它们在编辑器中不容易被发现,而最后在php执行的时候,会被作为网页字符发送给浏览器,我们查看一些网页的源代码会发现,他们的开头有很多空格和换行,就是因为这个原因。这不仅向浏览器发送了一些不必要的流量,而且对于某些浏览器而言,如果网页源代码没有以<!DOCTYPE或者其它html开头,可能会引起错位。
缩进与对齐:正确地使用Tab和空格
代码的对齐必须使用空格而非Tab,因为tab在不同的编辑器中的大小可能是不一样的,容易导致代码在其他机器上不再对齐。
代码编辑器设置tab制表符转换为空格,为4个空格即可。所以写代码的时候按的是tab,实际上是四个空格。
php双引号和单引号以及连接符混合解读
html中使用:
<a href="class.php?brand_id=<?php echo $brand_id ?>&class_id=<?php echo $rowClass['id'] ?>">More» </a>
php中使用:
echo "<a href='index.php?brand_id={$rowBrand['id']}'>{$rowBrand['bname']}</a> ";
php中如果不使用{}放变量得这样写:
echo "<a href='edit.php?id=".$row["id"]."'>回复</a>";
上面这段代码分开三段看 是这样的 “回复“; 这一段
外层的双引号包含这一个单引号,这个单引号中还有一个双引号。是很规范的。
上面的这几种情况不涉及单引号能不能解析变量的问题。因为echo $a; php是可以直接输出变量的。除非
$a="你好,{$name},我是$myname";
这个情况是需要使用双引号将里面的$name 解析成字符串或者数组等情况。
php里最外面的引号决定是否解析内部变量.
但是:
echo "<td>".$shop['num']*$shop['price'].'</td>';
该作何解释?就像上面的这个”“是单独的。’‘也是单独的。$shop[‘num’]$shop[‘price’]也是单独的。
那为什么”$shop[‘num’]$shop[‘price’]’不用双引号也正确呢?
echo $a;难道$a也要加双引号吗?php直接echo 变量就可以了。
就比如:$name = ‘韩梅梅’;
$a=’我是:$name’;
此时使用echo $a显示的是 我是$name; 因为单引号解析不了变量。需要使用双引号
使用\转义可以实现双引号中包含双引号:
echo"<meta http-equiv=\"refresh\" content=\"0;URL=$url\">";
使用eval函数,把字符串按照 PHP 代码来计算。
$name = '韩梅梅';
$myname = '李磊';
$str = '你好,{$name},我是$myname';
echo $str."<br />";// 直接输出 你好,{$name},我是$myname
eval("\$str = \"$str\";");
echo $str;// 使用eval函数,输出:你好,韩梅梅,我是李磊
实例:
echo '<td><a href="http://www.518up.com/imoocWeixin/access_token.php?route=usereSendMessage&openid= '.$user['openid']. '">查看</a></td>';
使用小括号将运算包起来
变量和字符串拼接的时候,遇到变量需要做运算的情况,使用小括号包起来,因为php连接符号是点,浮点型也用点表示。所以不知道点的作用。用括号包起来
或者将需要运算的内容先赋值给一个变量,这个变量和字符串进行拼接,适合运算步骤多的操作。
<?php
$tempContent = ($key + 1). ':姓名:'.$value -> fullName.',帐号:'.$value -> username.',金额:<span style="color:red;">'.$value -> amount.'</span> 元 <br />';
手机号码归属地
便宜的接口:
https://apis.baidu.com/store/detail/51d4c4fa-002e-4592-853c-2aaedf39d457
此接口已经失效
<?php
$string = '13301297239 黄炎人
15321112689 兆春
15810627195 小柯
18811399186 张会建';
/**
* 手机号码归属地查询
* @param $tel
* @return string
*/
function getLocation($tel)
{
// 过滤参数
if ( !isPhoneNumber($tel) ) return ['code'=>200,'status'=>false,'msg'=>'Cell phone number error!'];
// 请求地址
$url = 'http://mobsec-dianhua.baidu.com/dianhua_api/open/location?tel='.$tel;
// 发起请求
//$res = file_get_contents($url);
$res = curlRequest($url,'','GET');
if ( $res['code'] !== 200 ) return ['code'=>$res['code'],'status'=>false,'msg'=>$res['responseHeader']['msg']];// 判断请求是否成功
$data = $res['response'][$tel];// 接收返回值
if ( !$data ) return ['code'=>200,'status'=>false,'msg'=>'API Exception!'];// 返回值为空
$response['province'] = $data['detail']['province']; // 归属地
$response['city'] = $data['detail']['area'][0]['city']; // 城市
$response['service'] = $data['detail']['operator']; // 运行商
$response['fullname'] = $data['location']; // 运行商全称
return ['code'=>200,'status'=>true,'data'=>$response];
}
/**
* 手机号码格式验证
* @param $tel
* @return bool
*/
function isPhoneNumber($tel)//手机号码正则表达试
{
// return (preg_match("/0?(13|14|15|17|18|19)[0-9]{9}/",$tel))?true:false;
return true;
}
/**
* 发起CURL请求
* @param string $url 请求地址
* @param string $data 请求数据
* @param string $method 请求方式
* @return array 一维数组
*/
function curlRequest($url,$data = '',$method = 'POST')
{
$ch = curl_init(); //初始化CURL句柄
curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而s不是直接输出
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); //设置请求方式
curl_setopt($ch,CURLOPT_HTTPHEADER,array("X-HTTP-Method-Override: $method"));//设置HTTP头信息
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置提交的字符串
$document = curl_exec($ch);//执行预定义的CURL
$code = curl_getinfo($ch,CURLINFO_HTTP_CODE); //获取HTTP请求状态码~
curl_close($ch);
$document = json_decode(removeBOM($document),true);
$document['code'] = $code;
return $document;
}
/**
* 检测并移除 BOM 头
* @param string $str 字符串
* @return string 去除BOM以后的字符串
*/
function removeBOM($str = '')
{
if (substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) {
$str = substr($str, 3);
}
return $str;
}
// 查出号码归属地是厦门的用户和姓名
$arr1 = explode(PHP_EOL, $string);
$xiamenNumber = '';
foreach ($arr1 as $key => $value) {
$phone = explode(' ', $value);
$number = getLocation($phone[0]);
if($number['data']['city'] == '厦门'){
$xiamenNumber.=$phone[0].' '.$phone[1].'<br/>';
}
}
echo '<pre>';
print_r($xiamenNumber);
echo '</pre>';
die;
删除文件
<?
//将gbk文件转为utf8防止中文文件名,unlink删除中文会报错
$path = iconv('utf-8', 'gbk', $quests['oldpic']);
// $path = iconv('utf-8', 'gbk', 'E:\XAMPP\htdocs\baomingpe\public\images\upload\pebaoming\任兆春_15321112689_9.jpg');
//先检查文件是否存在,存在删除。public_path()为laravelpublic绝对目录
if(file_exists(public_path().'\\'.$path)){
unlink(public_path().'\\'.$path);
}
//前台显示图片的时候判断图片是否存在,而非判断数据库是否有记录
<?php $path = iconv('utf-8', 'gbk', $userinfo->pic); ?>
@if (file_exists(public_path().'\\'.$path))
<img id="preview" onclick="fileSelect();" src="{{ URL::asset('/') }}{!!$userinfo->pic!!}" width="150" height="180" style="width: 150px; height: 180px;">
@else
<img id="preview" onclick="fileSelect();" src="{{URL::asset('dist/images/baoming/geshi.png')}}" width="150" height="180" style="width: 150px; height: 180px;">
@endif
根据身份证计算年龄
<?php
// 通过身份证计算年龄
function getAgeByID($id)
{
if (empty($id)) return '';
$date = strtotime(substr($id, 6, 8)); //获得出生年月日的时间戳
$today = strtotime('today'); //获得今日的时间戳
// floor() 函数向下舍入为最接近的整数。
$diff = floor(($today - $date) / 86400 / 365); //得到两个日期相差的大体年数
//过了这年的生日才算多了1周岁
$age = strtotime(substr($id, 6, 8) . ' +' . $diff . 'years') > $today ? ($diff + 1) : $diff;
return $age;
}
// 导出身份证为Excel格式,没有双引号
$idcard = "111111x85846464613
432522196809270756
441322198705264019
320826196401010410
352224196706280018";
// 计算年龄
function unique($idcard){
$arr = explode(PHP_EOL, $idcard);
$ageArr=array();
$ageArr['25以下']=0;
$ageArr['25-30']=0;
$ageArr['30-35']=0;
$ageArr['35-40']=0;
$ageArr['40-45']=0;
$ageArr['45-50']=0;
$ageArr['50以上']=0;
foreach ($arr as $key => $value) {
if(getAgeByID($value)<25){
$ageArr['25以下']++;
}elseif(getAgeByID($value)>=25 && getAgeByID($value)<30){
$ageArr['25-30']++;
}elseif(getAgeByID($value)>=30 && getAgeByID($value)<35){
$ageArr['30-35']++;
}elseif(getAgeByID($value)>=35 && getAgeByID($value)<40){
$ageArr['35-40']++;
}elseif(getAgeByID($value)>=40 && getAgeByID($value)<45){
$ageArr['40-45']++;
}elseif(getAgeByID($value)>=45 && getAgeByID($value)<50){
$ageArr['45-50']++;
}else{
$ageArr['50以上']++;
}
}
return $ageArr;//返回值,返回到函数外部
}
echo '<pre>';
print_r(unique($idcard));
echo '</pre>';
die;
防刷票思考 - 小果果 - SegmentFault
刷票行为,一直以来都是个难题,无法从根本上防止。
但是我们可以尽量减少刷票的伤害,比如:通过人为增加的逻辑限制。
基于 PHP,下面介绍防刷票的一些技巧:
1、HTTP_REFERER : 校验 $_SERVER[‘HTTP_REFERER’]。可伪造,使用 CURL。
curl_setopt($ch, CURLOPT_REFERER, ‘HTTP://www.baidu.com’);(攻击手段)
2、IP限制:加上 IP 投票限制。可伪造,使用 CURL。
$ip = ...;$header = array( “CLIENT-IP:{$ip}”, “X-FORWARDED-FOR:{$ip}”,);curl_setopt($ch, CURLOPT_HTTPHEADER, $header);(攻击手段)
3、User-Agent:校验 $_SERVER[‘HTTP_USER_AGENT’]。可伪造,使用 CURL。
curl_setopt($ch, CURLOPT_USERAGENT, “Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.0)”);(攻击手段)
4、验证码:采用非常复杂的验证码,可以防止一些菜鸟攻击者。
a:但是专业刷票机可以攻破。如果不用验证码,投票基本就歇菜了。b:验证码获取方式,采用异步加载,即点击输入框时,才去请求。c:投票成功后,删除验证码的 Session。
5、登录:用户必须登录才能投票。
a:可以攻破,写程序不断注册新用户,然后用来投票。(攻击手段)b:指定大于某个 UID 的用户,或者某段时间内活跃的用户,才能进行投票。(预防对策)
6、限时投票:投票程序,只在某个时间段内开放。否则,对方半夜刷票,你咋办?
a:从 早 8 点 至 晚 23 点。(预防对策)
7、投票间隔:用户投票后,需要隔多长时间才能继续投。
a:很多投票站点基本上都有这个限制,但是对于更改 IP的攻击,就没办法了。b:针对 UID 限制,可以有效防止攻击,但是可以使用批量注册马甲用户。
8、投票结果展示:延迟展示,友好展示。
a:页面上投票,JS 立马加1,但是刷新页面,不一定立马展示最新投票结果。b:返回状态给页面(感谢您的投票!或者 投票成功!至于有没有成功,另说了!)
9、补票逻辑:常见于一些软件评选之类的投票。
a:有时候软件厂商会为了让自己的票数高一点,会私下给活动举办商 $,后台进行补票。b:后台跑脚本,采用 IP 库,缓慢平滑的增加票数。
10、扣量逻辑:常见于一些软件评选之类的投票。
a:这是个杀手锏,后台跑脚本实时监控异常增长(刷票)的项,然后实施扣量逻辑。b:即对于这个项,投 10 票才算一票。
11、Cookie:常用的手段。比较低级。
a:投票后,在客户端写入 Cookie,下次投票时判断 Cookie 是否存在。b:但是,这种方式非常容易攻破,因为 Cookie 可删除。
12、加密选项 ID:对一些投票选项的ID,进行随机加密。
a:加密算法,加Salt,并且设置有效时间,比如5分钟内。b:服务器端进行解密并且验证。
13、人工刷票:没办法防。。
a:雇佣了一批水军,进行刷票,这个真没辙,人家确实是花了血本的。
递归
<?php
// 源程序
function digui($var){
echo $var;
if($var>0){
digui($var-1);
}else{
echo '-----------';
}
echo $var;
}
digui(4);
// 当我第一次调用4的时候,先上面,然后执行中间的一些流程。流程执行完毕最后输出4,下面也会输出4,
// 分析代码过程
function digui(4){
echo 4; 4
if($var>0){
function digui(3){
echo 3; 3
if($val>0){
function digui(2){
echo 2; 2
if($val>0){
function digui(1){
echo 1; 1
if($val>0){
function digui(0){
echo 0; 0
if($val>0){
//这里条件不成立了!所以这里不再执行
}else{
echo '----------------'; ---------------------
}
echo 0; 0
}
}else{
echo '-------------';
}
echo 1; 1
}
}else{
echo '------------';
}
echo 2; 2
}
}else{
echo '----------';
}
echo 3; 3
}
}else{
echo '-----------';
}
echo 4; 4
}
?>