- 考察面向对象
这样写,对象是引用不是赋值 指向同一个地方
$b=new a();
$c=$b;
$b->abc='D';
echo $c->abc;
D
- abstract
抽象类里面有抽象方法,也可以有非抽象方法,抽象方法里面是不能有方法体的,就是{};
非抽象方法里可以有方法体。
接口中的方法不能定义protect,因为implements时,继承此接口的类,都要实现接口的方法,所以接口的方法都是公开的。
一个类可以实现多个接口,用逗号隔开
- 正则 邮箱
[]任选一个 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}$/
- php数据类型
布尔,字符串,数组,整型,浮点,对象,资源,null
-
php常见预定义变量
$GLOBALS 引用全局作用域可用的全部变量
$_SERVER
$_GET
$_FILES
$_REQUEST
$_SESSION
$_ENV 环境变量
$_COOKIE -
TCP怎么建立连接?
三次握手
-
3|6 等于多少?
0011 或 0110 = 0111 等于7 -
修饰符
private 私有 内部可以访问
protected 内部和继承类中可以访问
public 哪都能用 -
常用的魔术方法
__construct() 实例化类时自动调用
__destruct() 类对象使用结束时自动调用
__set() 在给未定义的属性赋值时调用
__get() 调用未定义的属性时调用
__isset() 使用isset() 或者empty() 函数时调用
__unset() 使用unset() 时调用
__sleep()使用serialize 序列化时调用
__wakeup() 使用unserialize反序列化时调用
__call() 调用第一个不存在的方法时调用
__callStatic() 调用一个不存在的静态方法时调用
__toString() 把对象转换成字符串时调用 比如echo
__invoke()当尝试把对象当方法调用时调用
__set_state() 当使用var_export()函数时调用,接受一个数组参数
__clone() 当使用clone复制一个对象时调用 -
常用数组函数
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));//以第一个数组为基础
- final关键字
如果父类中的方法被声明final ,则子类无法覆盖改方法,如果一个类被声明final,则不能被继承
前面都是12k的题
下面是15k的题
- 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();
-
socket连接步骤
还有一个好记的概念,看马士兵教育,别名"四元组"
源ip + port 端口号
目标ip + port端口号
(ps: 端口一共有65535)
-
超卖问题
1.悲观锁 不建议
2.乐观锁 不建议
3.队列
4.分布式锁 redis+lua脚本 -
第三方登录
-
php 中对trait的理解
php 5.4.0开始代码复用的方法
当前类大于trait大于父类
Traits和class在语义的定义上都是为了减少代码的复杂性,避免多重继承的问题。
traits test{
}
traits来定义
使用use 来调用
这篇文章说的挺好
https://zhuanlan.zhihu.com/p/91812589
- 一个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(文件,读多少个字节) 付给
-
php协程的方式是啥?
yield
我看的是这篇文章
https://www.cnblogs.com/lynxcat/p/7954456.html -
tcp和udp的区别?
-
构造函数和析构函数
-
获取客户端服务端ip
获取真实ip http_x_forearded_for
-
php内存溢出
-
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