`PHP`分类下的文章

PHP

引用符号'&'在foreach循环中的惊喜

工作中总会遇到一些奇奇怪怪的由前人所写下的不可置疑的代码,如果你仅仅跟着眼前所见的代码去理解他人的思路,Well You have fell into a terrible situation.

贴一段示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
$students = [
['name'=>'Jackson','age'=>15],
['name'=>'Jerry','age'=>14],
['name'=>'Amy','age'=>14]
];
$classes = [
'CL001'=>['name'=>'Language','classTime'=>30],
'CL002'=>['name'=>'PE','classTime'=>13]
];

/*
* 循环$students,为其添加一个属性'name-age'
* 这里使用了&$v以获得数组内部元素的引用,使的可以在循环体内修改元素内容
*/
foreach ($students as $k=>&$v){
$v['name-age'] = $v['name'] . '-' .$v['age'];
}

$classString = ''; //定义一个空串
/*
* 循环$classes,将所有课程ID和名称联结成串
*/
foreach ($classes as $k=>$v){
$classString .= 'ClassID:'.$k.'-'.$v['name'].PHP_EOL;
}
echo $classString;
var_dump($students); //Think here!

你也许会回答这样一个输出结果:

阅读剩下更多

默认配图
PHP

PHP加解密算法使用openssl替换mcrypt扩展

PHP版本从7.2开始不再支持mcrypt扩展,所以我们需要使用OpenSSl对其进行替换。本文仅列出部分算法的替换示例,所以不在本文出现的算法或模式需要自行尝试,顺水推舟。

本文替换案例:

  1. MCRYPT_RIJNDAEL_128 | MCRYPT_MODE_ECB => AES-128-ECB
  2. MCRYPT_DES | MCRYPT_MODE_CBC => DES-CBC
  3. MCRYPT_RIJNDAEL_128 | MCRYPT_MODE_CBC => AES-128-CBC
  4. MCRYPT_XTEA | MCRYPT_MODE_CBC

在使用 MCRYPT_RIJNDAEL_128 的地方,如果秘钥长度分别为16、24、32,则加密算法用 AES-128-ECB、AES-192-ECB、AES-256-ECB,BlockSize为16、24、32。

首先列出需要用到的数据填充方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function ZeroPadding($str, $block = 16) {
$pad = $block - (strlen($str) % $block);
if($pad == $block) return $str;
return $str.str_repeat(chr(0),$pad);
}
function ZeroUnPadding($str) {
return rtrim($str, "\0");
}


function PKCS7Padding($str, $block_size) {
$padding_char = $block_size - (strlen($str) % $block_size);
$padding_str = str_repeat(chr($padding_char),$padding_char);
return $str.$padding_str;
}
function PKCS7UnPadding($str) {
$char=substr($str,-1,1);
$num=ord($char);
if($num>0 && $num <= strlen($str)) {
$str = substr($str, 0, -1 * $num);
}
return $str;
}

阅读剩下更多

默认配图
PHP

Pazzle on array_column

  在PHP中内置的对数组操作的方法(函数)有一个叫做’array_column’的非常实用,它可以用作返回一个二维数组的指定列。

  先介绍一下它!

  好比这样一个用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$students = array(
array(
'id'=>1,
'name'=>'Jerry'
),
array(
'id'=>3,
'name'=>'Tom'
),
array(
'id'=>6,
'name'=>'Lily'
),
array(
'id'=>11,
'name'=>'Bob'
),
);
$student_names = array_column($students,'name');
var_dump($student_names);

输出结果:

1
2
3
4
5
array (size=4)
0 => string 'Jerry' (length=5)
1 => string 'Tom' (length=3)
2 => string 'Lily' (length=4)
3 => string 'Bob' (length=3)

  这样就得到了一个所有名字的数组,想必对于一个PHPER来说并不陌生。但是今天要讲的重点是array_column的另外一个用法,如果给它第三个参数,那么它将以第三个参数对应的数组中的值作为返回数组的键,用例如下:

阅读剩下更多

默认配图
PHP

array_walk中的$this报错

Fatal Error:Using $this when not in object context on line 54

  今天在完成一个小功能开发并提交SVN后,收到前端的求助,说是更新了我的代码后页面打不开了。很着急啊,我这里都是测试成功才提交版本的。现在只能麻溜的跑过查看了。

  首先,出现的情况是空白页面(对,没有任何输出)。报错肯定没打开,帮他打开E_ALL后就看到了今天的重点报错提示了。说是在54行有个$this不在对象环境中?

  然后我去看了,那个$this出现在array_walk方法的function中,从语句上来看是完全没有问题的,在类的方法里面用$this肯定没毛病啊,可是为什么他那里就报错呢?

  我突然想起来,如果要在array_walk里面使用外面的变量的时候需要使用use方法。所以改进一下:

1
2
3
4
$user_id = $this->user->id;
array_walk($arr,function(&$v) use($user_id) {
$v['user_id']=$user_id;
});

  这样就没毛病了。看来这个array_walk还挺调皮啊,不得不说这个方法的使用还真有许多需要注意的地方呢。

  通过查资料,得知这个$this在PHP版本低于5.4的情况下是会出现问题的。高版本的不会出现。

参考:Using $this when not in object context error within array_walk

阅读剩下更多

默认配图
PHP

PHP时区默认为Europe/zurich且修改php.ini无效的困惑

为何我的date(“Y/m/d H:i:s”)相差了7个小时?

环境:MacOS X EI Capitan / PHP5.6.25

  今天在校验Crontab的计划执行时,利用PHP输出执行时间却发现输出的时间和当地事件相差了7个小时,对!是7不是8,并不是默认的UTC,呵呵了~

  好吧,一贯思路,我去把php.ini中的date.timezone修改成PRC。嗯,肯定正常了吧。

  要能正常我也不会写本文了^_~!

  不论是修改成PRC还是Asia/Shanghai又或者UTC,全都未然。   


  1. apache输出phpinfo(),查看date区域它的Default Timezone还是没变。
    Phpinfo的date区域
  2. 在控制台查看php -i | grep zone也还是同样没变
    控制台输出timezone
  3. 核对加载的php.ini文件是否正确并且配置信息格式是否正确

  4. 控制台使用php -a交互模式,调用ini_get('date.timezone'),检查配置的INI是否生效

  全都没有任何问题啊!!!为什么结果却出乎意料呢??百度,谷歌我都问遍了,大家没人出现我这样的情况啊。正当我发愁的时候,小伙伴过来给我支招了。

阅读剩下更多

默认配图
PHP

php上传进度之uploadprogress

我的学习是项目驱动,这次遇到的需求是上传进度条。

注意:此方法仅在Apache下运行PHP时有效,如果您采用FastCGI方式(如:Nginx+fpm),这个不适用!

通过查PHP手册,了解到PHP版本5.4+有一个新特性uploadprogress,也可以说是新扩展吧!

1
2
当 session.upload_progress.enabled INI 选项开启时,PHP 能够在每一个文件上传时监测上传进度。 这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态
当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,上传进度可以在$_SESSION中获得。 当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据, 索引是 session.upload_progress.prefix 与 session.upload_progress.name连接在一起的值。

将这个扩展启用,需要开启PHP.INI支持:

session.upload_progress.enabled = On
session.upload_progress.cleanup = On
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
session.upload_progress.freq = "1%"
session.upload_progress.min_freq = "1"

  当然,我按照官方的示例操作了N久,就是读不到此类session的值。一开始以为是公司框架的问题,后来自己在本地单独写文件来测试,结果还是一样!

  在网上查找各种此类问题的解决办法,虽说有相同提问的,但是解答问题的人根本就没找到根本的原因。其实很简单:上传的文件Size太小

阅读剩下更多

默认配图
PHP

一种较好的实现PHP异步发送邮件的实现

前些天在写我的TR-System(社团招新管理系统)的时候,用到了邮箱验证用户注册,也就是注册成功后,需要访问收到的邮件中的URL进行用户激活。这个事件发生在用户提交注册请求之后,系统需要立即发送一封邮件用于激活,但是系统在调用PHPMailer的时候需要进行SMTP连接邮箱系统(用的腾讯企业邮),往往在这个时候会出现等待的情况。如果让用户来承担这个等待时间,体验也太差了!,没见过哪个系统上注册个用户,还需要慢慢等待系统告诉我到底有没有注册成功。
一开始在写的时候,直接在POST请求中处理,写入数据库后就调用sendEmail方法,情况是这样的:
1.提交注册 --> 2.写入数据库 --> 3.发送Email --> 4.注册成功。
这样在用户看来是有一个漫长的等待的。
实际上应该为:
1.提交注册 --> 2.写入数据库 --> 3.注册成功。 ||||||||||||||||||-->发送Email
这样的才是一个拥有良好用户体验的系统 ^_^ 。
若是在Java等环境下,咱们可以很好利用多线程,分出来一个任务让另一个线程去完成。
但是!PHP这个单线程环境下,没有new Thread来搞这个事情啊。 不过,换一个角度,线程不行的,我就给个新进程呗。当然不是在当前进程创建新进程。

阅读剩下更多

默认配图
PHP

分享一个PHP修改ini配置文件的类

.ini配置文件 有简单类型 和 复杂类型:
简单的不带节点,如:
username=myname
userage=21
userinfo=i’m a boy

另一种带有节点,如mysql的配置文件my.ini(windows下):
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 16M
max_allowed_packet = 1M
table_open_cache = 64

阅读剩下更多

默认配图
PHP

上传Excel表格写入数据表(上传订单功能)

代码包:ExcelToMysql
此项功能的实现依赖PHPExcelReader,下载压缩包可得。
下面贴出PHP主要实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<form id="form1" name="form1" method="post" action="">
<label>
<input name="file" type="file" id="file13"/>
<input type="submit" name="Submit" value="提交" />
</label>
</form>
<p>
<?php
require_once 'reader.php';
$Reader = new Spreadsheet_Excel_Reader();
$Reader->setOutputEncoding('gbk');
$conn= mysql_connect('localhost','root','root') or die("Can not connect to database.");
mysql_query("set names 'gbk'");//设置编码输出
mysql_select_db('my_db'); //选择数据库
if($_POST['Submit'])
{
$Reader->read($_POST['file']);

for ($i = 2; $i <= $Reader->sheets[0]['numRows']; $i++) {
//将EXCEL里面从第二行开始写入数据表'my_table'中
$sql = "INSERT INTO my_table VALUES (null,'".$Reader->sheets[0]['cells'][$i][1]."','".$Reader->sheets[0]['cells'][$i][2]."','".$Reader->sheets[0]['cells'][$i][3]."','".$Reader->sheets[0]['cells'][$i][4]."','".$Reader->sheets[0]['cells'][$i][5]."','".$Reader->sheets[0]['cells'][$i][6]."','".$Reader->sheets[0]['cells'][$i][7]."','".$Reader->sheets[0]['cells'][$i][8]."','".$Reader->sheets[0]['cells'][$i][9]."')";

$query=mysql_query($sql);
if($query)
{
echo "<script type=\"text/javascript\"><!--
alert('数据已经提交成功');window.top.location='a.php'
// --></script>";
}else{
echo "<script type=\"text/javascript\"><!--
alert('数据已经提交失败');window.top.location='a.php'
// --></script>";
}
}
}
?>

阅读剩下更多

默认配图
返回顶部