总结一些编码过程中可能忽略但在面试经常提及的细节点,那接下来我们就一起了解一下
有关类(class)的知识点
1,在类中self与static调用静态方法的区别
self:调用的是当前类(不是访问的当前类,而是self代码所在类中)的静态方法
static:调用的是访问当前类所在的静态方法。
// 父类定义
class StaticParentController extends Controller
{
/**
* @notes 静态测试方法
*/
public static function say(){
echo "parent-static-method-say";
}
/**
* @notes self 调用
*/
public function actionCallSelf(){
self::say();
}
/**
* @notes new static() 调用
*/
public function actionCallStatic(){
static::say();
}
}
// 子类继承父类并进行重构
class StaticSonController extends StaticParentController
{
/**
* @notes 静态测试方法
*/
public static function say(){
echo "son-static-method-say";
}
}
// 调用实例
staticParent/callself() ---parent-static-method-say
staticParent/callstatic()---parent-static-method-say
staticSon/callself() ---parent-static-method-say
staticSon/callstatic() ---son-static-method-say
2,类中常量不可重新赋值
const 定义的常量尽可能定义初始值,因为const不能赋值
注:define定义的常量重新赋值后也是原始值
3,class 实现多继承
php 类本身不支持多继承,只支持单继承。但可以使用trait来实现。
关键词是 trait,调用关键词 use, 调用多个类中 , 号隔开
trait 类中不区分修饰符(public,protected,private),当被外部类调用时不区分属性类别都可调用
trait 使用事项:
,trait 类 命名必须为 trait className。
,调用 trait 类使用 use,多个类之间用,号隔开。
,类中重名方法优先级【trait class,自身类,继承类】
自身类 > trait class > 继承类
,当调用的trait中出现重名的方法时,需定义使用那个方法 或者 进行方法的别名设置
例子:trait A 与 trait B 中都含有 getInfo 方法。此时就需要处理
定义使用那个方法
A::getInfo insteadof B 含义 当使用getInfo方法时,使用类A而不使用类B
定义方法别名
B::getinfo as getInfoV1 含义 为B类中的getinfo方法定义别名为 getinfov1
,trait class 不能被实例化
协程
//协程关键字:
go()
// 基础方式
go(function (){
})
// 调用已有的函数
function goCallback()
{
}
go('goCallback')
// 调用已有类中的函数
// attention: 必须是可访问的方法(公共)
go([$this, 'goCallback'])
or
go('className::someStaticMethod')
编码格式转换
,header头部转换
header("content-Type:text/html;charset=utf-8")
,具体某个字符串转换
mb_convert_encoding(str, '转换成那种编码格式', '当前编码格式')
iconv('当前编码','将要转换的编码','字符串')
,整个页面转换
mb_internal_encoding('网站当前的编码 ');
mb_http_output();
ob_start('mb_output_handler');
替换字符串
,★ strtr()
含义:根据指定字符进行匹配替换(一对一)
eg :
str = 'hello world';
字符串替换
strtr(str, 'eo', '12')
将字符串str中字符为e的替换为1,字符为o的替换为2
echo res: h1ll2, w2rld
数组替换,根据数组键名(key)替换成对应的value(键值)
arr = array('hello'=>'hi', 'world'=>'girl')
strtr(str, arr);
echo res : hi girl
, str_replace();
$str = 'I hello world';
// 字符串替换
// 将指定的字符串进行替换,一个被替换字符串是一个整体而不是整体字符串中的某个字符
$ret = str_replace( 'hello', 'hi', $str);
echo $ret;
echo PHP_EOL;
// 数组替换, 批量替换,
// 不必一对一,函数只对满足一对一的替换值与被替换值 操作
$replaceArr = array('hello', 'world'); // 被替换字符串 合集
$normal = array('hi', 'girl'); // 替换后值字符串合集
$ret = str_replace($replaceArr , $normal, $str);
echo $ret;
echo PHP_EOL;
// 字符 + 数组 替换
// 将被替数组中的全部元素都进行替换操作
$replaceArr = array('hello', 'world');
$normalStr = 'girl';
$ret = str_replace($replaceArr, $normalStr, $str);
echo $ret;
echo PHP_EOL;
数组相关
1,数组融合:
array_merge()与+ 融合的区别
array_merge:融合数组中key相同的话,后者替换前者
+:融合数组中key相同的话,后者不替换前者
//在这里插入代码片
$arr_A = array('a1'=>'a','b1'=>'b','c1'=>'c','d1'=>'d','e1'=>'e');
$arr_B = array('g1'=>'g_1','h1'=>'h_1','a1'=>'a_1','b1'=>'b_1','c1'=>'c_1','d1'=>'d_1','e1'=>'e_1','f1'=>'f_1 ');
print_r
$arr_A+$arr_B:
Array ( [a1] => a [b1] => b [c1] => c [d1] => d [e1] => e [g1] => g_1 [h1] => h_1 [f1] => f_1 )
array_merge($arr_B, $arr_A):
Array ( [g1] => g_1 [h1] => h_1 [a1] => a [b1] => b [c1] => c [d1] => d [e1] => e [f1] => f_1)
2,数组排序
2.1,array_multisort(): 一维, 二维数组排序(常用二维数组)
param1: 要排序的数组,
param2: 排序的类型(SORT_ASC, SORT_DESC)
param3: 要给予param1排序的数组
注: param1, oaram2 参数可重复
2.2,排序后键民与键值是否还保持原有规则
保持
asort -- 键值 升序
arsort -- 键值 降序
krsort -- 键名 降序
ksort -- 键名 升序
不保持
rsort -- 键值 降序
sort -- 键值 升序
$arr = [
[
'name' => '小王',
'age' => 11,
],
[
'name' => '小李',
'age' => 13,
],
[
'name' => '小张',
'age' => 10,
],
];
$ageArr = array_column($arr, 'age');
array_multisort($ageArr, SORT_DESC, $arr);
// 输出结果为, $arr关于age字段降序的新数组
3,数组运算符
$a == $b $a,$b 键 值 | 名 相同的话返回 true.
$a === $b $a,$b 键 值 | 名 相同的话(数据类型)返回 true.
$a !=||<> $b $a,$b 键 值 | 名 不相同的话返回 true.
运算符相关
注:符号运算符可能因精度不精确导致计算有误(+,/,*,-),故数学符号计算时推荐用php本身自带函数
加法:bcadd($stra,$strb,scale);
$stra:被加数
$strb:加数
$scale 保留几位小数。默认为0
减法:bcsub($stra,$strb,scale);
$stra:被减数
$strb:减数
$scale 保留几位小数。默认为0
乘法:bcmul($stra,$strb,scale);
$scale 保留几位小数。默认为0
除法:bcdiv($stra,$strb,scale);
$stra:被除数
$strb:除数
$scale 保留几位小数。默认为0
取余:bcmod($stra,$strb,scale);
$stra:被除数
$strb:除数
$scale 保留几位小数。默认为0
绝对值:abs()
幂函数:pow(stra,strb)
param:
stra:底数
strb:幂数
数组执行时间相关
1,foreach, array_map 执行时间对比
由于array_map 下发不同所占用的执行时间也不同,foreach 鉴于array_map 写法之间, 但array_map 占用的内存会比较少
算法关键词
1,回文串
从左往右,从右往左 字符串内容都一致,也就是手尾字母层层相等
eg: raceecar
2,字母异位词
不同字符中 所包含的字符一致且字符中每一个个数相同
anagram ,tnagaram
内存相关
1,传值与传引用
传值:PHP默认赋值方式,一个变量赋给另一个变量且更改其更改某一个变量不影响赋值的其他变量。
传引用:引用赋值,目标变量直接指向被赋值变量内存,更改其中一个变量同时影响全部变量。(关键词 :&)
注:使用大量的数据时尽量用引用赋值可以节省内存
header 注意事项
,自定义header注意事项
php中定义的key会自动转成大写
key中只能含有字母,数字,中划线(-)且中划线会被自动转换成下划线(_)
自定义的key的前缀会被加http_
eg :
name -> HTTP_NAME
user-name -> HTTP_USER_NAME
user_name -> 接收不到
composer
,查看composer 绑定的php版本
composer show --platform
,安装指定版本
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
// hash 值需要在官网找到 sha384 加密的值
php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
// --version 指定版本
php composer-setup.php --version=x.x.x
// 将composer.phar 复制到 /usr/local/bin/目录下并改名
cp composer-setup.php /usr/local/bin/composer
网络编程(socket)
PHP对socket操作提供两种类型且两者互不兼容,分别为 socket,stream_socket,其中一个socket资源,一个是stream资源
两者使用区别:
socket_*
、socket_create 创建的socket更底层,类似于C语言的socket接口,使用起来比较麻烦。
、操作底层socket必须使用 socket_* 系列函数,无法使用stream类型的函数,比如无法使用fread、fwrite,自然也无法使用stream
相关的过滤器、streamWrapper、SSL加密等。
、使用 socket_* 系列函数必须安装socket扩展。
、使用 socket_* 系列函数的优点是可以设置很多socket选项。
stream_socket_*
、stream_socket_server 是PHP自带的接口,无需安装任何扩展。
、stream_socket_server 接口使用非常简单,比如创建一个socket监听服务,socket_* 需要好多行代码才能搞定,但是
stream_socket_server只需一行就搞定了。
、stream_socket_server 创建的socket属于stream类型,可以用stream相关的函数操作,fread、fwrite等等。
也可以使用stream相关的高级特性,过滤器、streamWrapper、SSL加密等。
、stream_socket_* 系列函数的缺点是很多socket选项无法精确设置。所以当 stream_socket 无法完成精确设置的时候,可以借助
socket_import_stream将stream_socket转换成底层sockets,然后就可以通过socket_set_option设置stream_socket的
socket选项了。
抓取远端内容
,方法1
,file();
,方法2
,file_get_content()
,方法3
$resourse = fopen();
$content = '';
do{
$data = fread($resourse, 1024);
if (strlen($data) == 0){
break;
}
$content .= $data
}while(true)
fclose($resourse);
,方法4(效率最高)
curl 获取
$ch = curl_init();
curl_setopt(ch);// 相关参数配置
$ret = curl_exec($ch);
curl_close(ch); // 关闭
var_dump($ch );
,方法5(不常用)
socket 获取
注:
在用文件函数抓取页面内容时 会导致内存以及cpu上升(一段时间内增长较快)
匿名函数,闭包函数
匿名函数,也叫闭包函数 允许临时创建一个没有知道名称的函数。最经常用作回调函数参数的值,
常见用法
$message = 'hello world';
,传值(局部变量)
$explode = function () use ($message){
var_dump($message);
};
$explode();
,引用传值(全局变量)
$explode = function () use (&$message){
var_dump($message);
};
$explode();
,父级别方法赋值
$explode = function ($org) use (&$message){
var_dump($org.'--'.$message);
};
$explode('hi ');
攻击相关
1,web端攻击相关
1.1,xss攻击(跨站脚本攻击)
攻击原理:在web端传入js脚本,比如在文本框中输入"alert('xss')" 并提交,服务端未检测进行数据保存,当在信息再次被打开时
便会弹框。
攻击类型:反射性,存储型,DOM-based型。
存储型:
攻击方式:增加恶意链接
攻击步骤:
1. 攻击者在url后面的参数中加入恶意攻击代码。
2. 当用户打开带有恶意代码的URL的时候,网站服务端将恶意代码从URL中取出,拼接在html中并且返回给浏览器端。
3. 用户浏览器接收到响应后执行解析,其中的恶意代码也会被执行到。
4. 攻击者通过恶意代码来窃取到用户数据并发送到攻击者的网站。
5. 攻击者会获取到比如cookie等信息,然后使用该信息来冒充合法用户的行为,调用目标网站接口执行攻击等操作。
存储型:
攻击方式:输入恶意js代码
攻击步骤:
1. 攻击者将恶意代码提交到目标网站数据库中。
2. 用户打开目标网站时,网站服务器将恶意代码从数据库中取出,然后拼接到html中返回给浏览器中。
3. 用户浏览器接收到响应后解析执行,那么其中的恶意代码也会被执行。
4. 那么恶意代码执行后,就能获取到用户数据,比如上面的cookie等信息,那么把该cookie发送到攻击者网站中,
那么攻击者拿到该cookie然后会冒充该用户的行为,调用目标网站接口等违法操作。
DOM-Based:
攻击方式:原文内容直接输出
攻击步骤:更改代码增加输出页面代码,如:document.innerHtml, document.href,document.write
SQL注入
攻击方式:输入恶意语句
攻击步骤:
输入框输入非法sql语句
1.2,scrf攻击
1.3,ssrf攻击(伪造服务器请求)
攻击方式:通常用于控制web进而探测内网服务以及攻击内网脆弱应用
常见方式:
url地址拼接参数
url?dict://127.0.0.1:6379 | url?ftp://127.0.0.1:21
攻击原理:服务端用读取远程资源的函数执行时,伪造内网ip与端口访问内部资源
1.4,ddos 攻击