PHP 二维数组 按照 Value 中某 key 进行排序 获得另一个 key 的排序

<?php
$arr = [
    ['id'=>1,'main'=>222],
    ['id'=>2,'main'=>333],
    ['id'=>2,'main'=>444],
    ['id'=>1,'main'=>111],
    ['id'=>3,'main'=>122],
    ];
    
    $a = array_column($arr,'main');
    $b = array_column($arr,'id');
    
    echo "<pre>";
    var_dump($a,$b);
    var_dump(array_multisort($a,SORT_DESC,$b));
    var_dump($a,$b);
?>

array_multisort() 先把第一个数组按照键值的大小排序,然后其它数组都按照第一个数组的调整策略进行调整。

优化一下则为

<?php

$arr = [
    ['id'=>1,'main'=>222],
    ['id'=>2,'main'=>333],
    ['id'=>2,'main'=>444],
    ['id'=>1,'main'=>111],
    ['id'=>3,'main'=>122],
    ];
    
    echo "<pre>";
    array_multisort(array_column($arr,'main'),SORT_DESC,$arr);
    var_dump($arr);
?>

简单测试一下 PHP mt_rand( ) 函数一秒钟重复值

<?php
echo "<pre>";

$start = microtime(true);
$end = microtime(true);
$rand = [];
$i = 0;
do{
    $theRand = mt_rand(0,99999);
    if(in_array($theRand,$rand)){
        $i=$i+1;
    }
    $rand[] = $theRand;
    $end = microtime(true);
}while(($end-$start)<1);

echo $i;
echo "<br>";
echo count($rand);
?>

多次测试后,

当随机数为 0 – 99999 时,每秒约能生成 25000 个随机数,重复的约为 3000

当随机数为 0 – 999999 时,每秒约能生成 25000 个随机数,重复的约为 300

机数为 0 – 9999999 时,每秒约能生成 25000 个随机数,重复的约为 30

一秒钟内生成两个随机数撞车的概率还是蛮大的

起因是做活动,订单号貌似重复了,高峰期一分钟八单

一些 PHP 函数

两个日期之间的全部日期

//两个日期之间的日期数组形式
function prDates($start,$end){
  $dt_start = strtotime($start);
  $dt_end = strtotime($end);
  $date = array();
  while ($dt_start<=$dt_end){
    $date[] = date('Y-m-d',$dt_start);
    $dt_start = strtotime('+1 day',$dt_start);
  }
  return $date;
}

位数补零

$number=sprintf ( "%02d",$number);

数组的指定key后面插入数据

function array_push_after_key($array, $data=null, $key=false){
  $data  = (array)$data;
  $offset  = ($key===false)?false:array_search($key, array_keys($array));
  $offset  = ($offset)?$offset:false;
  if($offset){
    return array_merge(
      array_slice($array, 0, $offset+1),
      $data,
      array_slice($array, $offset+1)
    );
  }else{  //找不到key,就直接加到末尾
    return array_merge($array, $data);
  }
}

PHP 正则匹配替换 HTML 的 IMG 标签 SRC 属性,添加图片域名

private function preg_match($img){
  $newImg = preg_replace('/(<img.+?src=")(.*?)/','$1'.base_url().'$2', $img);
  return $newImg;
}

PHP 图片压缩至指定尺寸 封装函数

/**
 * @param $img 图片地址
 * @param string $width 宽
 * @param string $height 高
 * @param string $ratio 保持原比例
 * @return string 生成的地址
 */
public function resize_fuc($img, $width, $height, $ratio)
{

	$info = get_img_info($img);
	$name = pathinfo($img)['filename'];
	$dirname = pathinfo($img)['dirname'];
	$ext = pathinfo($img)['extension'];

	$im = NULL;
	$type = strtolower($info['type']);

	if (!in_array($type, ['jpg', 'jpeg', 'gif', 'png'])) {
		return FALSE;
	}
	$type = ($type == 'jpg' ? 'jpeg' : $type);

	$scale = $info['width'] / $info['height'];

	if ($ratio == TRUE) {
		$forScale = $width / $height;
		$x = 0;
		$y = 0;
		if ($scale >= $forScale) {
			$width = (int)($height * $scale);
			$rate = $info['height']/$height;
		} else {
			$height = (int)($width / $scale);
			$rate = $info['width']/$width;
		}
	} else {
		$forScale = $width / $height;
		if ($scale >= $forScale) {
			$x = ($info['width'] - $info['height'] * $forScale) / 2;
			$y = 0;
			$rate = $info['height'] / $height;
		} else {
			$x = 0;
			$y = ($info['height'] - $info['width'] / $forScale) / 2;
			$rate = $info['width'] / $width;
		}
	}

	if($width>$info['width'] || $height>$info['height']){
		return;
	}


	$imageCreateFun = 'imagecreatefrom' . $type;
	$im = $imageCreateFun($img);
	$thumb = $dirname . '/' . $name . '_tmp' . "." . $ext;

	$imageFun = 'image' . $type;
	$imageFun($im, $thumb);

	$thumbNew = imagecreatetruecolor($width, $height);

	imagecopyresampled(
		$thumbNew, $im,
		0, 0, intval($x), intval($y),
		intval($width * 1), intval($height * 1), intval($width * $rate), intval($height * $rate)
	);

	$imageFun($thumbNew, $thumb);

	imagedestroy($im);
	imagedestroy($thumbNew);

	rename($thumb,$img);
	return $img;
}
function get_img_info($img) {
    if(!is_file($img) || !in_array(strtolower(pathinfo($img)['extension']),['jpg','jpeg','bmp','gif','png'])){
        return false;
    }
    $img_info = getimagesize($img);
    if ($img_info !== false) {
        $img_type = strtolower(substr(image_type_to_extension($img_info[2]), 1));
        $info = array("width" => $img_info[0], "height" => $img_info[1], "type" => $img_type, "mime" => $img_info['mime'], );
        return $info;
    } else {
        return false;
    }
}

PHP 使用 exec 搭配 MozJPEG 的一些心得

环境 CentOS 7 PHP 7.2.6

查看 php 所在用户与用户组

为 www:www

将 www 用户添加至 root 权限

visudo
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
www     ALL=(ALL) NOPASSWD: ALL

允许 root 用户执行任何命令在任何位置。NOPASSWD  后为执行哪些命令不用输入密码

reboot 重启系统

PHP 测试命令

echo exec('php -v',$a1,$b1);
dump($a1);dump($b1);

echo exec('sudo /opt/mozjpeg/bin/cjpeg -version',$a2,$b2);
dump($a2);dump($b2);

echo exec('sudo /opt/mozjpeg/bin/cjpeg -quality 60 -debug /home/wwwroot/hi.unetu.net/public/tmp/uploads/1.jpeg > /home/wwwroot/hi.unetu.net/public/uploads/1.jpeg',$a3,$b3);
dump($a3);dump($b3);

die();

返回结果

exec 中第三个参数为 0 表示执行成功,其他值如 1 表示失败,上述代码表示执行成功但第二和第三个命令没有返回值也没有输出值

其中第三条 mozjpeg/cjpeg 的压缩图片执行成功

如果想要返回值,查找了一下可以使用管道,在命令添加 2>&1,尝试如下

返回结果

第二条输出了语句,第二条和第三条也都执行成功,但第三条的图片损坏了无法预览

这和在命令行里使用相同命令执行的结果一致

其他尝试

第三条 MozJPEG 如果原图片损坏,则第三条返回 int(1),表示执行失败

参考文献

浅谈PHP的exec()函数无返回值排查方法

https://www.jb51.net/article/110108.htm

PHPExcel 超过 26 列 解决方法

ThinkPHP 3.2 使用 PHPExcel

使用 chr(ord(‘A’)++) 的方法进行 Excel 列的自增,当列数超过26列时,会报如下错误

Invalid cell coordinate [1
错误位置
FILE: E:\wwwroot\wanaioa.a.cc\ThinkPHP\Library\Vendor\Excel\PHPExcel\Cell.php  LINE: 539

原因是 ord(‘Z’) 为 90,当 chr(91) 时为 string(1) “[“

但在 Excel 中应为 AA

解决方法是使用 PHPExcel 自带函数 stringFromColumnIndex

调用方法

\PHPExcel_Cell::stringFromColumnIndex(27);

源码为

/**
 *	String from columnindex
 *
 *	@param	int $pColumnIndex Column index (base 0 !!!)
 *	@return	string
 */
public static function stringFromColumnIndex($pColumnIndex = 0)
{
	//	Using a lookup cache adds a slight memory overhead, but boosts speed
	//	caching using a static within the method is faster than a class static,
	//		though it's additional memory overhead
	static $_indexCache = array();

	if (!isset($_indexCache[$pColumnIndex])) {
		// Determine column string
		if ($pColumnIndex < 26) {
			$_indexCache[$pColumnIndex] = chr(65 + $pColumnIndex);
		} elseif ($pColumnIndex < 702) {
			$_indexCache[$pColumnIndex] = chr(64 + ($pColumnIndex / 26)) .
										  chr(65 + $pColumnIndex % 26);
		} else {
			$_indexCache[$pColumnIndex] = chr(64 + (($pColumnIndex - 26) / 676)) .
										  chr(65 + ((($pColumnIndex - 26) % 676) / 26)) .
										  chr(65 + $pColumnIndex % 26);
		}
	}
	return $_indexCache[$pColumnIndex];
}

路径 

ThinkPHP/Library/Vendor/Excel/PHPExcel/Cell.php

封装一个 PHPExcel 的导出方法

本篇以 ThinkPHP 为示例

public function getExcel($property,$headArr,$data){

	Vendor('Excel.PHPExcel');
	$objPHPExcel = new \PHPExcel();
	$objPHPExcel
		-> getProperties()
		-> setCreator($property['creator'])
		-> setLastModifiedBy($property['last'])
		-> setTitle($property['title'])
		-> setSubject($property['subject'])
		-> setDescription($property['description'])
		-> setKeywords($property['keywords'])
		-> setCategory($property['category']);

	$column = 1;
	$span = ord("A");
	foreach($headArr as $v){
		$j = chr($span);
		$objPHPExcel->setActiveSheetIndex(0) -> setCellValue($j.$column,$v);
		$span ++;
	}

	$column ++;
	$objActSheet = $objPHPExcel->getActiveSheet();
	foreach($data as $key => $rows){
		$span = ord('A');
		foreach($rows as $keyName => $value){
			$j = chr($span);
			$objActSheet->setCellValue($j.$column, $value);
			$span ++;
		}
		$column ++;
	}

	$objPHPExcel->setActiveSheetIndex(0);

	ob_end_clean();
	ob_start();

	header("Content-Type: application/force-download");
	header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
	header("Content-Disposition:attachment;filename =" . str_ireplace('+', '%20', URLEncode($fileName)).'.xlsx');
	header('Cache-Control: max-age=0');

	$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
	$objWriter -> save('php://output');
	exit ;
}

调用

public function _index_export(){
	$property = array('title'=>'测试');
	$headArr = array('好','坏');
	$data = array(
		array(
			3,4
		),
		array(
			5,6
		)
	);
	$this->getExcel($property,$headArr,$data);
}

优化当超过 26 列

public function getExcel($property,$headArr,$data){

	Vendor('Excel.PHPExcel');
	$objPHPExcel = new \PHPExcel();
	$objPHPExcel
		-> getProperties()
		-> setCreator($property['creator'])
		-> setLastModifiedBy($property['last'])
		-> setTitle($property['title'])
		-> setSubject($property['subject'])
		-> setDescription($property['description'])
		-> setKeywords($property['keywords'])
		-> setCategory($property['category']);

	$column = 1;
	$span = 0;
	foreach($headArr as $v){
		$letter = \PHPExcel_Cell::stringFromColumnIndex($span);
		$objPHPExcel->setActiveSheetIndex(0) -> setCellValue($letter.$column,$v);
		$span ++;
	}

	$objActSheet = $objPHPExcel->getActiveSheet();
	foreach($data as $key => $rows){
		$column ++;
		$span = 0;
		foreach($rows as $keyName => $value){
			$letter = \PHPExcel_Cell::stringFromColumnIndex($span);
			$objActSheet->setCellValue($letter.$column, $value);
			$span ++;
		}
	}

	$objPHPExcel->setActiveSheetIndex(0);

	ob_end_clean();
	ob_start();

	header("Content-Type: application/force-download");
	header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
	header("Content-Disposition:attachment;filename =" . str_ireplace('+', '%20', URLEncode($property['title'])).'.xlsx');
	header('Cache-Control: max-age=0');

	$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
	$objWriter -> save('php://output');
	exit ;
}

可以设置列宽的一种方法

public function exportExcel($expTitle,$expCellName,$expTableData){
	$xlsTitle = iconv('utf-8', 'gb2312', $expTitle);//文件名称
	$fileName = $expTitle.date('_Ymd_His');//or $xlsTitle 文件名称可根据自己情况设定
	$cellNum = count($expCellName);
	$dataNum = count($expTableData);
	Vendor('Excel.PHPExcel');
	$objPHPExcel = new \PHPExcel();
	$cellName = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','AA','AB','AC','AD','AE','AF','AG','AH','AI','AJ','AK','AL','AM','AN','AO','AP','AQ','AR','AS','AT','AU','AV','AW','AX','AY','AZ');
	// $objPHPExcel->getActiveSheet(0)->mergeCells('A1:'.$cellName[$cellNum-1].'1');//合并单元格
	// $objPHPExcel->setActiveSheetIndex(0)->setCellValue('A1', $expTitle.'  Export time:'.date('Y-m-d H:i:s'));//第一行标题
	for($i=0;$i<$cellNum;$i++){
		$objPHPExcel->setActiveSheetIndex(0)->setCellValue($cellName[$i].'1', $expCellName[$i][1]);
		$objPHPExcel->getActiveSheet()->getColumnDimension($cellName[$i])->setWidth($expCellName[$i][2]); //设置宽度
	}
	// Miscellaneous glyphs, UTF-8
	for($i=0;$i<$dataNum;$i++){
		for($j=0;$j<$cellNum;$j++){
			$objPHPExcel->getActiveSheet(0)->setCellValue($cellName[$j].($i+2), $expTableData[$i][$expCellName[$j][0]]);
		}
	}
	header('pragma:public');
	header('Content-type:application/vnd.ms-excel;charset=utf-8;name="'.$xlsTitle.'.xls"');
	header("Content-Disposition:attachment;filename=$fileName.xls");//attachment新窗口打印inline本窗口打印
	$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
	$objWriter->save('php://output');
	exit;
}

调用

public function dumpLogsExcel(){
	//查询数据
	$where['member_card'] = 123456;
	$xlsData = array();//二维数组
	//构建excel
	$xlsName  = "用户评价信息表";
	$xlsCell  = array(
		array('GongSiMc','门店名称',20),
		array('order_num','保养单号',20),
		array('wx_name','微信名',20),
		array('member_card','会员卡号',15),
		array('is_good_name','是否满意',10),
		array('evaluate_item','具体评价',40),
		array('score','得分',10),
		array('create_time','创建时间',20),
	);
	$this->exportExcel($xlsName,$xlsCell,$xlsData);
}