文章目录
PHP 7 新特性
1、标量类型与返回值类型声明
标量类型
标量类型声明有两种模式:强制模式 (默认)、严格模式
强制模式实例
<?php
// 强制模式
function sum(int ...$ints)
{
return array_sum($ints);
}
print(sum(2, '3', 4.1));
//结果:9
?>
严格模式实例
<?php
// 严格模式
declare(strict_types=1);
function sum(int ...$ints)
{
return array_sum($ints);
}
print(sum(2, '3', 4.1));
//结果:PHP Fatal error: Uncaught TypeError: Argument 2 passed to sum() must be of the type integer, string given, called in……
?>
返回类型声明
要求返回结果为整数
<?php
declare(strict_types=1);
function returnIntValue(int $value): int
{
return $value;
}
print(returnIntValue(5));
//结果:5
?>
返回类型声明错误实例
<?php
declare(strict_types=1);
function returnIntValue(int $value): int
{
return $value + 1.0;
}
print(returnIntValue(5));
?>
//结果:Fatal error: Uncaught TypeError: Return value of returnIntValue() must be of the type integer, float returned...
2、NULL 合并运算符
以前我们这样写三元运算符:
$site = isset($_GET['site']) ? $_GET['site'] : '菜鸡';
现在我们可以直接这样写:
$site = $_GET['site'] ?? '小菜鸡';
3、太空船运算符
用于比较两个表达式 $a 和 $b,如果 $a 小于、等于或大于 $b时,它分别返回-1、0或1。
实例
<?php
// 整型比较
print( 1 <=> 1);print(PHP_EOL);// 0
print( 1 <=> 2);print(PHP_EOL);// -1
print( 2 <=> 1);print(PHP_EOL);// 1
// 浮点型比较
print( 1.5 <=> 1.5);print(PHP_EOL);// 0
print( 1.5 <=> 2.5);print(PHP_EOL);// -1
print( 2.5 <=> 1.5);print(PHP_EOL);// 1
// 字符串比较
print( "a" <=> "a");print(PHP_EOL);// 0
print( "a" <=> "b");print(PHP_EOL);// -1
print( "b" <=> "a");print(PHP_EOL);// 1
?>
4、常量数组
实例
<?php
// 使用 define 函数来定义数组
define('sites', [
'Google',
'Runoob',
'Taobao'
]);
print(sites[1]);
//结果:Runoob
?>
5、匿名类
实例
<?php
interface Logger {
public function log(string $msg);
}
class Application {
private $logger;
public function getLogger(): Logger {
return $this->logger;
}
public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}
$app = new Application;
// 使用 new class 创建匿名类
$app->setLogger(new class implements Logger {
public function log(string $msg) {
print($msg);
}
});
$app->getLogger()->log("我的第一条日志");
//结果:我的第一条日志
?>
thinkphp相关
5 6版本差别
- 采用PHP7强类型(严格模式)
- 只能使用composer安装
- 模版引擎需要单独安装
- 不再继承controller,继承basecontroller
- 目录结构不同
中间件的使用场景
前置中间件:HTTP请求过滤、判断登录状态、权限验证
后置中间件:写日志
面向对象三大特性
OOP是面向对象编程,具有三大特点:封装、继承、多态。
封装:就是类的定义, 将事物相关属性特征和行为特征集合在一起,形成一个类。
继承:就是B类继承A类,通过继承创建的类被称为子类或派生类。被继承的类称为基类或父类。
多态:就是同一个方法,传入不同的对象,实现不同的效果。
PHP正则匹配手机号
<?php
$str = '13712345678';
preg_match_all("/^1[34578]\d{9}$/", $str, $mobiles);
//var_dump($mobiles);
include与require的区别
1、执行的原理:include程序执行到才调用,require无条件优先执行
2、遇到报错:include报warning级别错误,后续代码可继续执行;require报error级别错误,中断执行
3、运行效率:require效率高于include
include_once、require_once同上,不同的是不管包含多少次,只会执行一次
常用函数
数组
array_diff:比较数组,返回两个数组的差集
array_keys:返回数组中所有的键名
array_values:返回数组中所有的值
array_merge:把一个或多个数组合并为一个数组
array_pop:删除数组中的最后一个元素
array_push:将一个或多个元素插入数组的末尾
字符串
explode:根据指定字符把字符串转数组
implode:把一个数组元素组合转字符串
str_split:把字符串分割到数组中
str_chr:查找字符在另一字符串中的第一次出现
strpos:查找字符串在另一字符串中的第一次出现
strlen:返回字符串长度
trim:去除字符串两边的空白
冒泡排序
$arr = [9,5,6,1,7,3];
$len = count($arr);
for ($i = 0;$i < $len; $i++){
for ($j = $i;$j < $len-1;$j++){
if ($arr[$i] > $arr[$j+1]){
$temp = $arr[$j+1];
$arr[$j+1] = $arr[$i];
$arr[$i] = $temp;
}
}
}
快速排序
public function quickSort($arr = []){
$len = count($arr);
if ($len <= 1) return $arr;
$num = $arr[0];
$low = [];
$high = [];
for ($i = 1;$i < $len;$i ++){
$arr[$i] > $num ? $high[] = $arr[$i] : $low[] = $arr[$i];
}
return array_merge($this->quickSort($low),[$num],$this->quickSort($high));
}
数据库字段类型varchar和char的区别
1、char类型的长度是固定的,varchar的长度是可变的
2、因为varchar长度可变,查询时需要确定数据的实际长度,再进行数据的提取,所以效率比char低,但是比char节省空间
session与cookie的区别
1、session保存在服务器端,cookie保存在客户端
2、session比较安全,cookie可以进行修改,不安全
3、因为session保存在服务器端,当访问量增多,会比较占用服务器性能
4、很多浏览器限制最多保存20个cookie,可以将重要信息保存在session,其他信息保存至cookie
5、cookie只能保存字符串类型,session保存对象类型
优化数据库的方法
1、选取最适用的字段属性,尽可能将字段的宽度设置到最小
2、使用join代替子查询,使用exists代替in、not exists代替not in
3、使用事务,合适的时候可以进行分区分表
4、在经常需要进行关联查询的表字段使用索引
5、大数据量条件下,配置读写分离
MVC三层架构
模型(Model):负责存储系统的中心数据
视图(View):将信息显示给用户
控制器(Controller):负责应用程序中处理用户的交互
传值与传引用的区别
值传递:函数外对值的改变会被忽略
引用传递:函数外对值的改变,值会被改变
优缺点:按值传递,需要对值进行复制,如果是一个大型的字符串或对象,会是一个很大的代价。按引用传递则是传递值的地址,对性能提高很大好处
怎么保证促销商品不会超卖
使用redis的队列来实现。将要促销的商品数量以队列的方式存入redis中,每当用户抢到一件促销商品则从队列中删除一个数据,确保商品不会超卖。
秒杀实现
1、通过redis的一个队列,把秒杀的请求写入队列里,秒杀结束后,读取队列里的数据,并写入到数据库里。实现了流量的均衡,不会对数据库产生太大压力。
$redis = new \Redis();
$redis->connect('127.0.0.1');
$datacenterId = 123124354; //指定数据中心ID
$workerId = 1122435; //计算机ID
$snowFlake = new Snowflake($datacenterId, $workerId); //步骤2:分布式生成唯一uuid(https://github.com/godruoyi/php-snowflake)
$uuid = $snowFlake->id();
$lockKey = 'lockKey'; //步骤3: 线程锁键key
$isLock = $redis->set($lockKey, $uuid, 30); //步骤4: 加锁并设置超时时间,设置值为uuid
if (!$isLock) { //步骤5:未获得锁的线程(用户)直接返回,稍后再试~
return '服务器繁忙,请稍后再试~';
}
try {
$stockKey = 'stock'; //步骤6: 库存键key
// $redis->set($stockKey, 5); //步骤7: 第一次运行,初始化库存(注意:初次执行)
$stock = $redis->get($stockKey); //步骤8: 获取库存值
if ($stock > 0) { //步骤9: 库存大于0
$stock = $stock - 1; //步骤10: 减库存
$redis->set($stockKey, $stock); //步骤11: 重新设置到缓存
echo '购买成功'; //步骤12: 减库存成功返回true
} else {
echo '库存不足'; //步骤13: 减库存成功返false
}
} finally {
//这一步不是原子性操作,还是会有问题,我们用lua原子性去处理
if ($uuid === $redis->get($lockKey)) { //步骤14: 保证用户删除的是自己的锁
$redis->del($lockKey); //步骤15: 删除当前锁
}
// //lua原子性去处理如下
$script = <<<EOF
local key = KEYS[1]
local value = ARGV[1]
if (redis.call('exists', key) == 1 and redis.call('get', key) == value)
then
return redis.call('del', key)
end
return 0
EOF;
$redis->eval($script, [$lockKey,$uuid]);
}