php常见面试题


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]);
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值