PHP
标签(空格分隔): 面试
PHP的引用变量的概念及定义
延伸: PHP引用变量的原理
概念:
在 PHP 中 引用意味着用不同的名字访问同一个变量的内容
定义方式:
使用&符号
PHP引用变量的工作原理
$a=range(0,1000);
//定义变量b,将a变量的值赋值给b
//COW机制 (Copy On Write)
$b=$a;
//对a进行修改才会copy
$a=range(0,1000);
//验证COW机制可以使用函数memory_get_usage()
//在每个表达式后面读取内存量
//而引用赋值不遵从COW机制,永远指向一个内存空间
zval结构体
//zval变量容器
$a=range(0,3);
xdebug_debug_zval('a');
//定义变量b,把a的值赋值给b
$b= $a;
xdebug_debug_zval('a');
//修改a
$a=range(0,3);
xdebug_debug_zval('a');
unset 对引用变量的影响
unset只会取消引用,不会销毁空间
$a=1;
$b=&$a;
unset($b);
echo $a."\n"; //此时$a还存在值,证明只是取消$b的引用
对象不会复制空间,不遵守COW
对象本身就是引用传递
class Person{
public $name='zhangsan';
}
$p1=new Person;
xdebug_debug_zval('p1');
$p2=$p1;
xdebug_debug_zval('p1');
$p2->name='lisi';
xdebug_debug_zval('p1'); //此时并没有开辟出一个新空间,clone对象才可以
真题
//真题
/**
* TODO 写出如下程序的输出结果
*
*/
$data=['a','b','c'];
foreach($data as $key => $val){
$val=&$data[$key];
var_dump($data);
}
var_dump($data);
/**
* TODO 程序运行时,每一次循环结束后变量$data的值是什么?请解释
* TODO 程序执行完成后,变量$data的值是什么?请解释
*/
常量及数据类型考点
PHP中字符串可以使用哪三种定义方法以及各自的区别是什么?
- 定义方式: 单引号,双引号,heredoc和nowdoc
heredoc 和 nowdoc (看看)
$a='sdsd';
$str="abcdsd '{$a}'"; //会被解析变量,并且单引号会原样输出
echo $str;
单引号比双引号更快,建议写单引号
- heredoc类似双引号
- nowdoc类似双引号
- 两者都是用来处理大文本
知识点延伸
- 数据类型考点
- 8 大 3 类
- 标量,复合,特殊
- 浮点类型
-
浮点类型不能运用到比较运算中[???],感觉是比较运算当做判断条件
$a=0.1;
-
$b=0.5;
echo $a+$b.PHP_EOL;
$c=$a+$b == 0.6 ? true:false;
var_dump($c); //为true,不知道为什么
```
```php
$a=0.1;
$b=0.7;
if($a+$b == 0.8) { //用于条件判断时出错
echo 'haha';
}else{
echo '5555';
}
```
比较浮点类型可以用php内置函数 bccomp()
-
布尔值
- false: 0,0.0,'','0',false,array(),null
-
数组类型:
- 超全局数组:
$GLOBALS,$_GET, $_POST,$_REQUEST,$_SESSION,$_COOKIE,$_SERVER,$_FILES,$_ENV
- 超全局数组:
-
NULL
- 三种情况: 直接赋值为null,未定义的变量,unset销毁的变量
常量
-
预定义常量
- _FILE,_LINE,_DIR,_FUNCTION,_CLASS,_TRAIT,_METHOD,_NAMESPACE
定义方式
const,define
const更快,是语言结构
define是函数
define不能用于类常量的定义,const可以
常量一经定义,不能被修改,不能被删除
真题
用PHP写出显示客户端IP与服务器IP的代码
FILE表示什么意思?
运算符
foo()和@foo()之间区别
- 考点:PHP的运算符的错误控制符@
- 延伸:
- PHP所有运算符考点
- 运算符的优先级
- 比较运算符
- 递增递减运算符
- 逻辑运算符
PHP的错误运算符
PHP 支持一个错误运算符: @.
当将其放置在一个PHP表达式之前,该表达式可能产生的任何错误信息都被忽略掉
延伸考点: PHP运算符优先级
递增/递减 > ! > 算数运算符 > 大小比较 > (不)相等比较 > 引用 > 位运算符(^) > 位运算符(|) > 逻辑与 > 逻辑或 > 三目 > 赋值 > and > xor > or
- 括号的使用可以增加代码可读性
延伸考点: 比较运算符
- == 和 === 的区别
- 等值判断(FALSE的七种情况) ==> 前面说过布尔值那里
延伸考点: 递增/递减运算符
- 递增/递减运算符不影响布尔值 ==> ++/-- 不改变布尔值
- 递减NULL值没有效果
- 递增NULL值为1
- 递增和递减在前就先运算符后返回,反之就先返回,后运算
延伸考点: 逻辑运算符
- 短路作用
- || 和 && 与 or和and 的优先级不同
$a=true || $b === 3; //短路作用
$b=false && $a===1;
//比较运算符 优先级问题
$a = false || true; //返回true
$b = false or true; //返回false
流程控制考点
真题: 请列出三种PHP数组循环操作的语法,并注明各个循环的区别
- for
- foreach
- while,list(),each()组合循环
for循环只能遍历索引数组,foreach可以遍历索引和关联数组.
联合使用list(),each()和while循环同样可以遍历索引和关联数组
while,list(),each()组合不会reset(),即指针不会重置
foreach遍历会对数组进行reset()操作
延伸考点: PHP分支结构
- if ... else if
- 在elseif语句中只能有一个表达式为true,即在elseif语句中只能有一个语句块被执行,多个elseif从句是排斥关系
- 使用elseif 语句有一个基本原则,总把优先范围小的条件放在前面处理
- switch...case...
- 和if不同的是,switch后面的控制表达式的数据类型只能是整型,浮点类型或者字符串
- continue语句作用到switch的作用类似于break跳出switch外的循环,可以使用continue 2
- switch ... case 会生成跳转表,直接跳转到对应case
- 效率: 如果条件比一个简单的比较要复杂的多或者在一个很多次的循环中,那么用switch语句可能快一点
真题: PHP中如何优化多个if...elseif语句的情况?
自定义函数及内部函数
考点:
- 变量的作用于和静态变量
延伸: 函数的参数及参数的引用传递
: 函数的返回值及引用返回
: 外部文件的导入
变量的作用域
- 变量的作用域也称变量的范围,变量的范围即它定义的上下文背景(也是它的生效范围).
- 大部分的PHP变量只有一个单独的范围.
- 这个单独的范围跨度同样包含了include和require引入的文件
//写出如下程序的输出结果
$count=5;
function get_count(){
static $count; //静态变量 此时无赋值,则为null
return $count++; //null++ ==> 1
}
echo $count;
++$count;
echo get_count();
echo get_count();
考点:
变量的作用域和静态变量
- 延伸: 函数的参数及参数的引用传递
- 延伸: 函数的返回值及引用返回
- 延伸: 外部文件的导入
- 延伸: 系统内置函数
$outer='str';
function mgfunc()
{
//全局变量引入到函数体内部使用,用关键字global
global $outer;
//或者
$GLOBALS['outer'] //也可以
echo $outer;
}
静态变量
静态变量仅在局部函数中存在,但当程序执行离开此作用域时,其值并不会消失
static关键字
- 仅初始化一次
- 初始化时需要赋值
- 每执行函数该值会保留
- static修饰的变量是局部的,仅在函数内部有效
- 可以记录函数的调用次数,从而可以在某些条件下终止递归
function get_count()
{
static $count; //只初始化一次
return $count++;
}
echo get_count(); //null
echo get_count(); //1
echo get_count(); //2
延伸考点: 函数的返回值
- 值通过使用可选的返回语句(return)返回可以返回包括数组和对象的任意类型
- 返回语句会终止函数执行,将控制权交回函数调用处
- 省略return,返回值为null,不可有多个返回值
延伸考点: 函数的引用返回
从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 &
function &myFunc()
{
static $b=10;
return $b;
}
$a=myFunc();
$a=&myFunc();
$a=100;
echo myFunc(); //100
延伸考点: 外部文件的导入
- include/require 语句包含并运行制定文件
- 如果给出路径名按照路径来找,否则从include_path中查找
- 如果include_path中也没有,则从调用脚本文件所在目录和当前工作目录下寻找
- 当一个文件被包含时,其中所包含的代码继承了include所在行的变量范围
- 加载过程中未找到文件则include结构会发出一个警告;这一点和require不同,后者会发出一个致命错误
require在出错时会产生E_COMPILE_ERROR 级别错误.
换句话讲将导致脚本终止而include只会产生警告(E_WARNING),脚本会继续运行
require(include)/require_once(include_once)唯一区别是PHP会检查该文件是否已经被包含过,如果是则不会再次包含
延伸考点: 系统内置函数
-
时间日期函数:
date(),strtotime(),mktime(),time(),microtime(),date_default_timezone_set()
-
IP处理函数:
ip2long(),long2ip()
-
打印处理:
print(),printf(),print_r(),echo,sprintf(),var_dump(),var_export()
-
序列化及反序列化函数:
serialize(),unserialize()
-
字符串处理函数:
implode(),explode(),join(),strrev(),trim(),ltrim(),rtrim(),strstr(),number_format()...
-
数组处理函数:
array_keys(),array_values(),array_diff(),array_intersect(),array_merge(),array_shif(),
array_unshift(),array_pop(),array_push(),sort()...
解题方法:
着重记忆PHP函数的定义相关内容,理解变量作用域,静态变量,函数的参数和返回值的相关内容,重点记忆我们总结的内置函数
//真题
$var1=5;
$var2=10;
function foo(&$my_var)
{
global $var1;
$var1 +=2;
$var2 =4;
$my_var+=3;
return $var2;
}
$my_var=5;
echo foo($my_var)."\n";
echo $my_var."\n";
echo $var1;
echo $var2;
$bar='foo';
$my_var=10;
echo $bar($my_var)."\n";