Home » Code » PHP拾零

PHP拾零

生成不重复随机数

function distinct_int($num, $min = 1, $max = 10000) {
    $count = 0;
    $result = array();
    while ($count < $num) {
        $result[] = mt_rand($min, $max);
        $result = array_flip(array_flip($result));
        $count = count($result);
    }
    return $result;
}

获得客户端IP

function get_client_ip() {
	$client_ip = '';
	$client_ip_list = '';
	if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
	{
		$client_ip_list = $_SERVER['HTTP_X_FORWARDED_FOR'];
	}
	elseif (!empty($_SERVER['HTTP_X_REAL_IP']))
	{
		$client_ip_list = $_SERVER['HTTP_X_REAL_IP'];
	}
	elseif (!empty($_SERVER['HTTP_PROXY_FORWARDED_FOR']))
	{
		$client_ip_list = $_SERVER['HTTP_PROXY_FORWARDED_FOR'];
	}
	if (strpos($client_ip_list, ',') !== false)
	{
		$client_ip = strstr($client_ip_list, ',', true);
	}
	else
	{
		$client_ip = $client_ip_list;
	}
	if (empty($client_ip))
	{
		$client_ip = empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR'];
	}
	return $client_ip;
}

判断正则表达式是否合法

有时候需要判断一个正则表达式是否合法,可以让它跟null来进行匹配:preg_match($regularString, null),如果结果 === false,则$regularString是有问题的,否则是无问题的。如果有问题会有错误报出,可以考虑在前边加上@符号。不要想着用正则去判断正则,没有必要也是浪费时间!参见这里

validate_regular

二维数组排序

$scores = [
  ['type' => 1, 'value' => 10],
  ['type' => 1, 'value' => 20],
  ['type' => 3, 'value' => 50],
  ['type' => 4, 'value' => 80],
  ['type' => 2, 'value' => 50],
  ['type' => 4, 'value' => 50],
  ['type' => 4, 'value' => 60],
  ['type' => 3, 'value' => 160],
];

//需求:按type排序,先后顺序为4, 3, 1, 2

//方案1
$typeSort = [];
foreach ($scores as $key => $value)
{
  switch ($value['type']) {
    case 4:
      $weight = 1;
      break;
    case 3:
      $weight = 2;
      break;
    case 1:
      $weight = 3;
      break;
    case 2:
      $weight = 4;
      break;
  }
  $typeSort[$key] = $weight;
}

array_multisort($typeSort, SORT_ASC, $scores);
var_dump($scores);

//方案2:
function uTypeSort($a, $b) {
  static $map = [
    4 => 1,
    3 => 2,
    1 => 3,
    2 => 4,
  ];

  if ($map[$a['type']] == $map[$b['type']])
  {
    return 0;
  }
  return $map[$a['type']] > $map[$b['type']] ? 1 : -1;
}

usort($scores, 'uTypeSort');
var_dump($scores);

个人感觉方案1更好一些,这里涉及字段权重的概念。

从数组中按键截取部分

比如原始数组:[‘a’ => ‘张三’, ‘b’ => ‘李四’, ‘c’ => ‘王五’];传递[‘a’, ‘c’]返回张三和王五。

$r = array_intersect_key($array, array_flip((array)$keys));

输出前导0及保留小数位数

//可以使用sprintf
echo sprintf('%03d', 1);//001
echo sprintf('%.3f', 25.78914);//25.789

命令空间use

use不一定要到具体类名,可以只use其中一部分,只是使用的时候要“接得上来”。

namespace A\B\C\D;

class E
{

}

namespace AA;

use A\B\C\D;
use A\B\C;

$e1 = new D\E; //不能少写成new E;
$e2 = new C\D\E; //也不能多写成new B\C\D\E

var_dump($e1, $e2); 
//输出:object(A\B\C\D\E)#1 (0) { } object(A\B\C\D\E)#2 (0) { }

循环输出一定范围的日期


$dateTime = new \DateTime();
$dateInterval = \DateInterval::createFromDateString('-3 day');//往前的日期可以直接new, 如new \DatePeriod('P3D')
$datePeriod = new \DatePeriod($dateTime, $dateInterval, 5);
foreach ($datePeriod as $value)
{
    echo $value->format('Y-m-d H:i:s'), '
';
}

curl post json 数据

protected function curlPostJson($url, $data)
{
    $handle = curl_init($url);
    $payload = json_encode( $data );
    curl_setopt_array($handle, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $payload,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER => 0,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
        ],
    ]);

    $result = curl_exec($handle);

    return $result;
}

正则引用前边的结果

比如要匹配以4个相同数字开头的字符串,开头只能是0000或1111或2222等。

if (!preg_match('/^(\d)\\1{3}/', $pid)) {
    return true;
}

位运算

与 &:都为1才为1,否则为0,意味着:1&任何数 = 任何数,0&任何数 = 0
或 |:都为0才为0,否则为1,意味着:0|任何数 = 任何数,1|任何数 = 1
异或 ^: 相同为0,否则为1
取反 ~: 0为1,1为0
左移 <<: 向左移动,高位丢弃,低位补0。左移一位,相当于 乘以 2
右移 >>: 向右移动,对无符号数,高位补0,对有符号数,高位补符号位。右移一位,相当于除以 2

array_merge() 与 array+

键为字符串的情况下:

$a = ['a' => 'PHP'];
$b = ['a' => 'JS'];

var_dump($a + $b); //以前边的为准,后边的抛弃,array(1) { ["a"]=> string(3) "PHP" }  
var_dump(array_merge($a, $b)); //后边的为准,覆盖前边的,array(1) { ["a"]=> string(2) "JS" } 

键为数字的情况下:

$a = ['PHP'];
$b = ['JS'];

var_dump($a + $b); //以前边的为准,后边的抛弃, array(1) { [0]=> string(3) "PHP" }
var_dump(array_merge($a, $b)); //不会覆盖,会格式化键名追加之,array(2) { [0]=> string(3) "PHP" [1]=> string(2) "JS" }

$_POST 与 php://input

  • Coentent-Type 仅在取值为 application/x-www-data-urlencoded 和 multipart/form- data 两种情况下,PHP 才会将 http 请求数据包中相应的数据填入全局变量 $_POST。
  • 只有 Coentent-Type 不为 multipart/form-data 的时候,PHP 不会将 http 请求数据包中的相应数据填入 php: //input,否则其它情况都会。填入的长度,由 Coentent-Length 指定。
  • 只有 Content-Type 为 application/x-www-data-urlencoded 时,php://input 数据才 跟 $_POST 数据相一致。
  • PHP 会将 PATH 字段的 query_path 部分,填入全局变量 $_GET。通常情况下,GET 方法提交的 http 请求,body 为空。

总结:

如果是 application/x-www-form-urlencoded 和 multipart/form-data 格式 用 $_POST。

如果不能获取的时候比如 text/xml、application/json、soap,使用 file_get_contents (‘php://input’)。

foreach 引用后二次foreach 不引用的问题

$arr = ['a', 'b', 'c'];

foreach ($arr as $key => &$value) {
    
}
echo '-----------------------------------';
foreach ($arr as $key => $value) {
    print_r($arr);
    echo "$value \n";
}

//输出结果是
(
    [0] => a
    [1] => b
    [2] => a
)
a 
Array
(
    [0] => a
    [1] => b
    [2] => b
)
b 
Array
(
    [0] => a
    [1] => b
    [2] => b
)
b 

原因分析:第一次 foreach 后,$value 与 $arr[2] 指向同一个内存地址。二次 foreach 开始,$value 要改变指针指向数组的第一个值 a , $arr[2] 与 $value 指向同一个地址,导致 $arr[2] = a,整个数组是 [a, b, a]。接着 $value 指向数组第二个值 b,$arr[2] = b,整个数组就是 [a, b, b]。最后 $value 指向数组第三个值 b,$arr[2] = b,整个数组为 [a, b, b]。

为避免此种情况,在第一次 foreach 之后,unset($value) 即可。

One comment

  1. 文章内容好像对不起标题啊,哈哈

Leave a Reply

Your email address will not be published. Required fields are marked *

*

Time limit is exhausted. Please reload CAPTCHA.