PHP技巧、可能遇到的错误

乱七八糟未分类

yield只能一维数组

杂项

十六进制( 以 0x 为前缀)或八进制(前缀为 0)。

PHP $_REQUEST 用于收集HTML表单提交的数据。
distinct机制 加mtime之后?

static关键字

当某个函数一旦完成时,它的所有的变量通常都会删除,然而,如果您希望有些局部变量不被删除,请使用static关键字

注:当您没有在函数外部定义时,该变量仍然是函数的局部变量。

<?php

function myTest()
{
static $x=0;
echo $x;
$x++;
}

myTest();
echo "<br />";
myTest();
echo "<br />";

echo $x;
?>

运行结果

0
1
PHP Notice:  Undefined variable: x in /root/soft/playground/index.php on line 16

print_r()

print_r()会将把数组的指针移到最后边。使用 reset() 可让指针回到开始处。

foreach

foreach还可可用于对象和普通数组

如果对普通数组使用,请

foreach (array_expression as $value)

const define static global globals[]区别

前二者用于定义常量 区别可参考https://www.cnblogs.com/yszr/p/10549511.html

后三者用于定义变量 区别以后补

下载

当下载的时候,网络中是不会显示接口地址的,这时候在弹出的下载框里看地址

CSV

csv本质是逗号分隔的文本文件 且只会保留第一个sheet,所以更省资源

07版以后的Excel本质上是xml,是二进制文件

版本差异

PHP7.3.14会遇到preg_match太大的问题 而7.4似乎就没有这个问题了

解决方法 php数组名后面可以加空格 数组键名可以有空格

            if (count($ret) > 2000 && count($ret) < 4000) {
                $notIn['push_action.id'] = array_slice($ret, 0, 2000);
                $notIn['push_action.id '] = array_slice($ret, 2000);
            } elseif (count($ret) >= 4000 && count($ret) < 6000) {
                $notIn['push_action.id'] = array_slice($ret, 0, 2000);
                $notIn['push_action.id '] = array_slice($ret, 2000, 2000);
                $notIn['push_action.id  '] = array_slice($ret, 4000);
            } 
            else {
                $notIn['push_action.id'] = $ret;
            }

排序 筛选 时间等各种方便的操作

看operation这个接口

数组索引

当进行某些删除操作时候如
unset($php[1]);
数组的key可能变成Array ( [0] => 0 [3] => 120 ) 此时可sort重建索引 或者和一个空数组array_merge

foreach结束后 itmm会保存最后一次的值

二维数组去重

$softs = array_unique($softs,SORT_REGULAR);

foreach 去除元素

我有一个简单的数组,其中包含所有国家/地区的名称以及每个国家/地区在我的网站上注册的用户总数.它是这样的:

Array (
[1] => Array ( [name] => Afghanistan [total] => 3 )
[2] => Array ( [name] => Albania [total] => 0 )
)
而且,我正在尝试删除拥有0个用户的数组元素(国家/地区).

我已尝试使用此代码,但它无法正常工作:

foreach($country as KaTeX parse error: Expected '}', got 'EOF' at end of input: row) { if (row[‘total’] == 0) {
unset($row);
}
}
这段代码有什么问题?

如果取消设置($row),则只删除局部变量.

而是获取密钥并删除它:

foreach ($country as $i => KaTeX parse error: Expected '}', got 'EOF' at end of input: row) { if (row[‘total’] == 0) {
unset( c o u n t r y [ country[ country[i]);
}
}

php数组的根基是关联数组

在理解一门语言之前 先确定其根基
比如php数组都是基于关联数组设计的,因而普通数组的 unique等操作,其key也是原来的。

空值的坑

array_column可能回返回
Array
(
[0] =>
[1] =>
)
这种数据 而empty判断会失效。处理办法array_filter

foreach之前记得empty判断

php一些奇淫异巧

$this->{$var}

$this->a = "hello";
$this->b = "hi";
$this->val = "howdy";

$val = "a";
echo $this->{$val}; // outputs "hello"

$val = "b";
echo $this->{$val}; // outputs "hi"

echo $this->val; // outputs "howdy"

echo $this->{"val"}; // also outputs "howdy"

相当于

$a = "hello";
$b = "hi";

$val = "a";
echo $$val; // outputs "hello"

$val = "b";
echo $$val; // outputs "hi"

还可动态调用函数

$this->{$fun_name}($plat_id, $v['id'], true)

json避免/转义

json_encode($params,JSON_UNESCAPED_SLASHES)

ip2long

如何将四个字段以点分开的IP网络址协议地址转换成整数呢?PHP里有这么一个函数ip2long

session

ini_set(‘session.gc_probability’,100); //否则不是百分之百 一般不改这个 特殊需求
ini_set(‘session.gc_divisor’,100);
设置后,会在返回值中多一个set-Cookie
微信小程序不能自动设置cookie,要先存到storge 然后在header中设置 Cookie

函数也可以引用

如 function &name(){
}

php值的传递

empty($this->a);这种形式的语法会始终判断为真 不知道是不是php的bug 而且在controller层调用正常 svc层又不正常

变量作用域

在所有函数外部定义的变量,拥有全局作用域。除了函数外,全局变量可以被脚本中的任何部分访问,但是要在一个函数中访问或修改一个全局变量,需要使用 global 关键字申明。
global $x,$y;
如果不声明,也可使用$GLOBALS['y']得形式
在 PHP 函数内部声明的变量是局部变量,仅能在函数内部访问:

函数中也可使用static作用域

当一个函数完成时,它的所有变量通常都会被删除。然而,有时候您希望某个局部变量不要被删除。

要做到这一点,请在您第一次声明变量时使用 static 关键字:

<?php
function myTest()
{
    static $x=0;
    echo $x;
    $x++;
    echo PHP_EOL;    // 换行符
}
 
myTest();
myTest();
myTest();
//然后,每次调用该函数时,该变量将会保留着函数前一次被调用时的值。
//注释:该变量仍然是函数的局部变量。

EOF

PHP 定界符 EOF 的作用就是按照原样,包括换行格式什么的,输出在其内部的东西;

$name="runoob";
$a= <<<EOF
        "abc"$name
        "123"
EOF;
// 结束需要独立一行且前后不能空格
echo $a;

三目运算符

1、传统的
(expr1) ? (expr2) : (expr3) 对 expr1 求值为 TRUE 时的值为 expr2,在 expr1 求值为 FALSE 时的值为 expr3。

2、PHP5.3新增
表达式 expr1 ?: expr3 在 expr1 求值为 TRUE 时返回 expr1,否则返回 expr3。

3、php7.3新增 null合并运算符
$site = $_GET[‘site’] ?? ‘菜鸟教程’;判断变量是否存在且值不为NULL,如果是,它就会返回自身的值,否则返回它的第二个操作数。

注:2和3得区别在于,当你想仅仅判断isset时候(不为布尔值、空数组等),二者是一致的。但是仅仅想判断isset的时候 用后面的不会出错。2的根据是true false 3的根据只有isset

命名空间的作用

1、用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
2、为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

//file1文件
namespace Foo\Bar\subnamespace; 

function foo() {}
<?php
namespace Foo\Bar;
include 'file1.php';//需要include 命名空间仅仅是为了解决命名冲突的 不是真实的目录结构

function foo() {}

/* 非限定名称 */
foo(); // 解析为函数 Foo\Bar\foo

/* 限定名称 */
subnamespace\foo(); // 解析为函数 Foo\Bar\subnamespace\foo
                                  
/* 完全限定名称 */
\Foo\Bar\foo(); // 解析为函数 Foo\Bar\foo
?>
//use用于为很长的命名空间起别名
use My\Full\Classname as Another;

// 下面的例子与 use My\Full\NSname as NSname 相同
use My\Full\NSname;

面向对象-见另一个博客 比较的

const、define、static区别

使用const使得代码简单易读,const本身就是一个语言结构,而define是一个函数。另外const在编译时要比define快很多。

1、const用于类成员变量的定义,一经定义,不可修改。Define不可以用于类成员变量的定义,可用于全局常量。

2、Const可在类中使用,define不能

3、Const不能再条件语句中定义常量

表单直接发送

<form action="welcome.php" method="post">
//welcome.php文件
欢迎<?php echo $_POST["fname"]; ?>!<br>

网络攻击

XSS又叫 CSS (Cross-Site Script) ,跨站脚本攻击。恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。

others

文件可用超级全局变量file数组得到

svc 用this->的写法可能找不到
array_search搜寻第一个的键名为0 会判断为false 一般还是用in_array把
如[{name: “搜狗浏览器”, soft_id: 10185},{ soft_id: 10185,name: “搜狗浏览器”}] array_unique(array,SORT_REGULAR)会失败

一些用法

$this->redisObj->sAdd('proSafeSvcUpdateActivityPhonesFailed',...$this->phones);
public function broadcast($message, array $phones)

list

list() 函数用于在一次操作中给一组变量赋值。可实现类似golang,python 多个返回值的情况

$my_array = array("Dog","Cat","Horse");

list($a, , $c) = $my_array;
echo "我在这里只用了 $a$c 变量。";

gzip

gzdecode、gzdecode可以对数据进行压缩,节省空间。不光是文件,字符串也可以直接用!
场景:如存关联数组到redis

和zip区别 linux的gz后缀就是用gzip压缩的

GZIP与zip区别主要是适应系统不同,还有就是压缩率不一样;普遍使用的是zip压缩,Windows系统下就用zipgzip为高压,可以把文件压缩得更小,便于放网盘或者网上供人下载;gzip是Linux下面用的格式,一般在Linux下解压,如果用Windows下的程序解压有可能丢失其中某些文件或属性。

函数可添加类型

在这里插入图片描述

指定环境变量测试还是正式的方法

以下方法任选其一
一、但是好像不成功 算了 还是nginx吧
1.打开etc/profile文件:vim /etc/profile

新增一个环境变量export PHP_ENV=“DEV”,正式服务器设置为=“PRODUCTION”

这样通过系统环境变量来做一些不同的操作,或者存在不同的数据库账号密码

设置完后重新加载:source /etc/profile

2.修改PHP的php-fpm.conf文件,设置PHP环境变量

底部增加:env[PHP_ENV]=$PHP_ENV

重启PHP服务,service php-fpm restart
然后代码中用$_ENV[‘PHP_ENV’]获取即可

二、 nginx设置
location ~ .php($|/) {
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME d o c u m e n t r o o t document_root documentrootfastcgi_script_name;
fastcgi_param PHP_ENV ‘DEV’; # PRODUCT DEV RETURN
}
设置完要重启nginx。
然后如果要修改nginx配置 可以先还原配置完 然后最后再加这句就行

然后代码用$_SERVER[‘PHP_ENV’]获取即可

json_decode 对路径无法生效

四斜杠

$j = '{"class":"app\\\\api"}';
dump(json_decode($j, true));//["class" => "app\api"]

三斜杠

$j = '{"class":"app\\\api"}';
dump(json_decode($j, true));//["class" => "app\api"]

双斜杠

$j = '{"class":"app\\api"}';
dump(json_decode($j, true))//null;

单斜杠

$j = '{"class":"app\api"}';
dump(json_decode($j, true));//null

解决方法
1、

// 把json中的\替换为/
$str = str_replace("\\", "/", $json);
//注意:第一个指要两个\\,如果一个的话会被转义掉!!

2、将有反下划线的单独拿出来,用urlencode函数处理后再放进去

定界符

为什么要使用定界符

比如你要打印代码 或者 一些gzip的数据 里面有单引号 然后就很麻烦 直接用引号包裹会报错

解决方案

heredoc和nowdoc
区别是后者不会解析$变量,使用差别是多了个引号

$gzip = <<<'EOF'
//EOF可为任意字符,然后下面的eof要顶格写  php7.3后对此做了优化 避免破坏格式
EOF

搜索技巧

你直接搜怎么单引号 加密数据啥的 很难搜到 可以换种思路
搜索 php定界方式

call

在这里插入图片描述

反斜杠类名

在new PHPExcel()时总报错,但在前面加个反斜杠就可以了,new \PHPExcel() ,这个斜杠表示,如果当前类中没有,就去全局搜索这个类

构造函数

新版的php 构造函数不再推荐与类名相同了,如果继续使用 会抛出异常

注解

比如throws 告诉使用的类要catch异常
在这里插入图片描述
@internal : 被此标签标记的内部类/方法,作用范围只能限于当前文件,外部文件不可调用.

@deprecated可以填写一个版本号,版本号的规则同@version
如果被标记的方法只是因为被其他新方法代替而被废弃,可以结合@see来表示被代替的方法

当定义了命名空间后,要用\Exception

不能exception 因为定义了命名空间,就要用类的全称了 不然会报错

方法1 use \Exception;
方法2 throw new \Exception;

var_dump与print_r

print_r输出的时候 字符型的"0"可能也输出0,造成json_encode 类型不对 而且不好排查。所以用var_dump.还有引用 var_dump

json_encode对数字的坑

json_encode($unique_soft, JSON_NUMERIC_CHECK);
因为查询mysql返回的数据,全部都是加了双引号的(都当成字符串)。我希望的是数字不要加双引号,而字符串就加上双引号。所以在进行json_encode() 时,加了参数 JSON_NUMERIC_CHECK(参考)
但是问题来了:加了这个参数后,它会把 decimal 类型的 价格 price 比如:20.00 ,后面的小数点去掉了,还有一个就是,比如说它也会把比如身份证号转换成了科学计数法了。

然后json_encode对浮点数,比如4.0会错误

//直接var_dump
array(9) {
  ["m2"]=>
  array(2) {
    ["num"]=>
    int(24)
    ["compare"]=>
    float(20)
  }
  ["base_board"]=>
  array(2) {
    ["num"]=>
    int(23)
    ["compare"]=>
    float(0)
  }
  ["cpu_name"]=>
  array(2) {
    ["num"]=>
    int(23)
    ["compare"]=>
    float(-4.17)
  }
  ["phys_memory"]=>
  array(2) {
    ["num"]=>
    int(46)
    ["compare"]=>
    float(-8)
  }
  ["disk_list"]=>
  array(2) {
    ["num"]=>
    int(26)
    ["compare"]=>
    float(0)
  }
  ["video_controller"]=>
  array(2) {
    ["num"]=>
    int(23)
    ["compare"]=>
    float(0)
  }
  ["physical_adapter"]=>
  array(2) {
    ["num"]=>
    int(26)
    ["compare"]=>
    float(0)
  }
  ["sound_device"]=>
  array(2) {
    ["num"]=>
    int(23)
    ["compare"]=>
    float(0)
  }
  ["desktop_monitor"]=>
  array(2) {
    ["num"]=>
    int(23)
    ["compare"]=>
    float(0)
  }
}
//json_encode后
{"m2":{"num":24,"compare":19.999999999999996},
"base_board":{"num":23,"compare":0},
"cpu_name":{"num":23,"compare":-4.1699999999999964},
"phys_memory":{"num":46,"compare":-7.9999999999999964},
"disk_list":{"num":26,"compare":0},
"video_controller":{"num":23,"compare":0},
"physical_adapter":{"num":26,"compare":0},
"sound_device":{"num":23,"compare":0},
"desktop_monitor":{"num":23,"compare":0}}

foreach 引用

比如foreach ($category_map as $k=>&$v)
如果引用 unset(k[xx])后面使用V的时候 是最新的v 而如果不是引用 那么就是原来的v(拷贝了一份)

数组元素为null 但是isset判断为false

定义一个PHP 数组 $arr = array('jjbao'=>null,'cnima'=>null); isset($arr['jjbao']) 居然返回的false
把 null 改为 0 就没有问题了
找了半个小时 蛋痛啊
解决方法: isset() 对于数组中为 NULL 的值不会返回 TRUE,而 array_key_exists() 会。

unset内存反而大?

在这里插入图片描述
备注 unset也生效了 用unset之前 是500k 用了300k 但是注释那种 只要200k

1、require和include以及once的区别

require() 语句的性能与 include() 相类似,都是包括并运行指定文件。不同之处在于:
1、对 include() 语句来说,在执行文件时每次都要进行读取和评估;而对于 require() 来说,文件只处理一次(实际上,文件内容替换 require() 语句,使它变成 PHP 脚本文件的一部分。)。这就意味着如果可能执行多次的代码,则使用 require() 效率比较高。另外一方面,如果每次执行代码时是读取不同的文件,或者有通过一组文件迭代的循环,就使用 include() 语句。
2、require一般放在最前面(类名前),而include可以在需要时,比如if循环时再引入,降低消耗。
3、PHP 系统在加载PHP程序时有一个伪编译过程,可使程序运行速度加快。但 incluce 的文档仍为解释执行。include 的文件中出错了,主程序继续往下执行,require 的文件出错了,主程序也停了,所以包含的文件出错对系统影响不大的话(如界面文件)就用 include,否则用 require。
4、include_once() 和 require_once() 语句也是在脚本执行期间包括运行指定文件。此行为和 include() 语句及 require() 类似,使用方法也一样。唯一区别是如果该文件中的代码已经被包括了,则不会再次包括。这两个语句应该用于在脚本执行期间,同一个文件有可能被包括超过一次的情况下,确保它只被包括一次,以避免函数重定义以及变量重新赋值等问题。
5、在这里插入图片描述

总之:
1、当很多函数都使用,或者经常要被执行的时候,当被包含的文件出错不让他继续运行的时候,用require。
2、当出错不影响、而且不经常被使用到时,用include。
3、Require_once 虽然官方说php5.3之后的版本 性能和require差不多了 但是···实际测试好像还是差了很多 如php5.3.3 所以 能用require就不要require_once

2、empty()和isset()

单从字面意思理解,empty是判断一个变量是否为“空”,而isset 则是判断一个变量是否已经设置。
但是这里有一点绝对要注意起来:当一个变量值为0,empty 认为这个变量同等于空,返回的是true!

3、== 和 ===

在这里插入图片描述
1==2 判断是false (之所以写这个是为了防止二者自动转换为true 然后判定相等)
‘1’==1 是true
Php 10和5 如果是字符串类型 那么可能会错误的结果 判断出5>10???是么

$a = (bool)('1');
dump($a);  //结果为true

4、浮点数(特别是涉及到钱的!)的运算必须用高精度运算函数

如 1/8 ==0.125可能判断错误 要用bcdiv
在这里插入图片描述

5、注意数据库加锁 lock(true)

为了防止读写冲突问题!!
lock(true)的实际就是在查询(select)语句最后加上 for update 指定使用悲观锁
详细可见https://blog.csdn.net/S_ZaiJiangHu/article/details/116720884

序列化和反序列化的作用

你想如果想把一个数组或者是对象存储到文件或数据库中,怎么办。不能像字符串那样的存储吧。所以在存储数组或对象之前先serialize,在取回内容时再unserialize…
一句话:serialize的作用是 产生一个可存储的值的表示.unserialize的作用是 对单一的已序列化的变量进行操作,
序列化可以将PHP中 对象、类、数组、变量、匿名函数等,转化为字符串,这样用户就方便储存和传输,对服务器或web中减轻一定的压力。

错误篇

字符串和数字判断相等返回true的问题

更多详细的 看https://www.cnblogs.com/beenupper/p/12635779.html

if('a'==0){
    echo "字符串a尽然等于0";//输出了
   
}

php虽然是弱类型的语言,但它是有数据类型的。大概分为三种类型:字符串、数字、布尔型。上面的问题出现是由于字符串转换为了数字类型。
正常情况下不同类型的值是不能比较的,php 为了比较进行了数据类型转换。把不同类型的值转换为相同类型后再比较。
规则如下:

宽松比较(==)类型转换规则
(1)数字和字符串比较,将字符串转为数字,然后进行比较
(2)数字和布尔型比较,将数字转为布尔型,然后进行比较
(3)字符串和布尔型比较,将字符串转为布尔型,然后进行比较。
宽松比较的落脚点只有两个,一个是布尔型,一个是数字。只有当数字和字符串比较的时候,会把字符串转为数字

三、字符串转数字

  1. 字符串的开始部分决定了它的数字值。
  2. 如果该字符串以合法的数字值开始,则使用该数值。否则其值为 0(零)。
  3. 合法数字值可以是正负号,后面跟着一个或多个数字(可能有小数点),再跟着可选的指数部分。指数部分由 ‘e’ 或 ‘E’ 后面跟着一个或多个数字构成。

四、剖析 ‘a’==0
‘a’ 这是一个字符串类型。0 是数字类型。使用 == 宽松比较,此时发生类型转换。字符串和数字比较,是将字符串转换为数字然后进行比较的。

运算步骤一:根据字符串转数字的规则,字符串的开始部分决定了它的数字值。该字符串的开头不是数字,则它的数字值为0。
所以’a’ 转换为数字类型时,它其实为0了。不仅’a’等于0,‘abc’,‘aabbcc’ 它们转为数字也是0哦。

运算步骤二:最后比较0是否等于0,结果为真。

字符串的布尔值和布尔值的相等问题

需要注意 即使强制类型转换也 比如(bool)‘false’==false 输出的是false
还是用0 1把

json变对象

在一次工作中跟前端对接API中出现的问题,前端说接口返回值跟接口文档不一致。API文档写的是返回数组,但是实际返回的是一个JSON对象。最后补充这个知识盲点:PHP的数组在转JSON的时候,如果索引连续,则转成数组。如果索引不连续,则会转成对象!

PHP数组转json后,元素变为object的坑🙈
今天项目遇到一个bug,组件排序是用数组做的排序,所以遇到了排序后的数组转为json字符串后,前端解析后变为了对象,导致了出现bug,自己研究了一下发现了一个坑。

首先测试key有序且下标从0开始的一个索引数组,代码如下:

<?php

$a[0] = '1a';
$a[1] = '2a';
$a[2] = '3a';
$b['a'] = $a;

$jStr = json_encode($b);
echo $jStr;

//结果是这样的
{“a”:[“1a”,“2a”,“3a”]}

可以看到这时,josn里的元素是数组,符合预期。

接下来试一下下标0开始,但是key无序的索引数组

<?php

$a[0] = '1a';
$a[2] = '2a';
$a[1] = '3a';
$b['a'] = $a;

$jStr = json_encode($b);
echo $jStr;

//结果是这样的
{“a”:{“0”:“1a”,“2”:“2a”,“1”:“3a”}}

这个时候已经可以看到,其中的a数组已经被json转为了对象

这个时候突发奇想,试一下key有序但是下标不是从0开始的索引数组:

<?php

$a[1] = '1a';
$a[2] = '2a';
$a[3] = '3a';
$b['a'] = $a;

$jStr = json_encode($b);
echo $jStr;

//结果如下:
{“a”:{“1”:“1a”,“2”:“2a”,“3”:“3a”}}

可以看到即使索引数组下标连续,但是下标key不是从0开始的索引数组,依然是会被转换为对象。

结论
如果也遇到了类似的需求,需要某种排序要用到这一步,一定要注意一下这里,要转换为从0开始,下标连续不间断的新数组,json_encode后才会是一个数组的形式。
我后来是转换为从0开始下标的新数组,并且使用ksort之后,json才成功转换为了想要的数组格式。

解决方案
加一个 : a r r a y = a r r a y v a l u e s ( array = array_values( array=arrayvalues(array);

技巧与使用篇

microtime()

字符串的两部分的单位都是(第一部分并不是微秒为单位),第一部分是精确到微秒的部分
比如0.25139300 ,有效数字是6位,正好符合1秒=1,000毫秒=1,000,000微秒
使用echo microtime(true);直接获得浮点值。

内外网判断

工作需要判断ip是否是内网ip,本来想着使用正则自己写一个呢,后来发现php自带的有现成的函数filter_var()
除了ip验证外还有许多都可以验证,如url、email等等

验证ip是否是内网ip,如果是的话返回false,否则返回ip;
直接的话 浏览器看不到 要 var_dump

代码如下:

filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)

内网ip

A类:10.0.0.0-10.255.255.255

B类:172.16.0.0-172.31.255.255

C类:192.168.0.0-192.168.255.255

本机地址:127.0.0.1

PHP FILTER_VALIDATE_IP 过滤器

定义和用法
FILTER_VALIDATE_IP 过滤器把值作为 IP 进行验证。
Name: “validate_ip”
ID-number: 275
可能的标志:
FILTER_FLAG_IPV4 - 要求值是合法的 IPv4 IP(比如 255.255.255.255)
FILTER_FLAG_IPV6 - 要求值是合法的 IPv6 IP(比如 2001:0db8:85a3:08d3:1319:8a2e:0370:7334)
FILTER_FLAG_NO_PRIV_RANGE - 要求值是 RFC 指定的私域 IP (比如 192.168.0.1)
FILTER_FLAG_NO_RES_RANGE - 要求值不在保留的 IP 范围内。该标志接受 IPV4 和 IPV6 值。

二维数组去重

这个函数默认只能一维,会报错 arr to string的错误 所以

array_unique中加:SORT_REGULAR参数

抑制错误@和TODO

curl和file_get_contents的区别

1.fopen /file_get_contents 每次请求都会重新做DNS查询,并不对 DNS信息进行缓存。但是CURL会自动对DNS信息进行缓存。对同一域名下的网页或者图片的请求只需要一次DNS查询。这大大减少了DNS查询的次数。所以CURL的性能比fopen /file_get_contents 好很多。

2.fopen /file_get_contents 在请求HTTP时,使用的是http_fopen_wrapper,不会keeplive。而curl却可以。这样在多次请求多个链接时,curl效率会好一些。

3.fopen / file_get_contents 函数会受到php.ini文件中allow_url_open选项配置的影响。如果该配置关闭了,则该函数也就失效了。而curl不受该配置的影响。

4.curl 可以模拟多种请求,例如:POST数据,表单提交等,用户可以按照自己的需求来定制请求。而fopen / file_get_contents只能使用get方式获取数据。
file_get_contents 获取远程文件时会把结果都存在一个字符串中 fiels函数则会储存成数组形式

由此可知curl在性能、速度、稳定性上都要优于file_get_contents,所以建议以后使用curl库进行网络请求。

<?php
  $curl = curl_init();//初始化一个cURL对象
  $url = "http://cart.jd.com/cart/cart.html?backurl=http://item.jd.com/176166.html&rid=0.9533184533      938766";
  $header = array();
  $header[] = 'User-Agent: 5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-us)';
  $header[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
  $header[]= 'Accept-Encoding: gzip,deflate';
  $header[]= '//可以根据需要增加header内容';
  curl_setopt($culr,CURLOPT_URL, $url);//设置你需要抓去的URL地址
  curl_setopt($curl,CURLOPT_HEADER,$header );//设置header
  curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);//将结果返回输出到字符串
  $str = curl_exec($curl);运行cURL,请求网页
  curl_close($curl);//关闭url请求
  return $str;//返回或者显示结果

php性能低的原因

作者:旗木五五开
链接:https://www.zhihu.com/question/422661037/answer/1602633070
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

php不管是哪个框架真的要到高性能的场景,都是撑不住的。原因?首先,没有连接池这个玩意,立马就拖垮了数据库的连接数,too many connection见过没?没见过的话等你见过了再来喷框架垃圾。其次,每次都要从入口文件加载一次全部代码,当然你可以用opcache减少编译。框架代码按照道理你应该只加载一次就够了,逻辑上应该从路由开始执行才对,这部分也是性能损失的原因。第三,php本身的io机制不是epoll的,理论上你php-fpm开了多少个进程,就能同时执行多少个请求,网上一堆教程教你要么保持和cpu核数一样,要么内存50m一个进程之类的方式。基于这个问题,php方面的性能优化只能靠叠服务器,不然你会经常碰到504 gateway timeout的问题。所以php的优化途径都是这样的:首先你随便用一个了框架。然后某天突然发现504 gateway timeout了,排除了你sql写的实在是烂的前提,你就会发现是php-fpm的进程不够用导致的,修改php-fpm.conf配置或者加机器。加完机器大概率会出现too many connection,原因是mysql的连接数不够用了,然后你就会想要么mysql主从分离,要么加缓存上redis,先查redis再查mysql。然后如果量继续加大,你就只能继续增加服务器,因为php-fpm进程数=1秒处理数导致的。接着你会发现服务器成本越来越贵,就差不多要换swoole或者go获取java了。当你换了go或者java或者swoole后,你就会发出服务器降了多少台,成本降了多少的感叹。所以选一个自己称手的框架上就行了,框架无非就是熟练它的各种类库罢了,那个熟练用哪个,非得有个高下立判就无趣了,真到性能瓶颈你都得换。说点Laravel的题外话,Laravel真的是除了性能不行,哪哪都行的框架。掌握好他的框架思想、设计模式、队列、调度等原理,真的大有裨益。

1、too many 的问题解决方案很多,如果使用的是云数据库,一般都有短链接优化功能,开启即可解决问题。如果是本地自建数据库,加一个数据库代理即可,但根据实践来看,往往引起数据库连接超量并不是因为没有连接池引起的,而是业务代码里出现了大量的循环创建mysql连接导致的,开启连接池只是避免了前端报错,避免服务crash,但问题本质还是存在

2、php-fpm并不是你们理解的那样,一个进程只能处理一个请求,fpm本质也是利用了linux的epool机制,可以同时轮询处理多个请求,但是要记住,业务代码里不能有阻塞代码,阻塞代码一定要放到后台进行,否则并发能力会大受影响,就真的变成一个进程一次只能处理一个请求了

3、用laravel这样的框架,正确的写代码,两台4G8核的服务器,可以支撑到日请求数300万,峰值每秒处理2000请求,一直到项目黄了也没有触摸到性能瓶颈,这一点是自己创业的经历,不多解释。

4、php十分适合低成本创业,php当前最大的问题是被语言创造者们抛弃了,得不到黑科技的注入了。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值