分类 PHP 基础 下的文章

Published on 23 February 2020 by laruence
本文地址: https://www.laruence.com/2020/02/23/1990.html
转载请注明出处

一个问题, var_dump(1...9)输出什么?

动手验证下:

php -r “var_dump(1...9)”;
string(4) ”10.9“

输出10.9, 乍一看这个var_dump的输出很奇怪是不是? 为什么呢?

这里教大家,如果看到一段PHP代码感觉输出很奇怪,第一反应是看下这段代码生成的opcodes是啥,虽然这个问题其实是词法分析阶段的问题,不过还是用phpdbg分析下吧(一般为了防止opcache的影响,会传递-n):

phpdbg -n -p /tmp/1.php
function name: (null)
L1-35 {main}() /tmp/1.php - 0x7f56d1a63460 + 4 ops
L2 #0 INIT_FCALL<1> 96 "var_dump"
L2 #1 SEND_VAL "10.9" 1
L2 #2 DO_ICALL
L35 #3 RETURN<-1> 1

所以这么看来,早在生成opcode之前,1...9就变成了常量10.9,考虑到这是字面量,我们现在去看看zend_language_scanner.l, 找到这么一行:

DNUM ({LNUM}?"."{LNUM})|({LNUM}"."{LNUM}?)

这个是词法分析定义的浮点数的格式,到这里也就恍然大悟了:
1...9 会被依次接受为: 1. (浮点数1), 然后是 . (字符串连接符号) 然后是.9(浮点数0.9)

所以在编译阶段就会直接生成 “1” . “0.9” -> 字符串的字面量”10.9”

好了,到这里,这个小“谜题”就解释清楚了。

当然这个也不仅仅是PHP会这么定义了,几乎所有的语言都会定义这种缩写浮点数都形式. C语言中有的时候我们为了输入一个浮点型的整形,就可以采用比如 1. 来告诉编译器这是个浮点数.

只不过,一来刚好在PHP中.号还有另外一层含义就是字符串连接,二来...在PHP5.6之后是个新的操作符叫做Splat operator, 可以用来定义可变参数函数,或者解数组,比如,

<?php
 
function  foo($a, $b, $c) {
        var_dump($a + $b + $c);
}
 
 
$parameters = array (1, 2, 3);
 
foo(...$parameters);
?>

所以, 乍一看才会导致了这个看起来很困惑的结果, :)

  • is_dir 判断给定文件名是否是一个目录
  • pathinfo 返回文件路径的信息 dirname basename extension filename
  • scandir 列出指定路径中的文件和目录
  • fopen 打开文件或者 URL
  • fgets 从文件指针中读取一行
  • strpos 查找字符串首次出现的位置
  • trim 去除字符串首尾处的空白字符(或者其他字符)
  • str_replace 子字符串替换
  • strpos 查找字符串首次出现的位置
  • strlen 获取字符串长度
  • array_sum 对数组中所有值求和
  • file_exists 检查文件或目录是否存在
  • file_put_contents 将一个字符串写入文件
  • file_get_contents 将整个文件读入一个字符串
  • rename 重命名一个文件或目录
  • array_slice 从数组中取出一段
  • number_format 以千位分隔符方式格式化一个数字
  • unlink 删除文件

Downloaded

  • ReStructuredText Support

Bundled

  • Angular and AngularJS
  • Apache config(.htaccess)
  • ASP
  • Behat Support
  • Blade
  • ChangeReminder
  • Codeception Framework
  • CoffeeScript
  • Command Line Tool
  • Copyright
  • CSS
  • Database Tools and SQL
  • Docker
  • DQL Support
  • Drupal
  • EditorConfig
  • File Watchers
  • FTP/SFTP Connectivitu(ex. Remote Hosts Access)
  • Gherkin
  • Git
  • GitHub
  • GNU GetText files support(*.po)
  • Haml
  • HTML Tools
  • HTTP Client
  • Hunspell
  • IDE Setting Sync
  • Ini
  • IntelliLang
  • JavaScript and TypeScript
  • JavaScript Intention Power Pack
  • Joomla! Support
  • Less
  • Machine Learning Code Completion
  • Markdown
  • Mercurial
  • NodeJS
  • Perforce
  • Performance Testing
  • Phing
  • PHP Docker
  • PHP Remote Interpreter
  • PHP WSL Support
  • PHPSpec BDD Framework
  • PHPT Support
  • Refactor-X
  • Sass
  • Settings Repository
  • Shell Script
  • Subversion
  • Task Management
  • Terminal
  • TextMate bundles
  • Time Tracking
  • tslint
  • Twig Support
  • UML
  • Vagrant
  • Vue.js
  • W3C Validators
  • WordPress
  • XPathView + XSLT
  • YAML

key 可以是 integer 或者 string。value 可以是任意类型。

此外 key 会有如下的强制转换:

  • 包含有合法整型值的字符串会被转换为整型。例如键名 "8" 实际会被储存为 8。但是 "08" 则不会强制转换,因为其不是一个合法的十进制数值。
  • 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
  • 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
  • Null 会被转换为空字符串,即键名 null 实际会被储存为 ""。
  • 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type

如果未指定,PHP 将自动使用之前用过的最大 integer 键名加上 1 作为新的键名。

  • PHP 标记

    当解析一个文件时,PHP 会寻找起始和结束标记,也就是 <?php 和 ?>,这告诉 PHP 开始和停止解析二者之间的代码。此种解析方式使得 PHP 可以被嵌入到各种不同的文档中去,而任何起始和结束标记之外的部分都会被 PHP 解析器忽略。

    PHP 也允许使用短标记 <? 和 ?>,但不鼓励使用。只有通过激活 php.ini 中的 short_open_tag 配置指令或者在编译 PHP 时使用了配置选项 --enable-short-tags 时才能使用短标记。

    如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记。这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白,而脚本中此时并无输出的意图。

  • 从 HTML 中分离

    凡是在一对开始和结束标记之外的内容都会被 PHP 解析器忽略,这使得 PHP 文件可以具备混合内容。 可以使 PHP 嵌入到 HTML 文档中去,如下例所示。

    <p>This is going to be ignored by PHP and displayed by the browser.</p>
    <?php echo 'While this is going to be parsed.'; ?>
    <p>This will also be ignored by PHP and displayed by the browser.</p> 
>这将如预期中的运行,因为当 PHP 解释器碰到 ?> 结束标记时就简单地将其后内容原样输出(除非马上紧接换行 - 见指令分隔符)直到碰到下一个开始标记;例外是处于条件语句中间时,此时 PHP 解释器会根据条件判断来决定哪些输出,哪些跳过。见下例。 

>使用条件结构:

>Example #1 使用条件的高级分离术
<?php if ($expression == true): ?>
  This will show if the expression is true.
<?php else: ?>
  Otherwise this will show.
<?php endif; ?> 
>例中 PHP 将跳过条件语句未达成的段落,即使该段落位于 PHP 开始和结束标记之外。由于 PHP 解释器会在条件未达成时直接跳过该段条件语句块,因此 PHP 会根据条件来忽略之。 

>要输出大段文本时,跳出 PHP 解析模式通常比将文本通过 echo 或 print 输出更有效率。 

>可以在 PHP 中使用四对不同的开始和结束标记。其中两种,<?php ?> 和 <script language="php"> </script> 总是可用的。另两种是短标记和 ASP 风格标记,可以在 php.ini 配置文件中打开或关闭。尽管有些人觉得短标记和 ASP 风格标记很方便,但移植性较差,通常不推荐使用。 

>此外注意如果将 PHP 嵌入到 XML 或 XHTML 中则需要使用 <?php ?> 标记以保持符合标准。 

>Example #2 PHP 开始和结束标记
1.  <?php echo 'if you want to serve XHTML or XML documents, do it like this'; ?>

2.  <script language="php">
        echo 'some editors (like FrontPage) don\'t
              like processing instructions';
    </script>

3.  <? echo 'this is the simplest, an SGML processing instruction'; ?>
    <?= expression ?> This is a shortcut for "<? echo expression ?>"

4.  <% echo 'You may optionally use ASP-style tags'; %>
    <%= $variable; # This is a shortcut for "<% echo . . ." %> 
>上例中的 1 和 2 中使用的标记总是可用的,其中示例 1 中是最常用,并建议使用的。 

>短标记(上例 3)仅在通过 php.ini 配置文件中的指令 short_open_tag 打开后才可用,或者在 PHP 编译时加入了 --enable-short-tags 选项。 

>ASP 风格标记(上例 4)仅在通过 php.ini 配置文件中的指令 asp_tags 打开后才可用。

>Note: 在以下情况应避免使用短标记:开发需要再次发布的程序或者库,或者在用户不能控制的服务器上开发。因为目标服务器可能不支持短标记。为了代码的移植及发行,确保不要使用短标记。 

>Note: 在 PHP 5.2 和之前的版本中,解释器不允许一个文件的全部内容就是一个开始标记 <?php。自 PHP 5.3 起则允许此种文件,但要开始标记后有一个或更多白空格符。 

>Note: 在 PHP 5.2 和之前的版本中,解释器不允许一个文件的全部内容就是一个开始标记 <?php。自 PHP 5.3 起则允许此种文件,但要开始标记后有一个或更多白空格符。