php开启Gzip压缩
if (extension_loaded('zlib')){
ob_end_clean();
ob_start('ob_gzhandler');
}
php版本比较
version_compare(PHP_VERSION,'5.5.0','<')
php .env文件转数组
parse_ini_file( '.env', true)
php .env文件转数组
putenv() getenv() 设置以及获取环境变量
php 判断是否是ajax请求
$_SERVER['HTTP_X_REQUEST_WITH']== 'XMLHttpRequest'
mysql导出全部表结构
SELECT
COLUMN_NAME 列名,
COLUMN_TYPE 数据类型,
DATA_TYPE 字段类型,
CHARACTER_MAXIMUM_LENGTH 长度,
IS_NULLABLE 是否为空,
COLUMN_DEFAULT 默认值,
COLUMN_COMMENT 备注
FROM
INFORMATION_SCHEMA.COLUMNS
where
-- developerclub为数据库名称,到时候只需要修改成你要导出表结构的数据库即可
table_schema ='developerclub'
AND
-- article为表名,到时候换成你要导出的表的名称
-- 如果不写的话,默认会查询出所有表中的数据,这样可能就分不清到底哪些字段是哪张表中的了,所以还是建议写上要导出的名名称
table_name = 'article'
php getter和setter
方法一:直接箭头->调用属性(最常用),不管有没有声明这个属性,都可以使用,但会报Notice级别的错误
方法二:添加setter和getter方法,类似于Java
class Dog
{
private $name="";
public function setName($value)
{
$this->name=$value;
}
public function getName()
{
return $this->name;
}
}
方法三:魔术方法 __set,__get,__isset,__unset当访问类中不可达参数或未定义参数时,则会调用魔术方法。
class Dog1
{
private $_name = '';
function __set($property, $value) {
if ($property === 'name') $this->_name = $value;
}
function __get($property) {
if ($property === 'name') return $this->_name;
}
}
php
new static()和new self();
XX::class;
consul:一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
number_format()
number_format(12345.66); //12,346
number_format(12345.44); //12,345
number_format(12345.44,1); //12,345.4
验证邮箱
filter_var($email,FILTER_VALIDATE_EMAIL);
preg_match('/^[0-9a-zA-Z]+@[0-9a-zA-Z]+(\.[0-9a-zA-Z]+){1,3}$/',$email);
双向队列
array_unshift与array_shift,array_push与array_pop
对二维数组根据某个key值排序
usort($arr,function ($a,$b) use ($var){
return strnatcmp($a[$var],$b[$var]);
});
多维数组首字母大写
array_walk_recursive($arr,function (&$value,$key){
$value=ucfirst($value);
});
秒杀系统
要点是分布锁的使用,使库存不被错误操作。
网络攻击
sql注入
如 name=“1;‘delete from table’;”;
使用pdo预处理prepare;使用addslashes进行转义;
xss脚本攻击
如text="*";
使用htmlspecialchars()
csrf
进行token验证
php7新特性
- 标量类型声明
- 返回值类型声明
- null合并运算。$param = $_GET[‘param’] ?? ‘’;??运算符会根据一个值来判断它是否是存在且不为NULL,如果是则返回第一个数,否则返回第二个数。
- 组合比较符。<=>
- define定义常量数组。
- 匿名类。
$class=new class()
{
public function execute()
{}
}
- 闭包绑定。之前声明一个闭包之后需要为为闭包绑定执行上下文,需要复制闭包然后绑定$this,现在使用call()省去复制步骤,更加方便,性能更好。
PHP7之前
class App
{
public function execute()
{
echo 'App execute';
}
}
$closure = function() {
echo $this->execute();
};
$newClosure = Closure::bind($closure, new App());
//或者$newClosure = $closure->bindTo(new App());
$newClosure(); //输出App execute
PHP7
class App
{
public function execute()
{
echo 'App execute Call';
}
}
$closure = function() {
echo $this->execute();
};
$closure->call(new App());
//输出App execute Call
- unserialize过滤
- 命名空间批量导入
//PHP之前
use oopsguy\framwork\core\Controller;
use oopsguy\framework\core\Model;
use oopsguy\framework\core\Config;
use function oopsguy\framework\core\function\func1;
use function oopsguy\framework\core\function\func2;
use const oopsguy\framework\core\constant\CONST_SESSION_KEY;
use const oopsguy\framework\core\constant\CONST_MANAGER_SESSION_KEY;
//PHP7
use oopsguy\framework\core\{Controller, Model, Config};
use function oopsguy\framework\core\function\{func1, func2};
use const oopsguy\framework\core\constant\{CONST_SESSION_KEY, CONST_MANAGER_SESSION_KEY};
新特性使得命名空间的声明语句变得简洁许多,精简了很多代码。
- 生成器返回表达器。生成器允许在foreach代码块中写代码来迭代一组数据而不需要在内存中创建一个数据,使你的内存达到上限,或者占据客观的处理时间。迭代的时候才会取值,不会把遍历的数据全部放入内存。php7中添加了getReturn接口,可以获取return返回值。
function getContent()
{
$handler = @fopen('web.config','rb');
if(is_resource($handler)){
while (!feof($handler)){
yield fgets($handler);
}
fclose($handler);
return "end";
}
return "no handler";
}
$content=getContent();
foreach ($content as $val){
echo $val;
}
echo $content->getReturn();
- 生成器委托 yield from
function getAllContent()
{
yield from getContent('web.config');
yield from getContent('robots.txt');
}
function getContent($file)
{
$handler = @fopen($file,'rb');
if(is_resource($handler)){
while (!feof($handler)){
yield fgets($handler);
}
fclose($handler);
return "end";
}
return "no handler";
}
$content=getAllContent();
foreach ($content as $val){
echo $val;
}
echo $content->getReturn();
- 整除函数 intdiv
- session配置,可以session_start时传入一个数组配置参数来覆盖运行时的php.ini文件的配置。
- list解构。list不仅能结构数组,还能结构实现了ArrayAccess接口的对象。
class Config implements ArrayAccess
{
private $data = [];
function __construct($file)
{
/** @noinspection PhpIncludeInspection */
$this->data = include $file;
}
public function offsetExists($offset)
{
return isset($this->data[$offset]);
}
public function offsetGet($offset)
{
return ($this->offsetExists($offset))
? $this->data[$offset]
: null;
}
public function offsetSet($offset, $value)
{
$this->data[$offset] = $value;
}
public function offsetUnset($offset)
{
if ($this->offsetExists($offset))
unset($this->data[$offset]);
}
}
$config = new Config('config.php');
echo $config[1] , '<br>';
list($key, $key1) = $config;
echo $key , '<br>';
echo $key1 , '<br>';
php7性能提升原因
1、存储变量的结构体变小,尽量使结构体里成员共用内存空间,减少引用,这样内存占用降低,变量的操作速度得到提升
2、字符串结构体的改变,字符串信息和数据本身原来是分成两个独立内存块存放,php7尽量将它们存入同一块内存,提升了cpu缓存命中率
3、数组结构的改变,数组元素和hash映射表在php5中会存入多个内存块,php7尽量将它们分配在同一块内存里,降低了内存占用、提升了cpu缓存命中率
4、改进了函数的调用机制,通过对参数传递环节的优化,减少一些指令操作,提高了执行效
像访问数组一样访问php类或对象
让类实现php的ArrayAccess(数组式访问)
fastcgi通过端口监听和通过文件监听的区别
fastcgi_pass 127.0.0.1:9200 //TCP连接
fastcgi_pass /tmp/php_cgi.sock // Unix domain Socket
从数组中查找最小的k个元素
/**
* 从数组里找出最小的 $k 个数
* @param $arr array 输入数组
* @param $k int 输出元素个数
* @return array 最小元素集合
*/
function getMinK($arr, $k)
{
$n=count($arr);
$minArray=[];
for($i=0;$i<$n;++$i){
if($i<$k){
$minArray[$i]=$arr[$i];
}else{
if($i==$k){
$maxPos=getMaxPos($minArray);
$max=$minArray[$maxPos];
}
if($max>$arr[$i]){
$minArray[$maxPos]=$arr[$i];
$maxPos=getMaxPos($minArray);
$max=$minArray[$maxPos];
}
}
}
return $minArray;
}
/**
* 从数组中查找最大值的位置
* @param $arr array 待查找数组
* @return int 位置
*/
function getMaxPos($arr)
{
$pos = 0;
for ($i = 1; $i < count($arr); $i++) {
if ($arr[$i] > $arr[$pos]) {
$pos = $i;
}
}
return $pos;
}
$arr = [1, 100, 20, 22, 33, 44, 55, 66, 23, 79, 18, 20, 11, 9, 129, 399, 145, 2469, 58];
$res = getMinK($arr, 5);
// 输出:[1,9,20,11,18]
echo json_encode($res);
取出n以内的质数
/**
* 1是合数,2是第一个质数,所以从3开始计算,除2外的偶数都不是质数,所以循环的补偿可以为2。
* n不能够被不大于根号n的任何质数整除,则n是一个质数
* @param $n
* @return array
*/
function primeNumber($n)
{
$prime=array(2);
for ($i=3;$i<$n;$i+=2){
$sqrt=intval(sqrt($i));
for ($j=3;$j<=$sqrt;$j+=2){
if($i%$j==0){
break;
}
}
if($j>$sqrt){
array_push($prime,$i);
}
}
return $prime;
}
数字和字母字符串分割成索引数组
/**
* preg_split 匹配正则的边界分隔符,
* @param $str
* @return array
*/
function split(string $str) :array
{
$num=preg_split('/[a-zA-Z]+/',$str,-1,PREG_SPLIT_NO_EMPTY);
$char=preg_split('/\d+/',$str,-1,PREG_SPLIT_NO_EMPTY);
$count=count($num);
$array=[];
for ($i=0;$i<$count;++$i){
$array[$num[$i]]=$char[$i];
}
return $array;
}
php性能优化
- 使用php7+
- 减少业务复杂度
- 使用异步消息队列处理复杂请求
- 使用缓存
- sql优化
php如何实现并发
- curl_multi_get()
- swoole
- exec
php调试
ini_set("display_error","on");
error_reporting(E_ALL);
php使用和处理异常
try {
// 执行操作,比如连接数据库、读写文件,这里必须throw exception才可以被捕捉
} catch (MyException $e) {
// 执行有错误,在这里处理错误(显示、读入log、或显示执行信)
} catch (Exception $e) {
// 可以分别catch多个异常
} finally {
// 最后可以返回连接、数据、或其他处理
}
php-fpm有哪些子进程运行方式
主要在php-fpm.conf进行配置,有三种static,dynamic,ondemand
php序列化方法
- serialize和unserialize(),序列化保存数据类型,100%能还原;体积大,速度慢;可读性差;php自带,不可跨平台。
- json_encode()和json_decode(),反序列化数据类型会有缺失;体积小,速度快;可读性强;跨平台。
php接口和抽象类的区别
- 都不能被实例化
- 定义接口的关键词是interface,实现是implement,抽象类是abstract class,实现是extends
- 接口的每一个方法都是public抽象方法,都只是定义,都必须实现
- 抽象类的方法不能是private,可以选择的实现
- 接口没有数据成员和构造函数,抽象类可以有
php魔术方法
__contruct():每次new对象的时候会调用
__destruct():每次对象的所有引用被删除时会调用
__call():在对象中调用一个不可访问的方法时调用
__callStatic():在静态上下文中调用一个不可访问访问时调用
__set():在给不可访问属性赋值时调用
__get():在获取不可访问属性时调用
__isset():在对不可访问属性调用isset时调用
__unset()同理__isset()
__sleep和__wakeup:serialize和unserialize时调用
__toString()和__debugInfo():echo和var_dump时调用
__clone():使用clone复制对象时调用
php中this,self,static,parent
this是实例对象的指针;
self是类本身的一个引用,一般用来指向静态变量,取决于定义当前方法所在的类;
static也是对类本身的一个引用,取决于运行时计算的;
parent是对父类的引用;
php传值和传引用的区别
传值,是将值赋值给行参。
传引用,实参和行参指向同一个对象,行参的值改变将影响实参的值。
php大版本改进
php7:性能提升;数据类型定义;匿名类;null合并运算符??;字符比较符<=>,yield from,yield::getReturn
php5.6:运算符定义变长参数函数
php5.5:新增generators,yield关键字
php5.4:trait,cli模式的web server
php5.3:命名空间,闭包
php创建字符串
单引号和newDoc(<<< ‘EOT’),双引号和hereDoc(<<< EOT)
获取文件中的图片并下载
/**
* 需要先获取到img url路径,再计算本地存储的path
* @param $url
* @param null $target_dir
* @return bool
*/
function downImagesFromTargetUrl($url, $target_dir = null)
{
if(!filter_var($url, FILTER_VALIDATE_URL)){
return false;
}
if(!$target_dir) {
$target_dir = './download';
}
$root_url = pathinfo($url);
$html = file_get_contents($url); //主要
preg_match_all('/<img[^>]*src="([^"]*)"[^>]*>/i',$html, $matchs); //主要
$images = $matchs[1];
foreach ($images as $img) {
$img_url = parse_url($img);
if(! array_key_exists('host', $img_url)) {
$img_url = $root_url['dirname'] . DIRECTORY_SEPARATOR . $img;
} else {
$img_url = $img;
}
$img_path = array_key_exists('path', parse_url($img_url)) ? parse_url($img_url)['path'] : $img;
$save = $target_dir . DIRECTORY_SEPARATOR . $img_path;
$save_path = pathinfo($save);
if(!is_dir($save_path['dirname'])) {
mkdir($save_path['dirname'], 0777, true);
}
file_put_contents($save,file_get_contents($img_url)); //主要
}
}
php实现单向链表,判断单向链表有没形成环,环入口在哪
单向链表是链表中的一种,其特点是链表的链接方向是单向的,对链表的访问要顺序通过头部节点开始,又称节点列表,链表是由一个个节点组装起来,head指针指向第一个成为表头节点,而终止于最后一个指向null的指针。
class Node
{
public $id;
public $name;
public $next;
public function __construct($id,$name,$next=null)
{
$this->id=$id;
$this->name=$name;
$this->next=$next;
}
}
class LinkList
{
public $head;
public function __construct($id=null,$name=null,$next=null)
{
$this->head=new Node($id,$name,$next);
}
public function getLinkListLen()
{
$i=0;
$current=$this->head;
while($current->next!=null){
$i++;
$current=$current->next;
}
return $i;
}
public function addLink($node)
{
$current=$this->head;
while ($current->next!=null){
if($current->next->id > $node->id){
break;
}
$current=$current->next;
}
$node->next=$current->next;
$current->next=$node;
}
public function deleteLink($node)
{
$current=$this->head;
$flag =false;
while($current->next!=null){
if($current->next->id == $node->id){
$flag=true;
break;
}
$current=$current->next;
}
if($flag){
$current->next=$current->next->next;
}else{
echo "未找到该节点";
}
}
public function getLinkList()
{
$current=$this->head;
if($current->next==null){
return "空链表";
}
while ($current->next!=null){
echo $current->id."-".$current->name."<br>";
if($current->next->next==null){
break;
}
$current=$current->next;
}
}
}
$lists = new LinkList ();
$lists->addLink ( new Node ( 5, 'eeeeee' ) );
$lists->addLink ( new Node ( 1, 'aaaaaa' ) );
$lists->addLink ( new Node ( 6, 'ffffff' ) );
$lists->addLink ( new Node ( 4, 'dddddd' ) );
$lists->addLink ( new Node ( 3, 'cccccc' ) );
$lists->addLink ( new Node ( 2, 'bbbbbb' ) );
$lists->getLinkList ();
function eatLink(Node $node)
{
$fast=$slow=$node;
while(true){
if ($fast->next==null || $fast->next->next==null){
return;
}else{
$fast=$fast->next->next;
$slow=$slow->next;
}
if($fast==$slow){
$p1=$node;
$p2=$fast;
while($p1!=$p2){
$p1=$p1->next;
$p2=$p2->next;
}
return $p1;
}
}
}
判断长方形
1.四个不同的点,2.算出点与点的长度,判断是否符合勾股定理
function isRectangle($point1, $point2, $point3, $point4){
if ($point1 == $point2 || $point1 == $point3 || $point1 == $point4 || $point2 == $point3 || $point2 == $point4 || $point3 == $point4) {
return false;
}
$lengthArr = [];
$lengthArr[] = getLengthSquare($point1, $point2);
$lengthArr[] = getLengthSquare($point1, $point3);
$lengthArr[] = getLengthSquare($point1, $point4);
$lengthArr[] = getLengthSquare($point2, $point3);
$lengthArr[] = getLengthSquare($point2, $point4);
$lengthArr[] = getLengthSquare($point3, $point4);
$lengthArr = array_unique($lengthArr);
$lengthCount = count($lengthArr);
if ($lengthCount == 3 || $lengthCount == 2 ) {
if ($lengthCount == 2) {
return(max($lengthArr) == 2*min($lengthArr));
} else {
$maxLength = max($lengthArr);
$minLength = min($lengthArr);
$otherLength = array_diff($lengthArr, [$maxLength, $minLength]);
return($minLength + $otherLength == $maxLength);
}
} else {
return false;
}
}
function getLengthSquare($point1, $point2){
$res = pow($point1[0]-$point2[0], 2)+pow($point1[1]-$point2[1], 2);
var_dump($res);
return $res;
}
var_dump(isRectangle([0,0],[0,2],[2,2],[2,0]));
遍历目录
function scanDirs($dir="./")
{
$data=array();
if(!is_dir($dir)){
return;
}
$handler=opendir($dir);
if(is_resource($handler)){
while ($file=readdir($handler)){
if($file=="."||$file==".."){
}elseif (is_dir($dir.DIRECTORY_SEPARATOR.$file)){
$data[$file]=scanDirs($dir.DIRECTORY_SEPARATOR.$file);
}else{
array_push($data,$file);
}
}
}
return $data;
}
计算相对路径
function getRelativePath($path1, $path2)
{
$path1Arr=explode('/',$path1);
$path2Arr=explode('/',$path2);
$len=count($path1Arr);
$dismatch=0;
$left='';
for($i=0;$i<$len;++$i){
if($path1Arr[$i]!=$path2Arr[$i]){
$dismatch=$len-$i;
$left=array_slice($path1Arr,$i);
break;
}
}
if ($dismatch){
echo str_repeat("../",$dismatch).implode('/',$left);
}
}
$a = '/a/b/c/d/e.php';
$b = '/a/b/12/34/5.php';
echo getRelativePath($a, $b);
遍历二叉树
前序遍历:中左右
中序遍历:左中右
后序遍历:左右中
class Node
{
public $data = null;
public $left = null;
public $right = null;
}
$A = new Node();
$B = clone $A;
$C = clone $A;
$D = clone $A;
$E = clone $A;
$F = clone $A;
$G = clone $A;
$H = clone $A;
$I = clone $A;
$A->data = 'A';
$B->data = 'B';
$C->data = 'C';
$D->data = 'D';
$E->data = 'E';
$F->data = 'F';
$G->data = 'G';
$H->data = 'H';
$I->data = 'I';
$A->left = $B;
$A->right = $C;
$B->left = $D;
$B->right = $E;
$E->left = $G;
$E->right = $H;
$G->right = $I;
$C->right = $F;
/**
* 前序遍历: 中左右
* 中序遍历: 左中右
* 后序遍历: 左右中
*/
function eatBtree($node)
{
if($node && $node->data){
if($node->data){
echo $node->data;
}
if($node->left){
eatBtree($node->left);
}
if($node->right){
eatBtree($node->right);
}
}
}
eatBtree($A);
字符串翻转
function reverseString($str)
{
$output = '';
$i = 0;
while (isset($str[$i]) && $str[$i] != null) {
$output = $str[$i++] . $output;
}
return $output;
}
// 测试代码,输出:9876543210
echo reverseString('0123456789');
括号闭合问题
主要左括号进栈,右括号出栈左括号,成一对。
function checkClose($str)
{
$stack=[];
for ($i=0;$i<strlen($str);++$i){
if($str[$i]=="("){
$stack[]="(";
}
if($str[$i]==')'){
if(!array_pop($stack)){
return false;
}
}
}
if(count($stack)==0){
return true;
}else{
return false;
}
}
var_dump( checkClose('(()))'));