php 面试题基础 呕心沥血总结

  1. 考察面向对象
    这样写,对象是引用不是赋值 指向同一个地方
$b=new a();
$c=$b;
$b->abc='D';
echo $c->abc;
D
  1. abstract

在这里插入图片描述

在这里插入图片描述
抽象类里面有抽象方法,也可以有非抽象方法,抽象方法里面是不能有方法体的,就是{};
非抽象方法里可以有方法体。
接口中的方法不能定义protect,因为implements时,继承此接口的类,都要实现接口的方法,所以接口的方法都是公开的。

一个类可以实现多个接口,用逗号隔开
在这里插入图片描述

  1. 正则 邮箱
[]任选一个 a-z a字母到z ,A到Z,0到9,_-
 1. 可匹配多个 至少一个
@ 匹配@
\.  匹配小数点 点本来是运算符,转义就是字符串
() 一组出现的 匹配.com  .163等等
/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/

在这里插入图片描述
() 代表组
| 代表或,可以是3或4或5
\d 数字
{} 代表有几个
^ 以什么开头
$ 以什么结尾

/^1(3|4|5)\d{9}$/
  1. php数据类型

布尔,字符串,数组,整型,浮点,对象,资源,null

  1. php常见预定义变量
    $GLOBALS 引用全局作用域可用的全部变量
    $_SERVER
    $_GET
    $_FILES
    $_REQUEST
    $_SESSION
    $_ENV 环境变量
    $_COOKIE

  2. TCP怎么建立连接?
    三次握手
    在这里插入图片描述
    在这里插入图片描述

  3. 3|6 等于多少?
    0011 或 0110 = 0111 等于7

  4. 修饰符
    private 私有 内部可以访问
    protected 内部和继承类中可以访问
    public 哪都能用

  5. 常用的魔术方法
    __construct() 实例化类时自动调用
    __destruct() 类对象使用结束时自动调用
    __set() 在给未定义的属性赋值时调用
    __get() 调用未定义的属性时调用
    __isset() 使用isset() 或者empty() 函数时调用
    __unset() 使用unset() 时调用
    __sleep()使用serialize 序列化时调用
    __wakeup() 使用unserialize反序列化时调用
    __call() 调用第一个不存在的方法时调用
    __callStatic() 调用一个不存在的静态方法时调用
    __toString() 把对象转换成字符串时调用 比如echo
    __invoke()当尝试把对象当方法调用时调用
    __set_state() 当使用var_export()函数时调用,接受一个数组参数
    __clone() 当使用clone复制一个对象时调用

  6. 常用数组函数
    compact() 将变量整合成数组
    extract() 将数组中的每个值以键的名分解成变量
    explode() 以某个紫川分解字符串成数组
    impode() 将一维数组根据某个符号拼接成字符串
    array_merge() 合并
    array_diff() 差集
    array_intersect() 交集
    array_pop 弹出最后一个值
    array_push 追加一个值
    in_array() 判断一个值是否在数组中
    array_key_exists()判断键是否存在数组中
    array_unique() 数组去重
    array_column() 获取二维数组中的值的集合
    array_values 提取数组的值组成一维数组
    array_keys 提取数组的键组成一维数组
    array_rand() 返回数组中的随机的键
    count() 返回数组值的数量
    array_search() 查询数组这种的值是否存在
    sort() 排序
    array_multisort() 多维数组排序
    array_chunk() 分割数组

$str = "123#234";
$c = explode('#',$str);
var_dump($c);

$d = implode('#',$c);
var_dump($d);

$s = array('name'=>'+号覆盖',2,5,6);
$z = array(1,'name'=>'merge覆盖',4,6);
$ss = array_merge($s,$z);
var_dump($ss);

var_dump($s+$z);
var_dump(array_diff($s,$z));//以第一个数组为基础

在这里插入图片描述

  1. final关键字
    如果父类中的方法被声明final ,则子类无法覆盖改方法,如果一个类被声明final,则不能被继承

前面都是12k的题
下面是15k的题

  1. php设计模式
    1.工厂模式是一个类,
    好处:解耦;方便管理;灵活;
    demo
    在这里插入图片描述
<?php
//定义一个抽象类
abstract class operation
{
    protected $_numA = 0;
    protected $_numB = 0;
    protected $_result = 0;
    public function __construct($a, $b)
    {
        $this->_numA = $a;
        $this->_numB = $b;
    }
    //抽象方法所有子类必须实现该方法
    protected abstract function getResult();
}
//加法运算
class operationAdd extends operation
{
    public function getResult()
    {
        $this->_result = $this->_numA + $this->_numB;
        return $this->_result;
    }
}
//减法运算
class operationSub extends operation
{
    public function getResult()
    {
        $this->_result = $this->_numA - $this->_numB;
        return $this->_result;
    }
}
//乘法运算
class operationMul extends operation
{
    public function getResult()
    {
        $this->_result = $this->_numA * $this->_numB;
        return $this->_result;
    }
}
//除法运算
class operationDiv extends operation
{
    public function getResult()
    {
        $this->_result = $this->_numA / $this->_numB;
        return $this->_result;
    }
}
//定义工厂类
class operationFactory
{
    //创建保存示例的静态成员变量
    private static $obj;
    //创建实例的静态方法
    public static function CreateOperation($type, $a, $b)
    {
        switch ($type) {
        case '+':
            self::$obj = new operationAdd($a, $b);
            break;
        case '-':
            self::$obj = new operationSub($a, $b);
            break;
        case '*':
            self::$obj = new operationMul($a, $b);
            break;
        case '/':
            self::$obj = new operationDiv($a, $b);
            break;
        }
        //最后返回这个实例
        return self::$obj;
    }
}
//最后我们使用工厂模式
$obj = operationFactory::CreateOperation('+', 100, 20);
echo $obj->getResult();

// 由工厂类根据参数来决定创建出哪一种产品类的实例;
// 工厂类是指包含了一个专门用来创建其他对象的方法的类。所谓按需分配,传入参数进行选择,返回具体的类。
// 工厂模式的最主要作用就是对象创建的封装、简化创建对象操作。
简单的说,记住这句话:就是调用工厂类的一个方法(传入参数)来得到需要的类

2单例模式
某个类中只有一个实例
在计算机系统中,缓存,日志对象,数据库操作,显卡的驱动常被设计成单例
单例模式分三种,懒汉单例,恶汉单例,登记单例
单例三个特点 1只能有一个实例,2必须自行创建这个实例,3必须给其他对象提供这个实例
好处: 节省资源

class DB
{
    private static $instance = null; //私有静态属性,存放该类的实例
 
    private function __construct() //私有构造方法,防止在类的外部实例化
    {
        # code...
    }
 
 
    private function __clone() //私有克隆方法,防止克隆
    {
        # code
    }
 
 
    public static function getInstance() //公共的静态方法,实例化该类本身,只实例化一次
    {
        if (!self::$instance instanceof self) {
            self::$instance = new self;
        }
        return self::$instance;
    }
}

3观察者模式
就是大家都要使用接口的方法

/**
 * @purpose: 观察者接口, 定义观察者具体需要执行的方法,当然方法名和方法个数可以自定义
 * Interface Observer
 */
interface Observer
{
    /**
     * @purpose: 广播通知后,所有已注册的观察者都需要执行该方法。
     * @return mixed
     */
    public function eat();
}

/**
 * @purpse: 定义猫猫类,继承观察者接口,实现具体细节
 * Class Cat
 */
class Cat implements Observer{
    public function eat(){
        echo 'Cat eat fish';
    }
}

/**
 * @purpse: 定义狗狗类,继承观察者接口,实现具体细节
 * Class Dog
 */
class Dog implements Observer{
    public function eat(){
        echo 'Dog eat bones';
    }
}



/**
 * @purpose: 主题接口, 定义添加观察者和广播通知的方法
 * Interface Notify
 */
interface Subject
{
    /**
     * @purpose: 添加观察者
     * @param string $key 给所添加的观察者的一个唯一 key,方便从注册树中移除观察者
     * @param Observer $observer 观察者对象
     * @return mixed
     */
    public function addObserver($key, Observer $observer);

    /**
     * @purpose: 从注册树中移除观察者
     * @param string $key 给所添加的观察者的一个唯一 key,方便从注册树中移除观察者
     * @return mixed
     */
    public function removeObserver($key);

    /**
     * @purpose: 广播通知以注册的观察者
     * @return mixed
     */
    public function notify();
}

/**
 * @purpose: 实现主体接口,主要就是添加观察者和广播通知观察者
 * Class Action
 */
class Action implements Subject
{
    /**
     * @var array 保存所有已注册的观察者
     */
    public $_observer = [];

    /**
     * @purpose: 添加观察者
     * @param string $key 给所添加的观察者的一个唯一 key,方便从注册树中移除观察者
     * @param Observer $observer 观察者对象
     * @return mixed
     */
    public function addObserver($key, Observer $observer)
    {
        $this->_observer[$key] = $observer;
    }

    /**
     * @purpose: 从注册树中移除观察者
     * @param string $key 给所添加的观察者的一个唯一 key,方便从注册树中移除观察者
     * @return mixed
     */
    public function removeObserver($key)
    {
        unset($this->_observer[$key]);
    }

    /**
     * @purpose: 广播通知以注册的观察者,对注册树进行遍历,让每个对象实现其接口提供的操作
     * @return mixed
     */
    public function notify()
    {
        foreach ($this->_observer as $observer) {
            $observer->eat();
        }
    }
}

4.注册模式

其实就像一个货架,每个货架上放着一个样机。这个样机就是单例。这个货架就是注册树

/** 
     * PHP设计模式之注册模式实例 
     *  
     */  
    class  Registry  {  

      protected  static  $store  =  array();     
      private static $instance;  

      public static function instance() {  
          if(!isset(self::$instance)) {  
              self::$instance = new self();  
          }  
          return self::$instance;  
      } 
       public function  get($key)  {  
        if  (array_key_exists($key,  Registry::$store))  
        return  Registry::$store[$key];  
      }  

      public  function  set($key,  $obj)  {  
        Registry::$store[$key]  =  $obj;  
      }  
    }  


    class ConnectDB {  

        private $host;  
        private $username;  
        private $password;  

        private $conn;  


        public function __construct($host, $username, $password){  
            $this->host = $host;  
            $this->username = $username;  
            $this->password = $password;  
        }  

        public function getConnect() {  
            return mysql_connect($this->host,$this->username,$this->password);  
        }  

    }  

    //使用测试  
    $reg = Registry::instance();  
    $reg->set('db1', new ConnectDB('localhost', 'root', 'mckee'));  
    $reg->set('db2', new ConnectDB('192.168.1.198', 'test', '0K5Dt@2jdc8#x@'));  
    print_r($reg->get('db1'));  
    print_r($reg->get('db2'));

5.策略模式
策略模式就是使用封装一个公共抽象算法,每个算法(比如,打折算法,满减算法)实现这个接口,然后搞个策略工厂类来调用这些算法

针对不同的商品有不同的策略
demo
在这里插入图片描述

1. 抽象活动算法类
<?php
/**
 * 抽象活动算法类
 */
namespace strategy;

abstract class StrategyAbstract
{
    /**
     * 具体活动算法方法
     * @return mixed
     */
    public abstract function doAction($money);
}
 

2. 具体算法产品类

<?php
/**
 * 满减算法产品类
 */
namespace strategy;

class ManJianStrategy extends StrategyAbstract
{
    public function doAction($money)
    {
        echo '满减算法:原价'. $money .'元';
    }
}

<?php
/**
 * 打折算法产品类
 */
namespace strategy;

class DaZheStrategy extends StrategyAbstract
{
    /**
     * 具体算法实现
     * @param $money
     * @return mixed|void
     */
    public function doAction($money)
    {
        echo '打折算法:原价'. $money .'元';
    }
}
 

3. 策略工厂类

<?php
/**
 * 策略工厂类
 */
namespace strategy;

class StrategyFind
{
    private $strategy_mode;

    /**
     * 初始时,传入具体的策略对象
     * @param $mode
     */
    public function __construct($mode)
    {
        $this->strategy_mode = $mode;
    }

    /**
     * 执行打折算法
     * @param $money
     */
    public function get($money)
    {
        $this->strategy_mode->doAction($money);
    }
}

 

入口文件

<?php

namespace strategy;

include '../autoload.php';
// 满减折算
$mode1 = new StrategyFind(new ManJianStrategy());
$mode1->get(100);

echo '<br>';

// 满减活动
$mode2= new StrategyFind(new DaZheStrategy());
$mode2->get(100);

6.适配器模式
把对某些相似的类的操作转化为一个统一的“接口”(适配器),或者比喻为一个“界面”,统一或屏蔽了那些类的细节。适配器模式还构造了一种“机制”,使“适配”的类可以很容易的增减,而不用修改与适配器交互的代码,符合“减少代码间耦合”的设计原则

可以有多种选择

<?php
abstract class Toy  
{  
    public abstract function openMouth();  
  
    public abstract function closeMouth();  
}  
  
class Dog extends Toy  
{  
    public function openMouth()  
    {  
        echo "Dog open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Dog close Mouth\n";  
    }  
}  
  
class Cat extends Toy  
{  
    public function openMouth()  
    {  
        echo "Cat open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Cat close Mouth\n";  
    }  
}


//目标角色:红枣遥控公司  
interface RedTarget  
{  
    public function doMouthOpen();  
  
    public function doMouthClose();  
}  
  
//目标角色:绿枣遥控公司及  
interface GreenTarget  
{  
    public function operateMouth($type = 0);  
}


//类适配器角色:红枣遥控公司  
class RedAdapter implements RedTarget  
{  
    private $adaptee;  
  
    function __construct(Toy $adaptee)  
    {  
        $this->adaptee = $adaptee;  
    }  
  
    //委派调用Adaptee的sampleMethod1方法  
    public function doMouthOpen()  
    {  
        $this->adaptee->openMouth();  
    }  
  
    public function doMouthClose()  
    {  
        $this->adaptee->closeMouth();  
    }  
}  
  
//类适配器角色:绿枣遥控公司  
class GreenAdapter implements GreenTarget  
{  
    private $adaptee;  
  
    function __construct(Toy $adaptee)  
    {  
        $this->adaptee = $adaptee;  
    }  
  
    //委派调用Adaptee:GreenTarget的operateMouth方法  
    public function operateMouth($type = 0)  
    {  
        if ($type) {  
            $this->adaptee->openMouth();  
        } else {  
            $this->adaptee->closeMouth();  
        }  
    }  
}



class testDriver  
{  
    public function run()  
    {  
         //实例化一只狗玩具  
        $adaptee_dog = new Dog();  
        echo "给狗套上红枣适配器\n";  
        $adapter_red = new RedAdapter($adaptee_dog);  
        //张嘴  
        $adapter_red->doMouthOpen();  
        //闭嘴  
        $adapter_red->doMouthClose();  
        echo "给狗套上绿枣适配器\n";  
        $adapter_green = new GreenAdapter($adaptee_dog);  
        //张嘴  
        $adapter_green->operateMouth(1);  
        //闭嘴  
        $adapter_green->operateMouth(0);  
    }  
}  
  
$test = new testDriver();  
$test->run();
  1. socket连接步骤
    还有一个好记的概念,看马士兵教育,别名"四元组"
    源ip + port 端口号
    目标ip + port端口号
    (ps: 端口一共有65535)
    在这里插入图片描述

  2. 超卖问题
    1.悲观锁 不建议
    2.乐观锁 不建议
    3.队列
    4.分布式锁 redis+lua脚本

  3. 第三方登录
    在这里插入图片描述

  4. php 中对trait的理解
    php 5.4.0开始代码复用的方法
    当前类大于trait大于父类
    Traits和class在语义的定义上都是为了减少代码的复杂性,避免多重继承的问题。

traits test{
}
traits来定义
使用use 来调用

在这里插入图片描述
这篇文章说的挺好
https://zhuanlan.zhihu.com/p/91812589

  1. 一个100G的大文件,里面存储了电话号码,怎么确认某个电话在文件中。

方法一:
php程序通过shell_exec 调用linux命令

<?php
shell_exec('grep 手机号 文件名.txt')

方法二:
fseek + fread函数进行检索
charset设置 gb2312
fopen 打开读内存里
feof() 函数检查是否已到达文件末尾(EOF)。如果出错或者文件指针到了文件末尾(EOF)则返回 TRUE,否则返回 FALSE
offset根据查找的长度有关,如果手机号那就是11;如果有空格就是12
fseek( FILE *stream, long offset, int origin );
第一个参数stream为文件指针
第二个参数offset为偏移量,整数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、 SEEK_END 或 SEEK_SET
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
其中SEEK_SET,SEEK_CUR和SEEK_END和依次为0,1和2.
简言之:fseek 确立指针位置
fseek(fp,100L,0);把fp指针移动到离文件开头100字节处;
fseek(fp,100L,1);把fp指针移动到离文件当前位置100字节处;
fseek(fp,100L,2);把fp指针退回到离文件结尾100字节处
fread(文件,读多少个字节) 付给
在这里插入图片描述

  1. php协程的方式是啥?
    yield
    我看的是这篇文章
    https://www.cnblogs.com/lynxcat/p/7954456.html

  2. tcp和udp的区别?
    、

  3. 构造函数和析构函数
    在这里插入图片描述

  4. 获取客户端服务端ip
    获取真实ip http_x_forearded_for
    在这里插入图片描述

  5. php内存溢出
    在这里插入图片描述

  6. php垃圾回收机制 zval变量容器是啥?
    垃圾回收机制简称 GC
    zval 是 _zend_value的简称
    相当于计数器
    引擎在判断一个变量空间是否能够被释放的时候是依据这个变量的zval的refcount的值,如果refcount为0,那么变量的空间可以被释放,否则就不释放,这是一种非常简单的GC实现

这篇文章我看懂了
https://www.cnblogs.com/taijun/p/4206770.html
在这里插入图片描述

is_ref 是不是引用
refcount 是一个计数器 3 被用了几次就计几次
如果refcount等于0 php就销毁变量

php 5和php 7的垃圾回收机制的区别?
$person[‘hello’] = $person[‘name’]
在PHP7中输出:
person:
(refcount=1, is_ref=0)
array (size=3)
‘name’ => (refcount=3, is_ref=0)string ‘看看’ (length=6)
‘age’ => (refcount=0, is_ref=0)int 19
‘hello’ => (refcount=3, is_ref=0)string ‘看看’ (length=6)

在PHP5中输出:
person:
(refcount=1, is_ref=0),
array (size=3)
‘name’ => (refcount=2, is_ref=0),string ‘看看’ (length=6)
‘age’ => (refcount=1, is_ref=0),int 19
‘hello’ => (refcount=2, is_ref=0),string ‘看看’ (length=6)
总结:
PHP5和PHP7的垃圾回收机制都属于引用计数,但是在复杂数据类型的算法处理上:
在 PHP7 中 zval 有了新的实现方式。

$a=['a'];
$a[] = $a; 
php5 计2次
php7 计1次
php 5 计数器 放内存堆里
 php7 _zend_value里面有计数器 

最基础的变化就是 zval 需要的内存不再是单独从堆上分配,不再自己存储引用计数。复杂数据类型(比如字符串、数组和对象)的引用计数由其自身来存储。这种实现方式有以下好处:
简单数据类型不需要单独分配内存,也不需要计数;
不会再有两次计数的情况。在对象中,只有对象自身存储的计数是有效的;
由于现在计数由数值自身存储,所以也就可以和非 zval 结构的数据共享,比如 zval 和 hashtable key 之间;

看这篇文章
https://blog.csdn.net/yangxuesong5555/article/details/79417264

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mr.杰瑞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值