答:
- php 版本1.0 1995-06-08
- php 版本5.6 2014-08-28
- php 版本7.0 2015-12-03
- php 版本7.1 2016-12-01
- php 版本7.2 2017-11-30
- php 版本7.3 2018-12-06
- php 版本8.1 2021-11-25
-
- php5与php7之间的区别:
-
- 1、性能提升:PHP7比PHP5.0性能提升了两倍。
- 2、以前的许多致命错误,现在改成抛出异常。
- 3、PHP 7.0比PHP5.0移除了一些老的不在支持的SAPI(服务器端应用编程端口)和扩展。
- 4、PHP 7.0比PHP5.0新增了空接合操作符,增加了空结合操作符(??),相当于三元运算符
- 5、PHP 7.0比PHP5.0新增加了结合比较运算符。
- 6、PHP 7.0比PHP5.0新增加了函数的返回类型声明。
- 7、PHP 7.0比PHP5.0新增加了标量类型声明。
- 8、PHP 7.0比PHP5.0新增加匿名类。
- 9、错误处理和64位支持
- 如果您了解错误和异常之间的区别,那么您就会知道在PHP 5中处理致命错误非常不容易。PHP7简化了流程,因为它已用可以轻松处理的异常替换了几个主要错误。这是通过引入新的引擎异常对象实现的。
- 您可能已经知道,PHP 5不支持64位整数或大文件,但PHP 7中的情况已发生变化。PHP7具有64位支持,因此您也可以使用本机64位整数作为大文件,因此,您可以在64位系统体系结构上完美运行应用程序。
- 10、声明返回类型
- 在PHP 5中,程序员无法定义函数或方法的返回类型。在现实生活中,这是一个巨大的缺点,因为程序员无法防止意外的返回类型并在其他情况下生成异常。
- 幸运的是,PHP 7允许程序员根据期望的返回值声明函数的返回类型。这肯定会使代码健壮和准确。有四种不同的返回类型可用-bool,int,string和float。
-
- 为什么 PHP7 比 PHP5 性能提升了?
- 1、变量存储字节减小,减少内存占用,提升变量操作速度
- 2、改善数组结构,数组元素和hash映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率
- 3、改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率
-
- PHP8 新特性
- 1、新增对联合参数
- 联合参数使一个变量有多个类型值 ,而不是一个(参考c语言中的联合类型参数就很好理解)
- 2、新增weakmap新特性
- WeakMap 允许你创建对象到任意值的映射(类似 SplObjectStorage),同时也不会阻止作为键的对象被垃圾回收。如果某个对象键被垃圾回收,对应键值对将从集合中移除。
- 这一新特性非常有用,因为这样一来,开发者就不必担心代码存在内存泄露了。大多数 PHP 开发者可能对此并不关心,但是当你编写长时间运行的进程时一定要提防这个问题,比如使用 ReactPHP 进行事件驱动编程时:有了 WeakMap 后,引用的对象会在失效时自动被垃圾回收。
- 3、新增 ValueError 异常
- PHP 8 引入了新的名为 ValueError 的内置异常类,它继承自 Exception 基类。每次当你传递值到函数时,如果是一个无效类型,则会抛出该异常,在 PHP 8 之前,这样的操作会导致警告。
- 4、重写方法时允许可变参数
- 当我们在子类重写父类方法时,任何数量的参数现在都可以被替换成可变参数,只要对应参数类型是兼容的即可
- 5、静态返回类型
- PHP 8 中可以使用 static 关键字标识某个方法返回该方法当前所属的类,即使它是继承的(后期静态绑定)
- 6、对象的类名字面量
- PHP 8 中可以使用 o b j e c t : : c l a s s 获 取 对 象 的 类 名 , 其 返 回 结 果 和 g e t c l a s s ( object::class 获取对象的类名,其返回结果和 get_class(object::class获取对象的类名,其返回结果和getclass(object) 一样
- 7、变量语法调整
- new 和 instanceof 关键字现在可以被用于任意表达式
- 8、Stringable 接口
- PHP 8 引入了新的 Stringable 接口,只要某个类实现了 __toString 方法,即被视作自动实现了 Stringable 接口(咋和 Go 接口实现有点像),而不必显式声明实现该接口
- 9、Trait 现在可以定义抽象私有方法
- 10、throw 现在可以被用作表达式
- throw 语句现在可以用在只允许表达式出现的地方,例如箭头函数、合并运算符和三元运算符等
- 11、参数列表中允许出现可选的尾部逗号
- 和数组中的尾部逗号类似,现在也可以在参数列表中定义一个尾部逗号
- 12、捕获异常而不存储到变量
- 现在可以编写 catch (Exception) 代码来捕获异常而不必将其存储到一个变量中
- 13、新增对 mixed 类型的支持
- PHP 8 引入了新的名为 mixed 的类型,该类型等价于 array|bool|callable|int|float|null|object|resource|string
- 14、新增对注解的支持
- 注解绝对是 PHP 8 引入的最大新特性之一,一开始理解起来可能有点困难(不过有 Java 基础的话会很简单)。简而言之,注解允许你添加元数据到 PHP 函数、参数、类等,这些元数据随后可以通过可编程方式获取,在 PHP 7 或者更低版本中实现类似功能需要解析代码注释块,而通过注解可以直接访问深度集成到 PHP 自身的这些信息。
- 15、新增构造函数属性提示支持
- 这个新特性只是一个语法简写而言,可以将属性声明和构造函数属性初始化合并到一起
- 16、新增 match 表达式支持
- match 表达式和 switch 分支语句类型,但是语义上更加安全并且可以直接返回值
- 17、新增对空安全运算符 ?-> 的支持
答:
-
- isset()函数一般用来检测变量是否设置。
- 格式: isset ( mixed $var [, mixed $... ] )
- 参数说明: $var:要检测的变量
- 返回值: 若变量不存在则返回 FALSE
- 若变量存在且其值为NULL,也返回 FALSE
- 若变量存在且值不为NULL,则返回 TURE
-
- empty()函数用来判断值为否为空。
- 格式: bool empty ( mixed var )
- 参数说明: $var:待检查的变量
- 返回值: 当 var 存在,并且是一个非空非零的值时返回 FALSE 否则返回 TRUE。
- 以下的变量会被认为是空的:
- "" (空字符串) 0 (作为整数的0) 0.0 (作为浮点数的0) "0" (作为字符串的0) NULL FALSE array() (一个空数组) $var; (一个声明了,但是没有值的变量)
答:
- 传值:是把实参的值赋值给行参 ,那么对行参的修改,不会影响实参的值
- 在php中传值的意思相当于复制,我将你的值复制给我,我可以随意改变复制之后的值,对你是不会产生影响的。
- 举例:
- $a = 1;
- $b = $a;
- echo $b.'
'; //1 - $b = 2;
- echo $a .'
'.$b; //1 2 - // 解释:将a的值赋给b,改变b的值,a的值不受影响。
-
- 传引用 :真正的以地址的方式传递参数传递以后,行参和实参都是同一个对象,只是他们名字不同而已对行参的修改将影响实参的值
- 在php中传引用用‘&’符号,是相当于我不仅将你的值赋给我,还将你的内存地址也复制过来了,那么我们两个任何一个改变,另外一个就跟着改变。
- 举例:
- $a = 1;
- $b = &$a;
- echo $b.'
'; //1 - $b = 2;
- echo $a .'
'.$b; //2 2 - // 解释:将a的值和内存地址赋给b,改变b的值,a的值也改变。
答:
- ==比较两个变量的值,不比较数据类型。
- ===比较两个变量的值和类型
- 举例:
- $a = '123'; string
- $b = 123; int
- 进行条件判断
- $a === $b //为假; 类型不一致
- $a == $b //为真; 变量值一致
答:
- 获取键则是:array_keys($array);
- 交换数组中的键值:array_flip($array);
- 判断数组中是否存在某个键:array_key_exits('php',$array);
- 向某数组的最后填充数据:array_push($array,'xxx','cccc');
- 将数组的第一个元素弹出,并且之后元素前移一位:array_pop($array);
- 返回两个数组中不同的地方,即求同存异:array_diff($array,$array2);
- 返回数组中相同的元素:array_diff_assoc($array,$array2);
- 将两个数组合并返回一个新的数组:array_merge($array,$array2);
- 从数组中取出任意一个单元:array_rand($array);
- 获取单元顺序相反的数组:array_reverse($array);
- 将数组中重复的值去除:array_unique($array);
答:
- array_flip() 函数用来交换数组中的键和值
-
- $trans = array("a" => 1, "b" => 1, "c" => 2);
- print_r(array_flip($trans));
- 如果同一个值出现了多次,那么最后一个键名将作为它的值,所有其他的都丢失了。
- Array
- (
- [1] => b
- [2] => c
- )
答:
- php多维数组去除重复值的方法:
- 1、使用“array_map('serialize', $arr)”将多维数组转换为以字符串形式的一维数组;
- 2、使用array_unique()去除一维数组中的重复值;
- 3、将去重后的一维数组重新转为多维数组。
-
- $t = array_map('serialize', $arr);
- //利用serialize()方法将数组转换为以字符串形式的一维数组
- $t = array_unique($t);
- //去掉重复值
- $new_arr = array_map('unserialize', $t);
- //然后将刚组建的一维数组转回为php值
- return $new_arr;
答:
- serialize:序列化 :把一个对象转成字符串形式, 可以用于保存
- unserialize: 反序列化:把serialize序列化后的字符串变成一个对象
-
-
- json_encode 和 json_decode JSON格式比serialize返回数据结果小。
- JSON格式是开放的、可移植的。其他语言也可以使用它。
-
- var_export 函数把变量作为一个字符串输出;
- eval把字符串当成PHP代码来执行,反序列化得到最初变量的内容。
-
- ddx_serialize_value函数可以序列化数组变量,并以XML字符串形式输出。
- XML标签字符较多,导致这种格式的序列化还是占了很多空间。
答:
- 封装:可以使类具有独立性和隔离性;保证类的高内聚。只暴露给类外部或者子类必须的属性和操作
- 继承:对现有类的一种复用机制。一个类如果继承现有类,则这个类将拥有被继承类的所有非私有特性
- 多态:是在继承基础上实现的,父类引用指向不同子类对象时,调用相同的方法,呈现出不同的行为
-
- oop七大设计原则? 开里依单接迪合
- 开闭原则:对扩展开放,对修改关闭
- 依赖倒置原则:面向接口编程,而不面向实现了类
- 接口隔离原则:为各个类提供所需的专用接口
答:
- 1、抽象类可以有属性、普通方法,接口不能有属性和普通方法;
- 2、抽象类中未必有抽象方法,接口中一定有抽象方法;
- 3、抽象类使用abstract关键字声明,接口使用interface关键字声明。
- 4、抽象类是用extends关键字让子类继承父类后,在子类实现详细的抽象方法。而接口则是用implements让普通类在类里实现接口的详细方法,且接口可以一次性实现多个方法,用逗号分开各个接口就可
- 抽象类:是基于类来说,其本身就是类,只是一种特殊的类,不能直接实例,可以在类里定义方法,属性。类似于模版,规范后让子类实现详细功能。
- 接口:主要基于方法的规范,有点像抽象类里的抽象方法,只是其相对于抽象方法来说,更加独立。可让某个类通过组合多个方法来形成新的类。
- 相同:
- 1、都是用于声明某一种事物,规范名称、参数,形成模块,未有详细的实现细节。
- 2、都是通过类来实现相关的细节工作
- 3、语法上,抽象类的抽象方法与接口一样,不能有方法体,即{}符号
- 4、都可以用继承,接口可以继承接口形成新的接口,抽象类可以继承抽象类从而形成新的抽象类
答:
- 一个类只能实现一个抽象类;但一个类可以实现多个接口,接口可以继承多个接口
答:
-
- 单例模式:保证在整个应用程序的生命周期中,单例类的实例只存在一个
- 私有化静态属性,私有化构造方法,私有化克隆方法,公有化静态方法。
-
- 工厂模式:定义一个创建对象的接口,让子类去实例化具体类。
- 观察者模式 发布/订阅模式:当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。
- 适配器模式:将一个类的接口转换成客户希望的接口,使得原本不兼容的接口可以兼容
- 依赖注入模式:是ioc的一种实现方式。用来减少程序中的耦合
答:Laravel生命周期_思维小刀的博客-CSDN博客_laravel的生命周期
答:注册加载composer自动生成的c lass loader ,就是加载初始化第三方依赖。
答:
- Laravel服务容器
- IoC (控制反转)
- DI (依赖注入)
-
- Laravel服务容器是-个用于管理类依赖和执行依赖注入的强大工具。
-
- IoC (控制反转)与DI (依赖注入)
- IoC (控制反转)与DI (依赖注入)是现在特别流行的概念,也是目前 降低软件开发复杂度;提升模块低耦合、高内聚所使用的-种设计模 式。
- 控制反转与IoC容器
- 控制反转:容器控制应用程序,由容器反向的向应用程序注入应用程序 所需要的外部资源;
- 控制反转是用来进行对象解耦。通过借助第三方 (IoC容器),将具有 依赖关系的对象进行解耦。
-
-
- 比如全体齿轮的转动由-个对象来控制,如类B。如下图所示:
-
-
-
- 引入了IoC容器后,对象A、B 、C、D之间没有了依赖关系,全体齿轮转
-
-
- 动的控制权交给IoC容器。这时候齿轮转动控制权不属于任何对象,而 属于IoC容器,所以控制权反转了,从某个对象转到了IoC容器。
-
-
-
-
- 依赖注入
- 依赖注入,首先依赖就是指-种关系,如果在类A中创建了类B的实例, 我们就可以说类A依赖类B。
-
-
-
- 例如:
- class B {
- public function func() {
- print_r(__CLASS__);
-
-
- }
- }
-
- class A {
- private $b;
-
- public function A() {
- $this->b = new B();
- }
-
- public function func() {
- $this->b->func();
- }
- }
- 而使用这种方式,则会出现以下问题:
- 问题1:如果现在要改变类B的创建方式,如需要用new B(String name)初始化B,需要修改类A中的源代码;
- 问题2:如果想测试不同B对象对A的影响很困难,因为B的初始化 被写死在了A的构造函数中;
- 问题3:如果要对类B的实例进行调试时,就必须在类A中对类B的 实例进行测试,增加了测试难度和复杂度;因为当出现问题时,不
- 知道是类A的问题 还是类B的问题。
- 基于此,提出以下的解决方案:
-
- class A {
-
-
- private $b;
-
- public function A() {
- $this->b = $bObj;
- }
-
- public function func() {
- $this->b->func();
- }
- }
- 将B对象实例作为类A的构造器参数进行传入,在调用类A构造器之前, 类B实例已经被初始化好了。像这种非自己主动初始化依赖,而通过外 部传入依赖对象的方式,就很完美的解决了上述的问题,这就是依赖注 入。
答:
Laravel 中的门面总体上还是遵循着门面模式的基本思想的。Laravel 中的门面是为应用的服务容器提供一个【静态】接口,相当于是服务容器底层类中的一个【静态代表】,能够提供更加灵活、易于测试、优雅的语法。laravel为什么要用门面-Laravel-PHP中文网
服务提供者是laravel 的引导中心 https://www.jianshu.com/p/ad60c37a29e0
$middleware:全局中间件,要对所有的请求要做一些处理的时候,就适合定义在该属性内。(比如统计请求次数这些)
$middlewareGroups:中间件组,比如我们项目有 api 请求和 web 的请求的时候,就要把两种类型的请求中间件分离开来,这时候就需要我们中间件组啦。
$routeMiddleware:路由中间件,有些个别的请求,我们需要执行特别的中间件时,就适合定义在这属性里面。 https://www.jb51.net/article/171835.htm
答: PHP-FPM采用的是Master/Worker进程模型。当PHP-FPM启动时,会读取配置文件,然后创建一个Master进程和若干个Worker进程(具体是几个Worker进程是由php-fpm.conf中配置的个数决定)。Worker进程是由Master进程fork出来的。PHP-FPM进程模型 - 知乎
答:
- 1. 尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描
- 2. 尽量避免使用in 和not in,会导致引擎走全表扫
- 3. 尽量避免使用 or,会导致数据库引擎放弃索引进行全表扫描
- 4. 尽量避免进行null值的判断,会导致数据库引擎放弃索引进行全表扫描。
- 5. 尽量避免在where条件中等号的左侧进行表达式、函数操作,会导致数据库引擎放弃索引进行全表扫描。
- 等等
答: 最左匹配
答: MySQL——主从复制与读写分离 - 知乎 (zhihu.com)
答:(4条消息) Redis的五种常用数据类型、三种特殊数据类型详解_Coder_Oldou的博客-CSDN博客_redis特殊数据类型
答: bitmap 存储格式 12进制 kb 字符串 存储占用内存
读写方面 bitmap 比string 更加稳定
答:秒杀场景实现思路_QQsilhonette的博客-CSDN博客_秒杀场景实现
- 1、首先在秒杀前先进行预热,将商品的库存加载到redis上;
-
- 2、秒杀开始,后端收到请求后,redis预减库存,如果库存已经没有了,就直接返回失败;
-
- 3、另外还要判断是否重复进行秒杀,避免一个账户重复秒杀;
-
- 4、如果库存充足且没有重复秒杀,就将秒杀请求加入消息队列,然后返回前端正在排队中;
-
- 5、后端消费端监听消息,如果有消息来了,则在数据表中再次判断库存和是否重复秒杀;
-
- 6、最后执行秒杀,减库存的时候要通过sql where条件>0的原子性来保证不会卖超,成功则返回订单号,否则返回秒杀失败。
-
- 在这个过程中还需要做一些安全性的优化:
-
- 1、要防止缓存穿透,要对不存在的对象也建立缓存;
-
- 2、要做接口防刷:a.通过隐藏秒杀地址的方式,在点击秒杀按钮时,先去请求一个动态的字符串并保存到缓存中,然后前端再将收到的这个字符串和秒杀接口做拼接再去请求秒杀,并判断这个字符串。b.通过url+userId拼接Key,并设置次数和有效期,控制5秒内最多访问5次。前端也可以加入验证码。
-
- 最后要做一个定时器,对30分钟还没有完成支付的订单要做退库存处理。