了解php

为什么PHP程序员务必了解与熟练 Composer?

对于PHP程序员来说对Composer并不陌生,但是只有在php5.3以上才能使用Composer包依赖管理工具。首先我们要知道Composer 不是一个包管理器,它仅仅是一个依赖管理工具,或许很多人之前都是使用PEAR包管理器,但是目前Composer已经取代PEAR包管理器,所以请PHP程序员务必了解与熟练 Composer。

使用过linux系统的开发人员都知道使用几条简单命令就可以快速安装Compose(curl -sS https://getcomposer.org/installer | phpmv composer.phar /usr/local/bin/composer),下载之后我们会发现composer.json,这是你项目定义的关键文件,使用Compose之后,在linux开发php扩展就得心应手了,一切都会在Composer帮助下完成你开发需要的工具。

PHP使用Composer最主要作用:

通过使用composer包依赖管理工具,我们可以使用大量的第三方库,而无需自己造轮子。

目前流行的框架都是需要composer在线安装,比如laravel、yii框架。

linux系统开发php目前必备管理工具。

流行网站都支持composer工具管理,比如github。

展开
收起

PHP7.3即将到来,快来了解一下新特性吧

本文为社区网友进行翻译,可能会有很多不足之处,欢迎讨论交流PHP 目前依旧是其它脚本语言强劲的竞争对手,这主要归功于其核心维护团队的快速更新。

自从 PHP 7.0 发布以来,社区见证了许多新特性的诞生,极大地改进了开发者在项目中应用 PHP 的方式。提高 PHP 应用的性能和安全性,是这些改进的主要目的。

PHP 最近实现了又一个里程碑 —— 发布 PHP 7.3。新版本带来了一些急需的更新。

在本文中,我将论述新推出的 PHP 7.3 特性 和更新。好消息是,你可以在你的测试服务器上自行安装新版本、查看新功能。但老生常谈,切勿在生产服务器上使用 RC 版本更新,可能会破坏你已经上线的应用。

以下是7.3版中引入的一些更新,与以前的版本相比,它们大大提高了 PHP 7.3 的性能 。

灵活的 Heredoc 和 Nowdoc 语法函数调用时允许尾随逗号JSON_THROW_ON_ERRORPCRE2 迁移list() 分配参考is_countable 函数array_key_first(), array_key_last()Argon2 密码哈希增强功能弃用和删除 image2wbmp()弃用和删除不区分大小写的常量相同站点 CookieFPM 更新改进 Windows 下的文件删除让我们逐一讨论上述的每一个更新。

灵活的 Heredoc 和 Nowdoc 语法

Heredoc 和 Nowdoc 语法能够在使用多行长字符串时起到很大帮助。它要求结束标识符应当为出现在新行的首个字符串。

// 除了这样:$query =<<<SQLSELECT *FROM `table`WHERE `column`=true;SQL;// 这样也可以:$query =<<<SQL SELECT * FROM `table` WHERE `column`=true; SQL;总的来说,此更新提出了两项改进,如下:

闭合标识符前支持缩进闭合标识符后不再强制换行在上面的例子里,可以很容易地看出这些改动。

函数调用中允许尾部逗号

在参数、元素、变量列表结尾,追加尾部逗号。有时我们在数组内以及函数调用(尤其是可变参函数)时需要传递大量元素,若是漏掉一个逗号,便会报错。鉴于如上情况,尾部逗号便显得十分有用。这个特性已经允许在数组内使用,并且从 PHP 7.2 开始,分组命名空间(Grouped Namespaces)语法也开始支持尾部逗号。

useFoo\Bar\{ Foo,Bar,};$foo =['foo','bar',];当新值需要被追加在此处时,尾部逗号便显得十分实用。在可变参函数例如 unset() 内,更是如此。

unset( $foo, $bar, $baz,);同时,当你使用 compact() 函数给模版引擎传递一批变量时,也是个能用到的例子。

echo $twig->render('index.html', compact('title','body','comments',));在某些需要构造连续或分组数据情况下,经常要使用 array_merge() 函数合并数组。也可以利用尾部逗号:

$newArray = array_merge( $arrayOne, $arrayTwo,['foo','bar'],);同样,你也可以在调用任意方法、函数以及闭包时使用此特性。

classFoo{publicfunction __construct(...$args){//}publicfunction bar(...$args){//}publicfunction __invoke(...$args){//}}$foo =newFoo('constructor','bar',);$foo->bar('method','bar',);$foo('invoke','bar',);JSON_THROW_ON_ERROR

解析 JSON 响应数据,有 json_encode() 以及 json_decode() 两个函数可供使用。不幸的是,它们都没有恰当的错误抛出表现。json_encode 失败时仅会返回 false;json_decode 失败时则会返回 null,而 null 可作为合法的 JSON 数值。唯一获取错误的方法是,调用 json_last_error() 或 json_last_error_msg(),它们将分别返回机器可读和人类可读的全局错误状态。

该 RFC 提出的解决方案是,为 JSON 函数新增 JSON_THROW_ON_ERROR 常量用于忽略全局错误状态。当错误发生时,JSON 函数将会抛出 JsonException 异常,异常消息(message)为 json_last_error() 的返回值,异常代码(code)为 json_last_error_msg() 的返回值。如下是调用例子:

json_encode($data, JSON_THROW_ON_ERROR);json_decode("invalid json",null,512, JSON_THROW_ON_ERROR);// 抛出 JsonException 异常升级 PCRE2

PHP 使用 PCRE 作为正则表达式引擎。但从 PHP 7.3 开始,PCRE2 将作为新的正则引擎大显身手。所以,你需要将现有的正则表达式迁移到符合 PCRE2 的规则。这些规则比以前更具侵入性。请看以下实例:

preg_match('/[\w-.]+/','');这个表达式在新版 PHP 内将会匹配失败且不会触发警告。因为 PCRE2 现严格要求,若需匹配连字符(-)而非用于表示范围,则必须移动到末尾或将其转义。

更新到 PCRE2 10.x 后,支持了以下以及更多特性:

相对后向引用 \g{+2}(等效于已存在的 \g{-2})PCRE2 版本检查 (?(VERSION>=x)...)(*NOTEMPTY) 和 (*NOTEMPTY_ATSTART) 告知引擎勿返回空匹配(*NO_JIT) 禁用 JIT 优化(*LIMIT_HEAP=d) 限制堆大小为 d KB(*LIMIT_DEPTH=d) 设置回溯深度限制为 d(*LIMIT_MATCH=d) 设置匹配数量限制为 d译者注:国内正则术语参差不一,「后向引用」—— Back References,又称「反向引用」、「回溯引用」等,此处参考 PHP 官方手册的中文译本。

list() 赋值引用

PHP 中的 list() 现在可以赋值给引用,在当前版本中 list() 中赋值不能使用引用,在 PHP 7.3 中将允许使用引用,新改进的语法如下:

$array =[1,2];list($a,&$b)= $array;相当于

$array =[1,2];$a = $array[0];$b =& $array[1];在 PHP 7.3 的变更中,我们还可以与 foreach() 方法一起嵌套使用

$array =[[1,2],[3,4]];foreach($array as list(&$a, $b)){ $a =7;}var_dump($array);is_countable 函数

在 PHP 7.2 中,用 count() 获取对象和数组的数量。如果对象不可数,PHP 会抛出警告 。所以需要检查对象或者数组是否可数。 PHP 7.3 提供新的函数 is_countable() 来解决这个问题。

该 RFC 提供新的函数 is_countable(),对数组类型或者实现了 Countable 接口的实例的变量返回 true 。

之前:

if(is_array($foo)|| $foo instanceofCountable){// $foo 是可数的}之后:

if(is_countable($foo)){// $foo 是可数的}array_key_first(), array_key_last()

当前版本的 PHP 允许使用 reset() ,end() 和 key() 等方法,通过改变数组的内部指针来获取数组首尾的键和值。现在,为了避免这种内部干扰,PHP 7.3 推出了新的函数来解决这个问题:

$key = array_key_first($array); 获取数组第一个元素的键名$key = array_key_last($array); 获取数组最后一个元素的键名让我们看一个例子:

// 关联数组的用法$array =['a'=>1,'b'=>2,'c'=>3];$firstKey = array_key_first($array);$lastKey = array_key_last($array);assert($firstKey ==='a');assert($lastKey ==='c');// 索引数组的用法$array =[1=>'a',2=>'b',3=>'c'];$firstKey = array_key_first($array);$lastKey = array_key_last($array);assert($firstKey ===1);assert($lastKey ===3);译者注:array_value_first() 和 array_value_last() 并没有通过 RFC 表决;因此 PHP 7.3 内仅提供了 array_key_first() 以及 array_key_last() 函数。参考链接:https://wiki.php.net/rfc/array_key_first_last

Argon2 和 Hash 密码加密性能增强

在PHP的早期版本中,我们增加了Argon2和哈希密码加密算法,这是一种使用哈希加密算法来保护密码的现代算法。它有三种不同的类型,Argon2i,Argon2d和Argon 2id。 我们针对Argon2i密码散列和基于密码的密钥生成进行了优化。 Argon2d性能更快,并使用依赖于内存的数据访问。 Argon2i使用与内存无关的数据访问。 Argon2id是Argon2i和Argon2d的混合体,使用依赖于数据和与数据独立的存储器访问的组合。

password_hash():

Argon2id现在是在paswword_ *函数中使用的推荐的Argon2变量。

具有自定义成员方法的名称的Argon2id与PASSWORD_ARGON2I的使用方法相同password_hash('password',PASSWORD_ARGON2ID,['memory_cost'=>1<<17,'time_cost'=>4,'threads'=>2]);password_verify();

除了Argon2i之外,password_verify()函数也适用于Argon2id。

password_needs_rehash();

此函数也将接受Argon2id哈希值,如果任何变量成员发生变化,则返回true。

$hash = password_hash('password', PASSWORD_ARGON2ID);password_needs_rehash($hash, PASSWORD_ARGON2ID);// 返回假password_needs_rehash($hash, PASSWORD_ARGON2ID,['memory_cost'=>1<<17]);// 返回真废弃并移除 image2wbmp()

该函数能够将图像输出为 WBMP 格式。另一个名为 imagewbmp() 的函数也同样具备单色转换的作用。因此,出于重复原因,image2wbmp() 现已被废弃,你可使用 imagewbmp() 代替它。此函数被弃用后,再次调用它将会触发已弃用警告。待后续此函数被移除后,再次调用它将会触发致命错误。

废弃并移除大小写不敏感的常量

使用先前版本的 PHP,你可以同时使用大小写敏感和大小写不敏感的常量。但大小写不敏感的常量会在使用中造成一点麻烦。所以,为了解决这个问题,PHP 7.3 废弃了大小写不敏感的常量。

原先的情况是:

类常量始终为「大小写敏感」。使用 const 关键字定义的全局常量始终为「大小写敏感」。注意此处仅仅是常量自身的名称,不包含命名空间名的部分,PHP 的命名空间始终为「大小写不敏感」。使用 define() 函数定义的常量默认为「大小写敏感」。使用 define() 函数并将第三个参数设为 true 定义的常量为「大小写不敏感」。如今 PHP 7.3 提议废弃并移除以下用法:

In PHP 7.3: 废弃使用 true 作为 define() 的第三个参数。In PHP 7.3: 废弃使用与定义时的大小写不一致的名称,访问大小写不敏感的常量。true、false 以及 null 除外。同站点 Cookie

PHP 7.3 在建议在使用 cookies 时,增加同站点标志。这个 RFC 会影响4个系统函数。

setcookiesetrawcookiesession_set_cookie_paramssession_get_cookie_params这个影响会在两种情况下起作用。其中一种方式会添加函数的新参数,另一种方式允许以数组形式的选项代替其他单独选项。

bool setcookie(string $name [,string $value =""[,int $expire =0[,string $path =""[,string $domain =""[,bool $secure =false[,bool $httponly =false]]]]]])bool setcookie (string $name [,string $value =""[,int $expire =0[, array $options ]]])// 两种方式均可.FPM 更新

FastCGI 进程管理器也进行了更新,现在提供了新的方式来记录 FPM 日志。

log_limit: 设置允许的日志长度,可以超过 1024 字符。

log_buffering: 允许不需要额外缓冲去操作日志。

decorate _workers_output: 当启用了 catch_workers_output 时,系统会去禁用渲染输出。

改进 Windows 下的文件删除

如官方文档所述:

默认情况下,文件描述符以共享读、写、删除的方式去操作。 这很有效的去映射 POSIX 并允许去删除正在使用中的文件。但这并不是100%都是一样的,不同的平台可能仍存在一些差异。删除操作之后,文件目录仍存在直到所有的文件操作被关闭。

结束语

之前我们已经讲解了最新版本的 PHP7.3 的特点,包含了许多新增跟弃用的功能。这些功能都可以在 php.net 网站上找到,并且已经合并到主分支上了。你现在就可以使用这些新功能部署在自己的服务器上,你也可以打开官方RFC页面查阅每一个详细版本。如果你对着新版 PHP7.3 有任何问题,你可以在评论下写下自己的想法。如果你喜欢这篇文章,并且觉得它很有帮助,你可以在 twitter 上关注我,来获得更多的信息!

原文地址:https://www.cloudways.com/blog/whats-new…译文地址:https://laravel-china.org/topics/21549

展开
收起

php编程小白必须要了解几种函数参数的传递方式

之前几篇文章详细介绍了php函数,对php函数不了解的可以看看我前几天发的文章,php函数由函数名、函数参数、函数体、return返回值组成,在函数调用过程中,被调用函数和执行程序通过函数参数进行数据传输,这篇文章为大家介绍一下函数中参数是通过哪些方式传递的?

参数传递其实就是在执行函数前导入某些值,供函数处理执行。php函数中传递参数的方式主要有按值传递参数和按引用传递参数,另外php函数还支持默认参数列表的传递方式。

按值传递参数

参数列表可以传递数据到函数,逗号分隔表达式,再php中默认是按值传递参数的,函数成为子程序,调用函数的程序成为父程序。父程序直接传递指定的值或是变量给函数使用,传递的值存于不同的内存区块,子程序对导入的数据做任何修改都不会对父程序有任何直接影响。

如上图所示,$a是函数test的形参,$b是函数test的实参,调用函数test($b)不会影响到$b的值,$b初始值仍为200.

按引用传递参数

默认情况下函数内部改变参数的值,并不会改变函数外部的值,如果我们想允许函数修改它的参数值从而改变函数外部的值,这时候必须通过引用传递参数。使用引用传递参数后,参数值的改变会连带对父程序造成影响。使用按引用传递参数需要在参数前加上符号“&”即可。如图所示:

调用test函数时,因为使用的是按引用传递参数原因,$b的值是100而不是200。

函数的默认参数

定义函数时声明了参数,在调用函数没有参数,就会出现警告。在php中,支持函数的默认方式调用,即为参数指定一个默认值。再调用函数时没有指定参数的值,在函数中会使用参数的默认值。默认值必须是常量表达式不是变量,类成员或者函数调用,php还允许使用数组和特殊类型null作为默认参数。如图所示:

运行结果

person();使用了函数的默认参数,person(“张三”)覆盖了$name的值,使用了函数默认参数$age的值,而person(“张三”,30)没有使用函数的默认参数值。

以上是关于php函数参数值传递的内容,如果大家有更好的想法可以相互讨论下!

展开
收起

电脑通带你了解什么是PHP反序列化安全

PHP是世界上最好的语言

曾几何时,这句话也是让php程序员感到一股暖流,但好景不长,随着安全技术的发展及安全意识的提升,越来越多安全漏洞相继爆发出来,比如SQL注入、XSS等高危漏洞可以直接威胁到企业的业务系统,影响极大。

PHP语法简洁且对编程初学者很友好。同样是一个web开发项目,假如用Java语言写可能需要3个多月,而用PHP写只用一个月就够了。这也就当时人们普遍使用PHP作为网站编程的热点语言语言

而令人惊讶的是,这些漏洞出现的编程语言大多是PHP。从而就造成人们对PHP的误解,以为这个语言不安全。其实这样理解是有失偏颇的,PHP语言本身是很安全的,只是使用这个语言去写程序的人在编程的时候忽略了安全性才导致出现漏洞的。所以,说PHP语言不安全是不正确的。

今天以PHP反序列化漏洞为例,简单理解一下PHP编程常见的安全问题。

php反序列化漏洞又称对象注入。那什么是对象,想和大家普及一下编程的概念:

类:人

变量:姓名

方法:吃饭睡觉打豆豆

对象:就是对类进行实例化,如小明在睡觉

PHP反序列化原理

1.序列化和反序列化

序列化是将变量转换为可保存或传输的字符串的过程。

反序列化是在适当的时候把这个字符串再转化成原来的变量使用。

2.php序列化和反序列化函数

serialilze:可将变量转换为字符串并且在转换中可以保存当前变量的值。

unserialize:可以将serialize生成的字符串变换回变量。

php进行序列化的目的是保存一个对象方便以后重用。

怎么去发现PHP反序列化漏洞

在代码审计过程中,先要找一个可控的反序列化函数,通过这个反序列化函数我们去调用一些类,这些类可能会包含一些魔法函数,在这些魔法函数中可能会有一些我们可控的危险操作,从而就触发反序列化漏洞。

如何产生的反序列化漏洞

如果一个PHP代码中使用了unserialize函数去调用某一类,该类中会自动执行一些自定义的magic method。这些magic method中如果包含了一些危险的操作或者这些magic method会去调用类中其他带有危险的操作的函数,如果这些危险操作是可控的,那就可以对象注入。

注:魔法函数是指在php的语法中,有一些系统自带的方法名,这类函数都是以__下划线开头,并在特定的情况下被调用。如__construct() 和 __destruct()、__get() 和 __set()、__isset() 和 __unset()__call() 和 __callStatic()... ... 他们在面向对象编程中起着至关重要的作用。

所以,PHP代码的安全还是要依赖开发人员自身的安全意识是否足够。

请将你的笔记本电脑摄像头遮上!因为黑客正在……

怎样通过一张照片定位他人的地理位置?

教你三行代码制作文件加密隐藏神器

展开
收起

PHP 7.4 新特新速看,预加载了解一下~

PHP 7.4 ,下一个 PHP 7 较小的发布版,期望在 2019 年 11 月 28 日发布。因此,现在是时候让大家深入了解这个版本添加哪些新特性使 PHP 更快、更可靠。

虽然 PHP 7.4 显著地提升了性能和提高代码可读性,PHP 8 才将会是 PHP 性能真正的里程碑,这在 JIT inclusion 的提案显示已充分证明。

现在去无偿迁移

总之,今天我们将概览 PHP 7.4 最瞩目的特性和性能提升。在继续探索之前,你最好记住以下重要的时间节点:

6 月 6 日:PHP 7.4 Alpha 17 月 18 日:PHP 7.4 Beta 1 – Feature freeze(特性固化)11 月 28 日:PHP 7.4 GA Release你可从 the official RFC page 查看全部新特性和功能。

PHP 7.4 发布日期:

PHP 7.4 将于 2019 年 11 月 28 日发布。这是 PHP 7 的下一个小版本,会再次提升性能,提高代码的可读性和可维护性。

PHP 7.4 有什么新功能?

在这边文章中,我们将讨论 PHP 7.4 最终版本中应该增加一些变化和特性:

抛弃 array_merge :PHP 7.4 在数组表达式中引入了扩展运算符

从 PHP 5.6 开始,参数解析 是一种解析数组并遍历到参数列表中的语法。要解析一个或遍历一个数组,必须以 ...(三个点)作为前缀,如下所示:

functiontest(...$args){var_dump($args);}test(1,2,3);现在 PHP 7.4 的 RFC 建议将这个功能扩展到数组定义中:

$arr=[...$args];扩展操作符在数组表达式 第一个明显的优点是性能。RFC 文档:

扩展操作符应该比 array_merge 性能更好。不仅是因为扩展操作符是一种语言结构,array_merge 是一个函数,还因为可以优化编译常量数组的性能。

扩展操作符一个重要的优点是支持任何可遍历的对象, array_merge 函数只支持数组。

下面是数组表达式中的参数解析示例:

$parts=['apple','pear'];$fruits=['banana','orange',...$parts,'watermelon'];var_dump($fruits);如果你在 PHP 7.3 或更早版本中运行此代码,PHP 将抛出解析错误:

Parse error: syntax error, unexpected '...'(T_ELLIPSIS), expecting ']' in /app/spread-operator.php on line 3相反,PHP 7.4 将返回一个数组:

array(5){[0]=>string(6)"banana"[1]=>string(6)"orange"[2]=>string(5)"apple"[3]=>string(4)"pear"[4]=>string(10)"watermelon"}RFC 声明我们可以多次扩展同一个数组。而且,我们可以在数组中的任何地方使用扩展运算符语法,因为可以在扩展运算符之前或之后添加普通元素。所以,就像下面代码所示的那样:

$arr1=[1,2,3];$arr2=[4,5,6];$arr3=[...$arr1,...$arr2];$arr4=[...$arr1,...$arr3,7,8,9];也可以将函数返回的数组直接合并到另一个数组:

functionbuildArray(){return['red','green','blue'];}$arr1=[...buildArray(),'pink','violet','yellow'];PHP 7.4 输出以下数组:

array(6){[0]=>string(3)"red"[1]=>string(5)"green"[2]=>string(4)"blue"[3]=>string(4)"pink"[4]=>string(6)"violet"[5]=>string(6)"yellow"}我们也可以使用 生成器:

functiongenerator(){for($i=3;$i<=5;$i++){yield$i;}}$arr1=[0,1,2,...generator()];但是我们不允许合并通过引用传递的数组。考虑以下的例子:

$arr1=['red','green','blue'];$arr2=[...&$arr1];如果我们尝试按引用合并数组,则 PHP 会引发以下解析错误:

Parse error: syntax error, unexpected '&' in /app/spread-operator.php on line 3无论如何,如果第一个数组的元素是通过引用存储的,则它们也将通过引用存储在第二个数组中。这是一个例子:

$arr0='red';$arr1=[&$arr0,'green','blue'];$arr2=['white',...$arr1,'black'];这就是我们使用 PHP 7.4 所获得的:

array(5){[0]=>string(5)"white"[1]=>&string(3)"red"[2]=>string(5)"green"[3]=>string(4)"blue"[4]=>string(5)"black"}The Spread operator 提案以 43 票对 1 票获得通过。

箭头函数 2.0 (短闭包)

对于 PHP 而言,匿名函数 被认为十分冗长并且难以使用和维护的。RFC 提出了更短并且语法更简洁的 * 箭头函数(短闭包),能够在很大程度上使我们的 PHP 代码更简洁。

考虑如下例子:

functioncube($n){return($n*$n*$n);}$a=[1,2,3,4,5];$b=array_map('cube',$a);print_r($b);PHP 7.4 允许使用更简洁的语法,上面的函数可以重写为如下:

$a=[1,2,3,4,5];$b=array_map(fn($n)=>$n*$n*$n,$a);print_r($b);目前,要感谢 use 语法,匿名函数 (闭包) 可以从父作用域里继承已经定义的变量:

$factor=10;$calc=function($num)use($factor){return$num*$factor;};但是在 PHP 7.4 中, 在父作用域里定义的变量被隐式捕获(隐式作用域绑定)了。如此一来,我们可用只用一行代码重写整个上面的函数:

$factor=10;$calc=fn($num)=>$num*$factor;我们可以像使用 use(变量) 一样,直接使用在父作用域里定义的变量,并且它也不会修改父作用域的变量。

新的语法对我们构建更可读可维护的代码带来了极大的改善。我们也可以使用参数和返回类型、默认值、变长参数列表(可变函数),可以传递或返回引用等等。然后呢,短闭包还可以被用作类方法,可以像常规一样使用 $this。

RFC 已经以 51 票对 8 票通过了,所以我们可以期待在 PHP 7.4 新增功能里见到它。

空合并赋值操作符

在 PHP 7 中,当我们需要同时使用三元运算符和 isset() 时,合并运算符(??)就可以派上用场了。如果第一个操作数是存在并且不为 NULL,则返回该操作数。否则返回第二个操作数。示例如下:

$username=$_GET['user']??'nobody';这段代码很简单:获取请求参数,如果不存在,则设置一个默认值。它的意思很明确,但如果出现像下方这个来自 RFC 中示例这种更长的变量名呢?

$this->request->data['comments']['user_id']=$this->request->data['comments']['user_id']??'value';从长远的角度看,这段代码可能有点难以维护。因此,为了帮助开发人员编写更直观的代码,这个 RFC 建议引入空合并赋值操作符(??=)。因此,我们可以编写如下代码进行替代:

$this->request->data['comments']['user_id']??='value';如果左侧的参数是 null,则使用右侧参数的值。请注意,当合并运算符是比较运算符时,??= 就是一个赋值运算符。

这项建议以 37:4 的票获得通过。

类型属性 2.0

参数类型声明(或类型提示)允许对将要传递给函数或者类方法的变量类型进行限定。该功能自 PHP 5 起可用,PHP 7.2 起可以使用对象作为数据类型。现在 PHP 7.4 通过添加 类属性类型声明 进一步扩展了类型提示。以下是一个基本的示例:

classUser{public int $id;public string $name;}支持 void 与 callable 以外的所有类型

public int $scalarType;protected ClassName $classType;private?ClassName $nullableClassType;这项 RFC 解释了为什么不支持 void 和 callable 返回值的原因:

不支持 void 类型,因为它没有用到并且语义不明确。不支持 callable 类型,因为其行为取决于上下文。

这样我们就可以安全地使用 bool, int, float, string, array, object, iterable, self, parent, 任何类或接口名称,并且可以为空 types (?type)。

类型可以用于静态属性:

publicstatic iterable $staticProp;也可以使用 var 标记:

var bool $flag;可以设置默认属性值,当然必须与声明的属性类型匹配,但是只有可为空的属性可以具有默认的 null 值:

public string $str="foo";public?string $nullableStr=null;相同类型适用于单个声明中的所有属性:

public float $x,$y;如果我们对属性类型进行错误处理会怎样?考虑以下代码:

classUser{public int $id;public string $name;}$user=newUser;$user->id=10;$user->name=[];在上面的代码中,我们声明了字符串属性类型,但是我们将数组设置为属性值。在这种情况下,我们将收到以下致命错误:

Fatal error: Uncaught TypeError: Typed property User::$name must be string,array used in /app/types.php:9该 RFC 已以 70 票对 1 票获得批准。

弱引用

在这项 RFC 中,PHP 7.4 引入了 WeakReference (弱引用) 类型,这样开发者就可以保留对对象的引用,而这不会阻止对象本身被破坏。

目前,PHP 通过使用诸如 pecl-weakref 之类的扩展名来支持弱引用。无论如何,新的 API 与记录的 WeakRef 类不同。

这是 一份简单的 demo 来自这项提议的作者 Nikita Popov。

$object=newstdClass;$weakRef=WeakReference::create($object);var_dump($weakRef->get());unset($object);var_dump($weakRef->get());第一个 var_dump 打印对象 object(stdClass)#1 (0) {} ,第二个 var_dump 打印引用为 NULL,因为所引用的对象已被销毁。

该 RFC 以 28 票对 5 票获得通过。

协变量返回和协变量参数

方差 是类层次结构的一个属性,描述了类型构造函数的类型如何影响 subtypes。通常,类型构造函数可以是:

Invariant:如果超类型的类型约束子类型的类型。Covariant:如果保留类型的顺序(类型从更具体到更一般)。Contravariant:如果它颠倒了顺序(类型从更通用到更具体地排序)。目前,PHP 的参数和返回类型大部分不变,只有少数例外。该 RFC 建议允许在参数类型和返回类型上进行协方差和协变,并提供一些代码示例。

这是 协变量返回 的一个简单例子:

interfaceFactory{functionmake(): object;}classUserFactoryimplementsFactory{functionmake(): User;}这个是 协变量参数 一个示例:

interfaceConcatable{functionconcat(Iterator $input);}classCollectionimplementsConcatable{// accepts all iterables, not just Iteratorfunctionconcat(iterable $input){/* . . . */}}请参阅 RFC 以更详细地了解 PHP 7.4 协变量返回和协变量参数。

该 RFC 以 39 对 1 票获得通过。

预加载

这项提议 来自 Dmitry Stogov ,这是我们的受支持的提议之一,因为它可以显着提高 PHP 的性能。预加载 是在模块初始化时将库和框架加载到 OPCache 的过程,详细了解 [PHP 生命周期]。

PHP 生命周期 (资源镜像: PHP Internals)

用 Dmitry 的话来说,预加载是这样工作的:

在服务器启动时(在运行任何应用程序代码之前),我们可以将一组 PHP 文件加载到内存中,并使它们的内容 永久可用 给该服务器将服务的所有后续请求。与内部实体完全一样,这些文件中定义的所有函数和类也可用于开箱即用的请求。

这些文件在服务器启动时加载,在任何应用程序之前执行,并且对以后的任何请求均可用。就性能而言,这很棒。

Preloading is controlled by a specific php.ini directive: opcache.preload. This directive specifies a PHP script to be compiled and executed at server start-up. This file can be used to preload additional files, either including them or via the opcache_compile_file() function (read more on PHP documentation).预加载由特定的 php.ini 指令控制:opcache.preload。该指令指定在服务器启动时要编译和执行的 PHP 脚本。此文件可用于预加载其他文件,包括它们或通过 opcache_compile_file() 函数(有关更多信息,请参见 [PHP 文档](https://www.php.net/manual/en/function.opc... -file.php))。

但是有一个缺点。实际上,RFC 里有明确声明:

预加载的文件将永远保留在 opcache 内存中。不重新启动另一台服务器,对其相应源文件的修改将不会生效。

但是,在预加载的文件中定义的所有函数将被永久加载到 PHP 函数和类表中,并且对于以后的每个请求均可用。即使这些改进可能有很大的不同,也会带来良好的性能改进。

您可以在官方的 预加载 RFC 页面 上阅读有关预加载的限制和例外的更多信息。

新的自定义对象序列化机制

这是 Nikita Popov 的另一项提议

当前,我们有两种不同的机制可以在 PHP 中对对象进行自定义序列化:

__sleep() 和 __wakeup() 魔术方法Serializable 接口根据 Nikita 的说法,这两个选项都存在导致复杂且不可靠的代码的问题。您可以在 RFC 中深入研究此主题。在这里我只是提到新的序列化机制应该通过提供两种新的魔术方法__serialize() 和 __unserialize() 来解决这些问题,这两种方法结合了两个现有机制。

该提案以 20 票对 7 票获得通过。

已废弃

PHP 7.4 不推荐使用以下功能。要获得更全面的弃用列表,请查看 PHP 7.4 升级说明。

更改串联运算符的优先级

当前,在 PHP 中,+ 和 - 算术运算符以及 . 字符串运算符保持关联性并具有相同的优先级。(阅读更多相关信息运算符优先级)

例如,考虑以下行:

echo"sum: ".$a+$b;在 PHP 7.3 中,此代码产生以下警告:

Warning:A non-numeric value encountered in /app/types.php on line 4这是因为从左到右评估了串联。与编写以下代码相同:

echo("sum: ".$a)+$b;这项 RFC 建议更改运算符的优先级,给 . 赋予比 + 和 - 运算符低的优先级,以便总是在字符串连接之前执行加法和减法。该行代码应等效于以下内容:

echo"sum: ".($a+$b);这是一个两步建议:

从 7.4 版开始,PHP 在遇到带有 + ,- 和 . 的非括号表达式时应发出弃用通知。这些运算符的优先级的实际更改应在 PHP 8 中添加。两项提议均以绝大多数票获得批准。

弃用左联想三元运算符

在 PHP 中,与许多其他语言不同,三元运算符是左关联的。根据 Nikita Popof 的说法,这对于在不同语言之间进行切换的开发者可能会造成混淆。

当前,在 PHP 中,以下代码是正确的:

$b=$a==1?'one':$a==2?'two':$a==3?'three':'other';解释为:

$b=(($a==1?'one':$a==2)?'two':$a==3)?'three':'other';这可能会导致错误,因为这可能不是我们打算要做的。因此,该 RFC 建议弃用并删除三元运算符的左关联性,并强制开发人员使用括号。

这是另外两个步骤的建议:

从 PHP 7.4 开始,不显式使用括号的嵌套三元将抛出弃用警告。从 PHP 8.0 开始,将出现编译时错误。该提案以 35 到 10 票获得批准。

在 Docker 中安装和运行 PHP 7.4

想在 Docker 上试试吗?幸运的是在 Docker 环境下你不需要再手动编译和配置 PHP 7.4 了 。如果你已经安装了 Docker , 那只需要花几秒钟安装这个非官方的 PHP-FPM 7.4 Docker 镜像 就可以在命令行中进行测试了。

如果你想要运行 PHP 7.4 的代码到你的浏览器中,那你还需要给 Docker 安装 Nginx 或 Apache 镜像。不用担心,只要按照 开发指南。将示例命令拷贝粘贴到命令行中并运行,就可以了。

摘要

在这篇文章中我们简单介绍了 PHP 7.4 发行版大量的更新和新增功能。如果你还想要了解完整的功能列表和正式的 RFC 官方文档,可以参考这些资源:

PHP 7.4 要求说明PHP 7.4 升级说明PHP 7.4 准备任务

展开
收起

这3种php高级过滤了解一下,很实用!

在php中有很多的过滤,可以对输入的字符串进行过滤,同时也可以对邮件地址进行过滤,接下来我要讲的是php中的3种高级过滤,在开发中很实用。

第一种:过滤数值范围

在php经常要接收各种数据,其中数值是非常普遍的一种,我们接收到的数值并不是多大都行的,无用的数据对于我们的数据库来说就是浪费资源,所以在接收数据的时候,有必要对数字的范围进行过滤。

对数字的范围进行过滤这里需要用到的是FILTER_VALIDATE_INT这个关键字以及它的附加条件,步骤如下:

1、新建一个变量。

2、通过filter_var函数对这个变量进行过滤,过滤的根据是FILTER_VALIDATE_INT,附加条件是数字的最大值和最小值。例如:filter_var($shuzi,FILTER_VALIDATE_INT,array("options"=>array("min_range"=>$min,"max_range"=>$max))。

3、最后就是根据过滤的结果给出相应的提示信息。

第二种:对ipv6地址进行过滤。

如今ipv4地址已经用完了,逐渐开始使用ipv6地址,在接收这类IP地址的时候,我们很可能就会遇到ipv6这样的地址,针对这样的地址,我们借用FILTER_VALIDATE_IP,FILTER_FLAG_IPV6这两个条件来进行过滤。实例代码如下:

$ipv6="2004:0db9:89a3";

$panduan=filter_var($ipv6,FILTER_VALIDATE_IP,FILTER_FLAG_IPV6);

if($panduan){

echo "这是合法的ipv6地址";

}

else{

echo "这个ipv6地址不合法";

}

第三种:对查询语句的过滤。

在接收数据的时候,我们不能防止用户输入什么内容,有些用户就故意在输入信息的时候,搞sql注入,在网址上添加查询语句,这样的语句我们是要拒绝接收的,所以,在接收网址的时候,对它进行过滤是非常有必要的,判断地址中是否包含了查询语句。

判断是否包含查询语句,我们可以通过FILTER_VALIDATE_URL和FILTER_FLAG_QUERY_REQUIRED这两个关键字来实现,具体代码如下:

$chaxun="http://www.nihao select * from b hello";

$panduan=filter_var($chaxun,FILTER_VALIDATE_URL,FILTER_FLAG_QUERY_REQUIRED);

if($panduan){

echo "url地址是不合法的";

}

else{

echo "url地址是合法的";

}

以上就是关于3种php高级过滤,有兴趣的朋友可以了解一下,同时欢迎提出宝贵的意见和建议。

展开
收起

全栈前端开发工程师可以了解的php基础

判断值"jason",是否存在数组$arr中

$a = array('sky','elson','david');

if(in_array('jason',$a)){

echo '存在';

}else{

echo '不存在';

}

数组$arr3倒叙输出,带键值

$a01 = array('aa'=>'sky','bb'=>'elson','cc'=>'david');

$a01=array_reverse($a01,true);

print_r($a01);

数组$arr3随机顺序输出,带键值

$a01 = array('aa'=>'sky','bb'=>'elson','cc'=>'david');

$temp_arr=$a01;

$temp_arr=array_flip($temp_arr);//Array ( [sky] => aa [elson] => bb [david] => cc )

//print_r($temp_arr);

shuffle($temp_arr);

//print_r($a01);// Array ( [0] => david [1] => sky [2] => elson )

$arr=array();

foreach($temp_arr as $key=>$value){

$arr[$value]=$a01[$value];

}

print_r($arr);

把字符串"sky alex joe david miny"组装为一个数组

$a02="sky alex joe david miny";

$a02=explode(' ',$a02);

print_r($a02);

假设有数组array('sky'=>1,'alex'=>2,'jason'=>3),请把数组的键值位置调换

$a03=array('sky'=>1,'alex'=>2,'jason'=>3);

$a03=array_flip($a03);

print_r($a03);

有数组array(1,2,3,4,5,6,7,8,9,10),请分别过滤出单双数,最少用2种方法完成

$menu=array(1,2,3,4,5,6,7,8,9,10);

foreach($menu as $value){

if($value%2==0){

$ou[]=$value;

}else{

$ji[]=$value;

}

}

print_r($ou);

print_r($ji);

$menu=array(1,2,3,4,5,6,7,8,9,10);

function odd($var)

{

return($var % 2 == 1);

}

function even($var)

{

return($var % 2 == 0);

}

print_r(array_filter($menu,'odd'));

print_r(array_filter($menu,'even'));

有数组a = array('sky','elson','david') b = array('miny','joe','judy'),合并2个数组

//print_r(array_merge(array('sky','elson','david'),array('miny','joe','judy')));

有如下手机信息表

机型牌子

G10htc

N85诺基亚

盖世3三星

iphone5apple

anycall三星

请用数组保存以上信息,并遍历数组,若发现三星牌子手机,把手机名字保存至数组$arrPhone中,并在最后打印输出

$arrPhone = array();

$phone=array(

'htc'=>'G10',

'诺基亚'=>'N85',

'apple'=>'iphone5',

'三星'=>array(

'盖世3','anycall'

)

);

foreach($phone as $key=>$value){

if($key=='三星'){

foreach($value as $v){

$arrPhone[]=$v;

}

}

}

print_r($arrPhone);

思考:请用数组保存如下数据,并最终按以下形式输出到页面中

家电

-洗衣机

--全自动

--半自动

-电视

--3D

--高清

服装

-女装

--裙

--上衣

-男装

--裤

---短裤

---长裤

$menu=array(

'家电'=>array(

'洗衣机'=>array(

'全自动','半自动'

),

'电视'=>array(

'3D','高清'

)

),

'服装'=>array(

'女装'=>array('裙','上衣'),

'男装'=>array(

'裤'=>array(

'短裤','长裤'

)

)

)

);

foreach($menu as $key=>$value){

echo $key.'<br/>';//家电 服装

foreach($value as $k1=>$v1){

echo '-'.$k1.'<br/>';//洗衣机电视女装男装

foreach($v1 as $k2=>$v2){

if(is_array($v2)){

echo '--'.$k2.'<br/>';

foreach($v2 as $k3=>$v3){

echo '---'.$v3.'<br/>';

}

}else{

echo '--'.$v2.'<br/>'; //'全自动','半自动' '3D','高清''裤'

}

}

}

}

展开
收起

前端开发工程师可以了解的PHP数组定义以及Foreach遍历方法

php定义数组,与JS区别在于不使用new关键字 且首字不需要大写

/* $arr=array();

$arr[2]='sky';

$arr[0]='weiyin';

$arr[1]='selecr';

print_r($arr); */

//数组不能这样输出;因为echo只能输出数字和字符串

//print_r($arr);//用于生产模式

//var_dump($arr);//输出变量的详细信息,可以输出简单的数据类型,也可以输出数组,object等复杂的数据类型,一般用于调试模式

//var_dump('abc');

//print $arr;

$arr=array(

0=>5,

'name'=>'sky',

'email'=>'3811230@qq.com',

'love'=>array(

'name'=>'帅哥',

'name01'=>'钞票'

)

);

// print_r($arr['name']);

foreach($arr as $key=>$value){

// echo 'k:'.$key.'=>v:'.$value.'<br/>';

if(is_array($value)){

foreach($value as $k=>$v){

echo 'k:'.$k.'=>v:'.$v.'<br/>';

}

}

}

/*foreach(数组名 as 键值=>遍历元素){} 遍历数组,将数组从头到尾遍历了一遍*/

**echo、print、print_r的区别

**相同点:echo/print/print_r都可以在页面进行输出

**不同点:1.echo是一个语言结构,不是函数[echo()/echo],没有返回值,只能输出数字和字符串

2.print和echo类似,是一个语言结构,有返回值,也只能输出数字和字符串

3.print_r是一个函数,有返回值,可以打印简单数据类型也可以打印数组,object等复杂的数据类型

varchar和char的区别

共同点:都是字符串,总长度是255

不同点:varchar是可变长度(varchar的长度是实际存储的值的长度),假设字符长度设置为10,如果存储的值只有5,那么varchar的长度是5;

char是固定长度(char的长度是设定的长度);

注意:所有的字段都不能设置为空

主键:用来标识唯一的行

1.每张表都要有且只有一个主键

2.一般来说主键都是int类型,并且自动递增(A_I)

2.1:主键id不会覆盖,也不会重复

2.2:删除其中一条数据后,id不存在,但是也不会被覆盖

时间可以保存为date/datetime,但是建议使用int,因为数字的读取和存储要比字符串的效率高

如果大家了解了今天的内容,可以尝试做做练习:

作业一

计算1-100中,除了5的倍数外所有数的总和

$num=0;

for($i=0;$i<101;$i++){

if($i%5!=0){

}}

作业二:

得到一个随机数,直到这个数字为9的倍数时,输出这个数字并输出ok,否则只输出这个数字并继续循环

$num=mt_rand(0,100);

while($num%9!=0){

echo $num; //条件成立时

echo '<br/>';

$num=mt_rand(0,100); //条件自身变化

}

echo $num.'0k';

作业三

设有变量$s1 = 'str1';$s2 = 'str2'

定义一个变量a,如果a等于0,输出10/3的余数;若a大于0,输出变量$s1和$s2的拼接字符串;若少于0,把$s2转为大写

$s1 = 'str1';

$s2 = 'str2';

$a=-9;

if($a==0){

$num=10%3;

echo $num;

}else if($a>0){

$s3=$s1.$s2;

echo $s3;

}else{

echo strtoupper($s2);

}

展开
收起

了解PHP字符串这三点,字符串处理就能做到游刃有余!

字符串的处理在编程中是一个不可缺少的内容,它们往往是简单而且重要存在。信息的解析、储存和显示、网络数据传输需要操作字符串来完成,尤其在web开发中这一点更为明显。程序开发大部分时间都花在操作字符串,有时候对字符串的处理也能检验程序员的编程能力。

字符串处理方式

在C中字符串作为字节处理,在Java语言中字符串作为对象处理的,而在PHP中字符串时作为数据类型来处理。PHP中常见的字符串操作涉及到字符串格式化、链接、比较、查找、匹配、替换,另外PHP中提供很多的字符串操作函数,字符串函数功能强大、使用方便可以在很大程度上提高效率。字符串函数和正则表达式都可以操作字符串,建议使用字符串函数,字符串函数要比正则表达式效果要高。但是要处理很复杂的字符串建议使用正则表达式。

php字符串类型特点

php是弱类型语言,其他类型的数据一般可以直接用于字符串函数里,自动转换成字符串数据类型进行处理。在“echo substr(1000,1,3);”这个例子中,整形数据在字符串函数sbstr处理后会输出字符串000。可以用以下两种方法来输出,中括号语法用的不多,一般都是使用花括号。

PHP中常见的字符串函数

函数echo()

函数echo()用于输出若干个字符串,在PHP中使用最多的函数,因为使用它的效率比其他字符串函数高。严格来说echo()不是函数而是语言结构,使用时可以去掉花括号。如果是传递多个参数,使用括号会出现解析错误。

函数pirnt()

函数pirnt()和函数echo()功能是一样的,但是它有返回值,成功返回1,失败返回0。print也可以不用花括号,print执行效率不如echo高。

函数die()

是exit()函数别名。如果是参数是字符串,函数会在退出前输出、如果参数是整数,这个值被用作推出状态。退出状态值在0到254之间。255由PHP保留。

函数printf()

用于输出格式化的字符串,函数printf()第一个参数是必选项(规定如何格式化其中变量),多个可选参数,规定插到第一个参数的格式化字符中对应%符号处的参数。如$num = 13亿;$str = "中国";printf("在%s有 %u 亿人口",$str,$num);最后输出结果是“在中国有13亿人口”。函数printf()参数表:

今天关于PHP字符串先说到这,以后再接着说。每天一个知识点,每日寄语-“不因昨日收获而满足,因为这是失败的先兆。”

展开
收起

PHP实战技巧(15)通过phpinfo()了解你的PHP配置状况(一)

前言

工欲善其事,必先利其器。当你使用PHP编程,就需要对它的运行状况有所了解,否则事倍功半。

从今天起,和大家聊一聊 phpinfo() 函数所展示的信息含义。

phpinfo() 有什么用

它是一个系统函数,你可以直接编写代码 <?php phpinfo();?>,然后通过网页访问它,就能看到一个类似于这样的网页。

该网页包含了当前PHP的各种配置信息、扩展模块的信息等。以前有一种软件叫“探针”,专门用来探测服务器当前的PHP相关信息,现在随着虚拟主机的没落,已经越来越少人用啦。

如何阅读 phpinfo 的信息?

整个网页内容非常多,但主要分为四个部分

基本信息,也就是最顶部的内容。配置信息(Configuration)各种模块的信息PHP Credits,荣誉名单,记录对PHP语言有帮助的人PHP License 版权许可说明

基本配置

本文和大家说说基本信息中,各项内容的含义。(以我当前使用的PHP版本为例)

PHP 版本

最顶端:PHP Version 7.2.3,就是我们当前PHP的版本。

System

Darwin mac.local 17.5.0 Darwin Kernel Version 17.5.0: Fri Apr 13 19:32:32 PDT 2018; root:xnu-4570.51.2~1/RELEASE_X86_64 x86_64

运行此PHP的操作系统信息(我是mac机)

Build Date

Mar 19 2018 11:50:19

编译时间

Configure Command

'./configure' '--prefix=/usr/local/opt/php723' '--exec-prefix=/usr/local/opt/php723/' '--enable-debug' '--enable-fpm' '--with-iconv=/usr/' '--with-config-file-path=/usr/local/etc/php723' '--with-openssl=/usr/local/opt/openssl' '--enable-bcmath' '--with-curl' '--enable-exif' '--with-gd' '--with-mysqli' '--with-pdo-mysql' '--enable-zip' '--with-libzip' '--enable-mysqlnd' '--enable-sockets' '--enable-mbstring' '--enable-soap' '--with-freetype-dir=/usr/local/opt/freetype' '--with-xmlrpc' '--with-jpeg-dir=/usr/local/opt/jpeg' '--with-png-dir=/usr/local/opt/libpng' '--with-libxml-dir=/usr/local/opt/libxml2' '--without-gmp'

编译时,使用的各项配置信息。

Server API

FPM/FastCGI

当前采用的服务模式为 FCGI(快速通用网关接口协议),实现该协议的服务为 FPM(也就是PHP-FPM),与 NGINX 搭配的时候,基本都是通过它来进行通讯的,以后有机会和大家细聊。

Virtual Directory Support

disabled

虚拟目录支持,目前是禁用状态(disabled)也就是不支持。

Configuration File (php.ini) Path

/usr/local/etc/php723

PHP.ini 的所在目录。

Loaded Configuration File

/usr/local/etc/php723/php.ini

php.ini 所在的完整文件路径。

Scan this dir for additional .ini files

(none)

Additional .ini files parsed

(none)

PHP API

20170718

PHP核心版本,一般大版本变更时,此日期会随之变化(应该是核心版本的发布或编译日期)

其他

剩下的就不一一说明了,需要额外提醒的是,此处出现的 zend 是PHP解释器名字,你也可以认为它就是PHP核心,除此之外还有 zend框架、zend代码混淆、zend代码编辑器,注意不要把自己弄混了。

总结

今天先和大家介绍下基本信息,其中像PHP版本、configure的编译配置、php.ini的路径、php api 的版本等几项,是我们日常开发中需要用到的。其余的,大家有兴趣可以自己行了解。

明天开始,介绍第二部分:各种扩展库。

展开
收起