PHP知识整理
一、列举一些PHP的设计模式
- 单例模式:保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个,同时这个类还必须提供一个访问该类的全局访问点。
- 工厂模式:定义一个创建对象的接口,但是让子类去实例化具体类。工厂方法模式让类的实例化延迟到子类中。
- 观察者模式:观察者模式有时也被称作发布/订阅模式,该模式用于为对象实现发布/订阅功能:一旦主体对象状态发生改变,与之关联的观察者对象会收到通知,并进行相应操作。
- 适配器模式:适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
- 依赖注入模式:依赖注入(Dependency Injection)是控制反转(Inversion of Control)的一种实现方式。要实现控制反转,通常的解决方案是将创建被调用者实例的工作交由 IoC 容器来完成,然后在调用者中注入被调用者(通过构造器/方法注入实现),这样我们就实现了调用者与被调用者的解耦,该过程被称为依赖注入。
- 门面模式:门面模式(Facade)又称外观模式,用于为子系统中的一组接口提供一个一致的界面。
二、单例模式代码示例
三、PHP7 和 PHP5 的区别,具体多了哪些新特性?
- 性能提升了两倍
- 增加了结合比较运算符 (<=>) , 以及 ?? 等。
- 增加了标量类型声明、返回类型声明
try...catch
增加多条件判断,更多 Error 错误可以进行异常处理 Error 和 Exception 的捕获手段不同- 增加了匿名类,现在支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。
为什么性能提升了2倍?
- 变量存储字节减小,减少内存占用,提升变量操作速度
- 改善数组结构,数组元素和 hash 映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率
- 改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率(在vm栈中的指令send_val和recv参数的指令是相同,PHP7通过减少这两条重复,来达到对函数调用机制的底层优化)
四、web常见的攻击手段
1. CSRF 跨站伪造请求
盗用用户身份,欺骗服务器,完成攻击请求。
防范手段: 使用验证码, 为每个请求添加token验证。
2. XSS 攻击 跨站脚本攻击。
攻击者往页面里嵌入恶意js代码,攻击用户。
防范手段: 核心就在于,永远不要相信用户的输入数据,始终对用户输入的数据保持过滤。
3. SQL注入 攻击者在提交数据等场景 提交了一些非法的sql,导致数据库被注入大量垃圾数据,运行缓慢。或者暴露系统隐私数据。
防范手段:核心依然在于永远不要相信用户输入的数据,不要使用动态拼装的sql,对隐私数据加密,禁止明文存储。
其次,可以借助php.ini 里的一个配置magic_quotes_gpc = on 开启用户提交对查询时的字符转义 比如把'转义成\。 或者使用其他自定义函数进行过滤。
Laravel 防sql注入相关策略:
五、框架相关-Laravel的服务容器
DI 依赖注入 所需要的依赖类都通过参数的形式传入。
IOC 控制反转 将依赖类的控制权交出去,由主动变为被动。
参考大佬文章 https://learnku.com/articles/19195
laravel 和 tp 的区别:
1.tp 5以前不支持composer。
2.tp 路由和文件名称位置绑定。 laravel重路由,有专门的路由文件。
3.laravel 在表单里提交时有对csrf攻击的防护处理,tp完全需要自己编写相应逻辑。
4.tp没有原生中间件层。
5.tp里没有.env这种灵活的系统配置。
六、四大排序算法实现
// 冒泡排序 function mpSort($a = []){ $count = count($a); if($count <= 1){ return $a; } for($i = 0; $i < $count; $i++){ for($j = $count - 1; $j > $i; $j--){ if($a[$j] > $a[$i]){ $tmp = $a[$j]; $a[$j] = $a[$i]; $a[$i] = $tmp; } } } return $a; } //快速排序 function ksSort($a = []){ $count = count($a); if($count <= 1){ return $a; } $aLeft = $aRight = []; $nTarget = $a[0]; for($i = 1; $i < $count; $i ++ ){ if($a[$i] > $nTarget){ $aRight[] = $a[$i]; }else{ $aLeft[] = $a[$i]; } } $aLeft = ksSort($aLeft); $aRight = ksSort($aRight); return array_merge($aLeft, [$nTarget], $aRight); } //选择排序 function selectSort($a = []){ $count = count($a); if($count <= 1) { return $a; } for($i = 0; $i < $count -1; $i ++) { $min = $i; for($j = $i + 1; $j < $count ; $j++) { if($a[$j] < $a[$min]){ $min = $j; } } if($min != $i){ $tmp = $a[$min]; $a[$min] = $a[$i]; $a[$i] = $tmp; } } return $a; } // 插入排序 function insertSort($a = []){ $count = count($a); if($count <= 1){ return $a; } for($i = 1; $i < $count; $i ++){ for($j = $i; $j > 0; $j--){ if($a[$j - 1] > $a[$j]){ $tmp = $a[$j - 1]; $a[$j-1] = $a[$j]; $a[$j] = $tmp; } } } return $a; }
//二分查找普通
function halfSelect($arr , $target){
$count = count($arr);
if($count <= 0 || !is_numeric($target)){
return false;
}
$i = 0;
$j = $count -1;
while($j >= $i){
$tmp = floor(($i + $j) /2);
if($arr[$tmp] == $target){
return true;
}
if($arr[$tmp] < $target){
$i = $tmp + 1;
}
if($arr[$tmp] > $target){
$j = $tmp - 1;
}
}
return false;
}
七、static关键字
1. static 修饰的变量和方法创建后,始终使用同一块内存。 而实例的方式,会创建多块内存。
2.static 修饰的变量和方法,不需要实例化类即可调用。 实例化类时,不会再次声明 static 修饰的属性。
3. 效率上讲, static要比普通实例化的方法高一些。 但是static的不会自动销毁, 实例化的方法会随着实例自动销毁。
引用一段话,说明下static 使用场景。
八、interface 工厂模式、抽象类相关
PHP的工厂模式大多采用interface去做,interface里的方法必须是public的,并且不能带函数体。
当interface的子类实现接口函数时,如果不想开发全部的函数实体,可以采用抽象类中转实现interface,再由子类继承抽象类来做,将子类不想实现的函数在抽象类中定义为普通函数(必须带函数体),不加abstract修饰。 加abstract修饰的函数不能带函数体。
// 抽象类 or 接口挺相似的作用。使用场景主要由子类是否是一些关联性比较强的类,如果是,就使用抽象类。 不是 就使用接口。 再有就是看 子类是不是需要实现多个接口以及静态成员变量之类的。
<?php 2 3 // 工厂interface 4 interface FactoryTest{ 5 public function getName(); 6 public function getPrice(); 7 } 8 // 手机抽象类 9 abstract class Mobile implements FactoryTest{ 10 abstract public function getName(); 11 public function getPrice(){ 12 13 } 14 } 15 // 手机品牌子类 16 class Apple extends Mobile{ 17 public function getName(){ 18 echo 'Iphone'; 19 } 20 } 21 22 23 $obj = new Apple(); 24 echo $obj->getName();