PHP 基础知识

1. 引用变量;

问题:什么是引用变量?在 PHP 中,用什么符号定义引用变量?

PHP 的引用变量的概念及定义方式
概念:在 PHP 中引用意味着用不同的名字访问同一个变量内容
定义方式:使用 & 符号
  • 延伸:PHP 引用变量的工作原理
<?php
// 场景 1:
// 定义一个变量
// 内存开辟一块空间,$a 指向这个内存空间
$a = range(0, 1000);
var_dump(memory_get_usage());	// 查看内存空间
// 定义一个变量 b,将 a 变量的值赋值给 b
// 内存里不开辟空间,$b 指向 $a 指向的内存空间
// COW 机制:Copy On Write,表示有修改操作,才会复制内存
$b = $a;
var_dump(memory_get_usage());
// 对 $a 进行修改
// 虽然值没有发生改变,但是对它进行写操作,会开辟新内存空间
$a = range(0, 1000);
// 此时内存使用会翻倍
var_dump(memory_get_usage());

// 场景 2:
$a = range(0, 1000);
var_dump(memory_get_usage());
// 使用了“&”引用,表示 $a 和 $b 永远会指向同一块内存空间,而不会去复制,所以没有 COW 机制
$b = &$a;
var_dump(memory_get_usage());
$a = range(0, 1000);
// 此时内存使用不会有太大的变化
var_dump(memory_get_usage());

// 关于 zval 结构体
// 在 PHP 中,变量都是通过 zend 引擎处理,zend 引擎里有一个 zval 结构体
// 这个 zval 结构体就是变量容器,负责去管理变量的一些内容
// 场景 3:
$a = range(0, 3);
xdebug_debug_zval('a');		// a:refcount=1 表示 1 个变量指向这个内存空间, is_ref=0 表示引用 0
// 定义变量 $b,把 $a 的值赋值给 $b
$b = $a;
xdebug_debug_zval('a');		// a:refcount=2 表示 2 个变量指向这个内存空间, is_ref=0
// 修改 $a,$a 执行了写操作,不再指向之前的空间,复制了一块空间出来
$a = range(0, 3);
xdebug_debug_zval('a');		// a:refcount=1, is_ref=0

// 场景 4:
$a = range(0, 3);
xdebug_debug_zval('a');		// a:refcount=1, is_ref=0
$b = &$a;
xdebug_debug_zval('a');		// a:refcount=2, is_ref=1
$a = range(0, 3);
xdebug_debug_zval('a');		// a:refcount=2, is_ref=1

// 场景 5:
// 关于 unset(),只会取消引用,不会销毁内存空间
$a = 1;
$b = &$a;
unset($b);			// 取消 $b 引用
echo $a . "\n";		// 输出 1

// 场景 6:
// PHP 里对象本身就是引用传值,不需要加引用符号,它也是引用
class Person{
	public $name = "zhangsan";
}
$p1 = new Person();
xdebug_debug_zval('p1');		// p1:refcount=1, is_ref=0
$p2 = $p1;	// 指向同一个内存空间
xdebug_debug_zval('p1');		// p1:refcount=2, is_ref=0
$p2->name = "lisi";				
xdebug_debug_zval('p1');		// p1:refcount=2, is_ref=0
// 按道理应该执行 COW 机制复制出一块空间才对,
// 但是 p1 的内存空间还是 2,p1 和 p2 还是指向一个空间,
// 同时 p1->name 也被改成“lisi”,说明 p1 和 p2 现在改的都是同一个空间
// 对象有对象的特殊性,本身不会进行空间的复制
// 如果要复制,要用到 clone
  • 同类问题
// 程序执行时,每一次循环后变量 $data 的值是什么?
// 程序执行完成后,$data 的值是什么?
<?php
$data = ['a', 'b', 'c'];
foreach($data as $key => $val){
	$val = &$data[$key];
	var_dump($data);
}
var_dump($data);
// 思路,第 1 次循环:
// $key = 0; $val = 'a'; $val = &$data[0] = 'a'; 结果:abc
// 第 2 次循环:$key = 1; $val = 'b'; => $data[0] = 'b'; $val = &$data[1] = 'b'; 结果:bbc
// 第 3 次循环:$key = 2; $val = 'c'; => $data[1] = 'c'; $val = &$data[2] = 'c'; 结果:bcc

// array(3) { [0]=> &string(1) "a" [1]=> string(1) "b" [2]=> string(1) "c" } 
// array(3) { [0]=> string(1) "b" [1]=> &string(1) "b" [2]=> string(1) "c" } 
// array(3) { [0]=> string(1) "b" [1]=> string(1) "c" [2]=> &string(1) "c" }
// array(3) { [0]=> string(1) "b" [1]=> string(1) "c" [2]=> string(1) "c" }

2. 常量及数据类型;

问题:PHP 中字符串可以使用哪三种定义方法以及各自的区别是什么?

涉及 PHP 的字符串的定义方式以及各自区别
定义方式:单引号、双引号、heredoc 和 newdoc (定界符)
单引号区别:
‐ 单引号不解析变量
‐ 单引号不能解析转义字符,只能解析单引号和反斜线本身
‐ 变量和变量、变量和字符串、字符串和字符串之间可以用“.”连接
单引号效率更高
双引号区别:
‐ 双引号可以解析变量,变量可以使用特殊字符和 {} 包含
‐ 双引号可以解析所有转义字符
‐ 也可以使用“.”连接
heredoc 和 newdoc 区别:
‐ heredoc 类似于双引号
‐ newdoc 类似于单引号
‐ 两者都是用来处理大文本
$str = 'a b c d e f $a g';
$str = "a b c d e f '{$a}' g h";	// “{}”不会返回,返回 a b c d e f '$a的值' g h
$str = "a b c d e f '$a' g h";		// 同上
$str = "a b c d e f & $a & g h";	// “&&”会返回,返回 a b c d e f & $a的值 & g h

$sql = "SELECT * FROM user WHERE name = '$name'";
// 最外层双引号,里面单引号包含了一个变量,变量原样输出,就是单引号变量的值
// 但是双引号效率低,建议如下写法
$sql = 'SELECT * FROM user WHERE name = \''.$name.'\'';

// 关于 heredoc 和 newdoc
// 定义一个字符串,非常长,使用 heredoc
$str = <<< EoT
.
. // 字符串内容
.
EoT	// 开头和结尾保持一致

// newdoc,类似单引号,里面的内容不会被解析
$str = <<< 'EoT'
.
. 
.
EoT	
延伸:数据类型以及常量
三大数据类型(标量,复合,特殊)
标量里有浮点、整型、字符串、布尔
复合是数组和对象
特殊数据类型:NULL 和 resource(资源)
// 浮点类型不能运用到比较运算中(不能运用到精确相等判断里)
$a = 0.1; 
$b = 0.7; 
if($a + $b == 0.8){
	// 这里不会进入,因为是不相等的
	// 因为 0.1 和 0.7 在计算的时候是交给 CPU 计算
	// CPU 在计算的时候只能把它转化为二进制,在二进制的时候就会有一定的损耗
	// 所以0.1 + 0.7 最终结果是 0.79999999
}

// 布尔类型需要知道 false 的七种情况(什么时候判断为 false)
// 整型0,浮点0.0,空字符串,0字符串,布尔false,空数组、NULL
0 , 0.0 , '' , '0' , false , array() , NULL

// 数组类型:超全局数组
// $GLOBALS,$_GET,$_POST,$_REQUEST,$_SESSION,$_COOKIE,$_SERVER,$_FILES,$_ENV
// $GLOBALS 包含后面所有的内容
// $_REQUEST 包含 $_GET,$_POST,$_COOKIE
// $_REQUEST 少用,因为是万能钥匙所以不安全
// 重点:$_SERVER
$_SERVER['SERVER_ADDR']		// 服务器端 ip 地址
$_SERVER['SERVER_NAME']		// 服务器名称
$_SERVER['REQUEST_TIME']	// 请求时间		
$_SERVER['QUERY_STRING']	// 请求地址“?”后面的字符串,有可能为空
$_SERVER['HTTP_REFERER']	// 上级请求页面,可能为空
$_SERVER['HTTP_USER_AGENT']	// 返回头信息里的 USER_AGENT 信息
$_SERVER['REMOTE_ADDR']		// 客户端 ip 地址
$_SERVER['REQUEST_URI']		// 访问 index.php 则为 /index.php
$_SERVER['PATH_INFO']		// 处理路由,框架里一些路由的功能,抓 url 地址路径的部分,去掉域名和"?"后面的部分,比如:/user/login

// NULL
// 三种情况:直接赋值为 NULL、未定义的变量、unset() 销毁的变量

// 常量
// 定义的方式:const、define()
// const 更快,是语言结构,define() 是函数
// define 不能用于类常量的定义,const 可以
// 常量一经定义,不能被修改,不能被删除

// 预定义常量
// __FILE__,__LINE__,__DIR__,__FUNCTION__,__CLASS__,__TRAIT__,__METHOD__,__NAMESPACE__
__FILE__		// 文件的路径名和文件的名称
__LINE__ 		// 所在行的行号
__DIR__ 		// 所在目录
__FUNCTION__ 	// 所在的函数体的函数名称
__CLASS__ 		// 类名
__TRAIT__ 		// trait 的名称
__METHOD__ 		// 类名加方法名
__NAMESPACE__ 	// 返回命名空间名称

3. 运算符;

问题:foo() 和 @foo() 之间的区别

PHP 的运算符的 错误控制符 @
PHP支持一个错误控制符:@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都会被忽略掉。
  • 延伸:PHP 所有运算符
运算符的优先级
官方文档: https://www.php.net/manual/zh/language.operators.precedence.php
递增 / 递减 > ! > 算术运算符 > 大小比较 > (不)相等比较 > 引用 > 位运算符(^) > 位运算符(|) > 逻辑与 > 逻辑或 > 三目 > 赋值 > and > xor > or
括号的适应可以增加代码可读性,推荐使用
比较运算符
==” 和 “ ===” 的区别
等值判断(FALSE)的七种情况
递增 / 递减运算符
递增 / 递减运算符不影响布尔值
递减 NULL 值没有效果,递增 NULL 值为 1
递增和递减在前就先运算后返回,反之就先返回后运算
逻辑运算符
短路作用
“||” 和 “&&”与 “or” 和 “and” 的优先级不同

4. 流程控制;

5. 自定义函数及内部函数 ;

6. 正则表达式;

7. 文件及目录处理;

8. 会话控制技术;

简述 cookie 和 session 的区别及各自的工作机制,储存位置等,简述 cookie 的优缺点

  • PHP 的会话控制技术
为什么要使用会话控制技术?
WEB 是通过 HTTP 协议来实现的,而 HTTP 协议又是无状态的协议。也就是说 HTTP 协议没有内建机制来维护两个事物之间的状态。所以同一个用户在请求相同界面两次的时候,HTTP 协议不会认为这两次请求都来自同一个用户,会把它当成是两次独立请求隔离开,认为是不同的两个人来请求的。如果用户执行了登录操作,再次请求页面,HTTP 协议不会认为该用户之前做过登录,因为它没办法保持该用户之前的登录状态,没办法在不同页面之间进行用户的跟踪和用户状态的保持。
对于用户会话控制技术来说就是为了解决这样一个问题。就是允许服务器跟踪同一个客户端做出的连续请求。这样就可以保持用户的状态,从而完成登录状态的一个保持
会话控制技术实现的方式
通过 GET 参数传递:但是信息不是特别安全,其次会参数丢失,不建议使用
Cookie:它是一种由服务器发送给客户端的片段信息,存储在客户端浏览器的内存或者是硬盘当中的技术。就是存储在客户端(用户浏览器)里的一个文件,这个文件包含了客户端的一些片段信息。
‐ 比如用户去超市购买完东西办理了会员卡。超市就是服务器,用户就是客户端,会员卡就是 Cookie。Cookie 存储了用户的基本信息。基本信息就是用户的状态信息。用户登录就会把登录状态保存在 Cookie 文件里。
Cookie 的操作:见下
Cookie 的优点和缺点:
‐ 将信息存储在客户端,不会占用服务器资源,效率高。
‐ 缺点也是将信息存储在客户端,所以不建议将一些敏感的信息保存在 Cookie 中。
‐ 而且用户有权限禁止浏览器 Cookie 的使用,一旦用户禁止,就无法保存用户信息。
Session:是将使用者的资料存储在服务器中。这样用户无法禁用 Session 的使用。但是 Session 并不是完全脱离 Cookie 的,而是基于 Cookie 的。
比如说用户还是去超市。用户也办了会员卡,但是会员卡是一张电子卡,每次要说明会员的身份证号,就可以给该会员进行打折优惠。这里超市还是服务器,用户还是客户端,但是对于会员卡来说,因为没有实质的会员卡,拿到的是一个电子卡,会员卡信息依然是用户状态的信息,但是会员卡信息是存储在服务器的,与 Cookie 不同的是,电子卡是由服务器端进行保存的,是由超市进行保存的。用户每次过来的时候只需要报身份证号,这个身份证号就是 SessionID,这个 SessionID 是存储在 Cookie 里的,如果 Cookie 被禁用,可以通过 URL 来传递 SessionID,来保存一个 Session 的状态。所以 Session 是基于 Cookie 的。Session 是存在服务器端的一个文件里。 每当用户想要读取 Session 内容的时候,首先他会拿浏览器中携带的 SessionID 的 Cookie 文件,根据 SessionID 找到对应的 Session 文件,然后讲内容读取出来。这就是 Session 的工作原理。
Session 的操作:见下
Session 的优点和缺点:
‐ 信息非常安全,都是存储在服务器端,客户端拿不到信息
‐ 缺点就是消耗服务器资源
传递 SessionID 的问题:Session 是基于 Cookie 的,Cookie 里面存储了 SessionID,如果把浏览器 Cookie 禁用,那 SessionID 没有办法传递了。那怎么办?session_name() 和 session_id() 去进行传递,见下。
Session 存储:在服务器配置集群的情况下,建议不要以文件的形式存储 Session,把 Session 存储到内存服务器里。
‐ session_set_save_handler(),存 MySQL,Memcached,Redis 等。
// cookie 的操作:
//创建 cookie
setcookie($name, $value, $expire, $path,  $domain, $secure);
setcookie('a[b]', 'val');	// 存数组
$_COOKIE					// 读取 cookie(只读)
setcookie($name, '', time()-1000);	// 删除 cookie

// Session 的操作
session_start();	// 创建 Session
$_SESSION;			// 操作 Session
$_SESSION = [];		// 清空 Session
session_destroy();	// 删除 Session 以及对应的 SessionID 的 Cookie

// 关于 Session 的配置信息(php.ini 中)
session.auto_start		// 是否自动开启 session_start();
session.cookie_domain	// 存储 SessionID 的 Cookie 的有效域名
session.cookie_lifetime
session.cookie_path
session.name			// 默认是 PHPSESSID,可以改
session.save_path		// Session 在服务器中存储的路径
session.use_cookies		// 是否用 Cookie 传递 SessionID
session.use_trans_sid
// Session 垃圾回收机制,三者配合使用
// 如果用户直接关闭浏览器不退出,Session 会永久保存在服务器里
// 这个时候就会配置一些垃圾回收,把 Session 文件定时清理掉
// 每 100 次调用 session_start() 的时候,会有 1 次去清理文件
// 什么样的文件?就是当前时间的时间戳减去最后文件修改的时间超过 1440 秒的,
// 说明这个文件已经过期了,要清楚掉
// 如果 session.gc_divisor=1,就是每次 session_start() 都会清理过期文件
// 不建议把 session.gc_divisor 配置的特别小,会消耗服务器资源
session.gc_probability=1
session.gc_divisor=100
session.gc_maxlifetime=1440	// Session 最大生命周期,超过清理

session.save_handler	// Session 存储的句柄(也可以存储到 Memcached,Redis 等)

// 传递 SessionID 的问题
// session_name() 和 session_id() 
// <a href="1.php?PHPSESSID=sessionID的值">下一个页面</a>
// sessionID的值就是文件名称:sess_[sessionID的值]
<a href="1.php?<?php echo session_name().'='.session_id(); ?>">下一个页面</a>
// session_name() 就是配置里 session.name 的值,默认的 PHPSESSID
// session_id() 就是登录以后生成的新的 Session 文件的 ID 的值

<a href="1.php?<?php echo SID; ?>">下一个页面</a>
// SID 就是 session_name() 和 session_id() 的拼接
// 但是 SID 有一个特性,就是如果开启了 Cookie,SID 就是空;如果 Cookie 禁用才会有值,很智能。

9. 面向对象;

问题:写出 PHP 类权限控制修饰符

public、protected、private
public:修饰的成员有最高权限,可以在类的内部使用、外部使用、子类中使用
protected:类的内部使用、子类中使用(被继承)、不可以在类的外部使用
private:权限最小,只能在类的内部使用,不能被继承、不允许在外部使用
  • 延伸 1:面向对象的封装、继承和多态
成员访问的权限
public、protected、private 分别在类的内部,子类,类的外部的访问权限
单一继承
PHP 是单一继承,同时只能继承一个类。
如果有接口(interface)的话,可以继承一个类,继承一个接口。也可以实现多个接口。
以上参考 抽象类和接口
方法重写
父类中定义一个方法,子类继承父类的时候,如果方法名称相同会覆盖掉
如果不想覆盖的话,可以延伸(parent::父类)
在这里插入图片描述
面向对象的多态
抽象类的定义:在类的前面使用 abstract。
如果类当中有抽象方法,类必须定义为抽象类
如果类当中没有抽象方法,类也可以定义为抽象类
接口的定义:里面的方法都是抽象的,没有方法体(大括号)
定义好方法,等着后面来实现。(参考: 抽象类和接口
  • 延伸 2:魔术方法
    • __construct()、__destruct()、__call()、__construct()、__callStatic()、__get()、__set()、__isset()、__sleep()、__wakeup()、__toString()、__clone()
  • 延伸 3:设计模式
    • 常见设计模式:工厂模式、单例模式、注册树模式、适配器模式、观察者模式和策略模式

10. 网络协议;

问题:HTTP/1.1 中,状态码 200、301、304、403、404、500 的含义

HTTP 状态码
HTTP 状态码负责客户端 HTTP 请求的返回结果,标记服务器端的处理是否正常,通知出现的错误。状态码的职责是当客户端向服务器端发送请求的时候,描述返回的一个请求结果。借助状态码,用户可以知道服务器端是否正确的处理了请求。
状态码的五类响应:1XX、2XX、3XX、4XX、5XX
1XX 类的是信息类状态码,它主要接收请求,表示接受请求正在处理。
2XX 类的表示 Success,是成功类状态码。它代表的意思是请求正常处理完毕。
3XX 类的是重定向,redirection。它代表的意思是需要进行附加操作以完成请求。
4XX 类的是 client error,客户端错误,服务器无法完成请求。
5XX 类的是 server error,服务端错误,服务器处理请求出错。
  • 延伸 1:OSI 七层模型
  • 延伸 2:HTTP 协议的工作特点和工作原理
  • 延伸 3:HTTP 协议常见请求 / 响应头和请求方法
  • 延伸 4:HTTPS 协议的工作原理
  • 延伸 5:常见的网络协议和端口

11. 开发环境及配置。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值