PHP面试题收集整理

1、oop是面向对象编程。面向对象编程是一种计算机编程架构,OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。

封装性:也称为信息隐藏,就是将一个类的使用和实现分开,只保留部分接口和方法与外部联系,或者说只公开了一些供开发人员使用的方法。于是开发人员只需要关注这个类如何使用,而不用去关心其具体的实现过程,这样就能实现MVC分工合作,也能有效避免程序间相互依赖,实现代码模块间松藕合。

继承性:就是子类自动继承其父级类中的属性和方法,并可以添加新的属性和方法或者对部分属性和方法进行重写。继承增加了代码的可重用性。PHP只支持单继承,也就是说一个子类只能有一个父类。

多态性:子类继承了来自父级类中的属性和方法,并对其中部分方法进行重写。于是多个子类中虽然都具有同一个方法,但是这些子类实例化的对象调用这些相同的方法后却可以获得完全不同的结果,这种技术就是多态性。多态性增强了软件的灵活性。

易维护 、质量高 、效率高 、易扩展 由于继承、封装、多态的特性,自然设计出高内聚、低耦合的系统结构,使得系统更灵活、更容易扩展,而且成本较低。

2、各框架
ThinkPHP
优点:

1.简化开发、提高效率、易于扩展、易于上手,有丰富的中文文档;

2.框架的兼容性较强,PHP4和PHP5完全兼容、完全支持UTF8等。

3.适合用于中小项目的开发

缺点:

1.对Ajax的支持不是很好;

2.目录结构混乱,需要花时间整理;

3.上手容易,但是深入学习较难。

YII
优点

1.纯OOP

2.用于大规模Web应用

3.模型使用方便

4.开发速度快,运行速度也快。性能优异且功能丰富

5.使用命令行工具。

缺点:

1.对Model层的指导和考虑较少

2.文档实例较少

3.英文太多

4.要求PHP技术精通,OOP编程要熟练!

5.View并不是理想view,理想中的view可能只是html代码,不会涉及PHP代码。

CodeIgniter
优点:
推崇简单,配置简单,全部的配置使用PHP脚本来配置,执行效率高,快速简洁,代码不多,执行性能高,框架简单,容易上手,学习成本低,文档详细;自带了很多简单好用的library,框架适合小型应用。
缺点:
内部结构过于混乱,虽然简单易用,但缺乏扩展能力。 把Model层简单的理解为数据库操作. 框架略显简单,只能够满足小型应用,略微不太能够满足中型应用需要.

laravel框架的设计思想比较先进,非常适合应用各种开发模式,作为一个框架,它为你准备好了一切。 laravel框架最大的特点和优秀之处就是集合了php比较新的特点,以及各种各样的设计模式,Ioc模式,依赖注入等。

  • 强大的rest router:用简单的回调函数就可以调用,快速绑定controller和router
  • artisan:命令行工具,很多手动的工作都自动化
  • 可继承的模板,简化view的开发和管理
  • blade模板:渲染速度更快
  • ORM操作数据库
  • migration管理数据库和版本控制
  • composer也是亮点
  • 测试功能也很强大
    缺点:
    基于组件式的框架,所以比较臃肿

3、数据库优化

从结构层: web服务器采用负载均衡服务器,mysql服务器采用主从复制,读写分离
从储存层: 采用合适的存储引擎,采用三范式
从设计层: 采用分区分表,索引,表的字段采用合适的字段属性,适当的采用逆范式,开启mysql缓存
从sql语句层:结果一样的情况下,采用效率高、速度快节省资源的sql语句执行
负载均衡:

MySQL之间数据复制的基础是二进制日志文件(binary log file)。
Master 将改变记录到二进制日志中。
Slave 将 Master 的二进制日志拷贝到它的中继日志( Relay_log )
Slave 重做中继日志中的事件,将改变反映它自己的数据

mysql主从复制用途
实时灾备,用于故障切换
读写分离,提供查询服务
备份,避免影响业务

主从部署必要条件:
主库开启binlog日志(设置log-bin参数)
主从server-id不同
从库服务器能连通主库

原理:
主:log dump线程传binlog;
从:i/o线程接受读取binlog,并写入relay log文件
sql线程从relay log 文件中读取binlog并持久化

主从复制链接:blog.csdn.net/wangyuanjun…

4、如何处理负载、高并发

  • HTML静态化
  • 图片服务器分离
  • 数据库集群和库表散列及缓存: 数据库的并发连接为100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如memcache、redis。
  • 负载均衡: Apache的最大并发连接为1500,只能增加服务器,可以从硬件上着手,如F5服务器。当然硬件的成本比较高,我们往往从软件方面着手。

1、流量优化

(1) 防盗链处理(去除恶意请求)
(2) 控制大文件的下载。

2、前端优化

(1) 减少HTTP请求[将css,js等合并]

(2) 添加异步请求(先不将所有数据都展示给用户,用户触发某个事件,才会异步请求数据)

(3) 启用浏览器缓存和文件压缩

(4) CDN加速

(5) 建立独立的图片服务器(减少I/O)

3、服务端优化

(1) 页面静态化

(2) 并发处理

(3) 队列处理

4、数据库优化

(1) 数据库缓存

(2) 分库分表,分区

(3) 读写分离

(4) 负载均衡

5、web服务器优化

(1) nginx反向代理实现负载均衡

(2) lvs实现负载均衡
原文:blog.csdn.net/m_nanle_xia…

悲观锁:
通常所说的“一锁二查三更新”即指的是使用悲观锁。需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。不同的数据库对select for update的实现和支持都是有所区别的,select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。

乐观锁:
在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号或者时间戳:

1. SELECT data AS old_data, version AS old_version FROM …;
2. 根据获取的数据进行业务操作,得到new_data和new_version
3. UPDATE SET data = new_data, version = new_version WHERE version = old_version
if (updated row > 0) {
    // 乐观锁获取成功,操作完成
} else {
    // 乐观锁获取失败,回滚并重试
}
复制代码

高并发:www.cnblogs.com/phpper/p/67…

5、
mysql的默认端口

3306  
复制代码

获取IP地址

客户端 — $_SERVER['REMOTE_ADDR'];  

服务器端 — $_SERVER["SERVER_ADDR"];

gethostname — 获取主机名

ip2long — 将 IPV4 的字符串互联网协议转换成长整型数字

long2ip — 将长整型转化为字符串形式带点的互联网标准格式地址(IPV4)

例子:
$ip = gethostbyname('www.baidu.com'); //14.215.177.39
$ip2long = ip2long($ip); // 249016615

复制代码

编码转换的函数

Iconv('utf-8', 'gb2312', $str);
复制代码

6、架构类的东西
数据库的读写分离、主从复制及集群。

Nginx负载均衡

redis集群及主从

7、session与cookie的区别
cookie数据存放在第三方应用的浏览器上,session数据放在服务器上。

cookie不是很安全,别人可以分析存放在本地的COOKIE,进行COOKIE欺骗,考虑到安全应当使用session。

session会在一定时间内保存在服务器上。session用新的机制保持与客户端的同步,不依赖于客户端设置;会占用服务器资源,加大服务器端的负载,尤其当并发用户很多时,会生成大量的session,影响服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。session存储的信息更敏感,而且是以文件形式保存在服务器中,因此仍然存在着安全隐患。

单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

所以个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE

8、抽象类是一种不能被实例化的类,只能作为其他类的父类来使用。抽象类是通过关键字abstract来声明的。
抽象类与普通类相似,都包含成员变量和成员方法,两者的区别在于,抽象类中至少要包含一个抽象方法,抽象方法没有方法体,该方法天生就是要被子类重写的。 抽象方法的格式为:abstract function abstractMethod()

接口是通过 interface 关键字来声明的,接口中的成员常量和方法都是 public 的,方法可以不写关键字public,接口中的方法也是没有方法体。接口中的方法也天生就是要被子类实现的。

抽象类和接口实现的功能十分相似,最大的不同是接口能实现多继承。在应用中选择抽象类还是接口要看具体实现。 子类继承抽象类使用 extends,子类实现接口使用implements。

接口中不可以声明变量,但可以声明类常量。抽象类中可以声明各种变量

接口没有构造函数,抽象类可以有

接口中的方法默认为public,抽象类中的方法可以用public、protected、private修饰

一个类可以继承多个接口,但只能继承一个抽象类

含有抽象方法的类不一定是抽象类

抽象类

<?php
abstract class Animal {
  public $name;
  abstract public function eat($food);
}
?>

<?php
class Whale extends Animal {
  public function __construct() {
    $this->name = "Whale";
  }
  public function eat($food) {
    echo $this->name . " eat " . $food . ".\n";
  }
}
?>

<?php
  $whale = new Whale();
  $whale->eat("fish");
?>
复制代码

接口

<?php
interface IAction {
  public function eat($food);
  public function swim();
}
?>

<?php
class Whale implements IAction {
  public function eat($food) {
    echo "Whale eat " . $food . "\n.";
  }
  public swim() {
    echo "Whale is swimming.\n";
  }
}
?>

<?php
  $whale = new Whale();
  $whale->eat("fish");
?>
复制代码

interface Eat
{
    public function eat();
}

class Pig implements Eat
{
    public function eat()
    {
        echo 'pig eat ...';
    }
}

class Cat implements Eat
{
    public function eat()
    {
        echo 'cat eat ....';
    }
}

class Test
{
    function aa(Eat $animal)
    {
        $animal->eat();
    }
}
$test = new Test();
$pig = new Pig();
$cat = new Cat();
$test->aa($pig);
$test->aa($cat);
复制代码

抽象用于不同的事物,而接口用于事物的行为。 如:水生生物是鲸鱼的抽象概念,但是水生生物并不是鲸鱼的行为,吃东西才是鲸鱼的行为。 对于大型项目来说,对象都是由基本的抽象类继承实现,而这些类的方法通常都由接口来定义。 此外,对于事物属性的更改,建议使用接口,而不是直接赋值或者别的方式,

9、MySQL设计之三范式
第一范式(1NF):字段具有原子性,不可再分。 所有关系型数据库系统都满足第一范式, 数据库表中的字段都是单一属性的, 不可再分。 例如, 姓名字段, 其中的姓和名必须作为一个整体, 无法区分哪部分是姓, 哪部分是名, 如果要区分出姓和名, 必须设计成两个独立的字段。

第二范式(2NF):要求数据库表中的每个实例或行必须可以被唯一区分。 通常需要为表加上一个列, 以存储各个实例的惟一标识。 这个惟一属性列被称为主关键字或主键。

第三范式(3NF):要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。

总结
1、 每一列只有一个值(字段不可分)
2、 每一行都能区分。(有主键,非主键字段依赖主键)
3、 每一个表都不包含其他表已经包含的非主关键字信息。

反三范式
没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,提高读性能,就必须降低范式标准,适当保留冗余数据。 在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,减少了查询时的关联,提高查询效率,因为在数据库的操作中查询的比例要远远大于DML的比例。但是反范式化一定要适度,并且在原本已满足三范式的基础上再做调整的。

10、一种是表锁定(myisam存储引擎),一个是行锁定(innodb存储引擎)
1、存储引擎的使用不同,冷数据使用MyIsam 可以有更好的查询数据。活跃数据,可以使用Innodb ,可以有更好的更新速度。
2、对冷数据进行更多的从库配置,因为更多的操作是查询,这样来加快查询速度。对热数据,可以相对有更多的主库的横向分表处理。
3、对于一些特殊的活跃数据,也可以考虑使用memcache 、redis之类的缓存,等累计到一定量再去更新数据库.

11、数据库引擎

InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。

MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。

MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。

merge:用于日志和数据仓库

archive:用于日志,只有select和insert,不支持索引。

注意,同一个数据库也可以使用多种存储引擎的表。如果一个表要求比较高的事务处理,可以选择InnoDB。这个数据库中可以将查询要求比较高的表选择MyISAM存储。如果该数据库需要一个用于查询的临时表,可以选择MEMORY存储引擎。

InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “a%”

就是说在不确定的范围时,InnoDB还是会锁表的。

以下两点必须使用InnoDB:

1)可靠性高或者要求事务处理,则使用InnoDB。这个是必须的。

2)表更新和查询都相当的频繁,并且表锁定的机会比较大的情况指定InnoDB数据引擎的创建。

对比之下,MyISAM的使用场景:

1)做很多count的计算的。如一些日志,调查的业务表。

2)插入修改不频繁,查询非常频繁的。

12、数据库事务
事务是指作为单个逻辑工作单元执行的一系列操作,可以被看作一个单元的一系列SQL语句的集合。要么完全地执行,要么完全地不执行。 如果不进行并发控制,可能会产生脏读、非重复读、幻像读、丢失修改的异常情况。
事务的特性(ACID):
A、atomacity 原子性(所有过程要么都执行,要么都不执行。如果异常了那么回滚)
C、consistency 一致性(例如转账前转账后的总额度不变)
I、isolation 隔离性(只要事务还没有提交,数据都不会有变化)
D、durability 持久性(事务提交,一定发生变化)

13、事物隔离是基于锁实现的。
在DBMS中,可以把数据库锁分为行级锁(INNODB引擎)表级锁(MYISAM引擎)页级锁(BDB引擎)

行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁。特点是开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,实现简单,资源消耗较少,被大部分MySQL引擎支持。MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。特点是开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折中的页级,一次锁定相邻的一组记录。 特点是开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

14、分区分表

分区:就是把一个数据表的文件和索引分散存储在不同的物理文件中。 表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的、容易管理的部分。从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。

分表:指的是通过一定规则,将一张表分解成多张不同的表,每一个小表都是完正的一张表,都对应三个文件(MyISAM引擎:一个.MYD数据文件,.MYI索引文件,.frm表结构文件)。比如将用户订单记录根据时间成多个表。

分表与分区的区别:
实现方式上:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。

数据处理上:分表后数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面。分区则不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表还是一张表,数据处理还是由自己来完成。

提高性能上:分表后,单表的并发能力提高了,磁盘I/O性能也提高了。分区突破了磁盘I/O瓶颈,想提高磁盘的读写能力,来增加mysql性能。
在这一点上,分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的。

实现的难易度上:分表的方法有很多,用merge来分表,是最简单的一种方式。这种方式和分区难易度差不多,并且对程序代码来说可以做到透明的。如果是用其他分表方式就比分区麻烦了。 分区实现是比较简单的,建立分区表,跟建平常的表没什么区别,并且对代码端来说是透明的。 分区和分表的目的就是减少数据库的执行负担,稳定SQL性能。

分区
mysql支持的分区类型包括Range、List、Hash、Key

CREATE TABLE user (
	id INT NOT NULL auto_increment,
	username VARCHAR (10),
	PRIMARY KEY (id)
) ENGINE = INNODB charset = utf8 PARTITION BY RANGE (id)(
	PARTITION user_1 VALUES less than (10),
	PARTITION user_2 VALUES less than (20),
	PARTITION user_3 VALUES less than MAXVALUE
);
复制代码

表分区好处:
1)分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。
2)和单个磁盘或者文件系统相比,可以存储更多数据
3)优化查询。在where语句中包含分区条件时,可以只扫描一个或多个分区表来提高查询效率;涉及sum和count语句时,也可以在多个分区上并行处理,最后汇总结果。
4)分区表更容易维护。例如:想批量删除大量数据可以清除整个分区。
5)可以使用分区表来避免某些特殊的瓶颈,例如InnoDB的单个索引的互斥访问,ext3问价你系统的inode锁竞争等。

分区的限制:

  • 主键或者唯一索引必须包含分区字段,如primary key (id,username),不过innoDB的大组建性能不好。
  • 很多时候,使用分区就不要在使用主键了,否则可能影响性能。
  • 只能通过int类型的字段或者返回int类型的表达式来分区,通常使用year或者to_days等函数(mysql 5.6 对限制开始放开了)。
  • 每个表最多1024个分区,而且多分区会大量消耗内存。
  • 分区的表不支持外键,相关的逻辑约束需要使用程序来实现。
  • 分区后,可能会造成索引失效,需要验证分区可行性。

分表

// 创建一个完整表存储着所有的成员信息
CREATE TABLE `member` (
`id`  int(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
`name`  varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' ,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET = utf8 AUTO_INCREMENT = 1;

// 插入数据(第2条语句多执行几次就有了很多数据):
insert into member(name) values('a');
insert into member(name) select name from member;

// 创建两个分表tb_member1,tb_member2
DROP TABLE IF EXISTS tb_member1;
CREATE TABLE tb_member1 (
`id` INT (10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR (20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE = MyISAM DEFAULT CHARSET = utf8 AUTO_INCREMENT = 1;

DROP TABLE IF EXISTS tb_member2;
CREATE TABLE tb_member2 LIKE tb_member1;

// 创建主表tb_member
DROP TABLE IF EXISTS tb_member;
CREATE TABLE tb_member (
`id` INT (10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR (20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE = MERGE UNION = (tb_member1, tb_member2) INSERT_METHOD = LAST CHARSET = utf8 AUTO_INCREMENT = 1;

// 把数据分到两个分表中去
insert into tb_member1(id, name) select id,name from member where id%2=0;
insert into tb_member2(id, name) select id,name from member where id%2=1;
复制代码

分表存在的问题:

  • 跨库跨表的join问题
  • 额外的数据管理负担和数据运算压力(数据的定位问题和数据的增删改查的重复执行问题)

分表的几种常见方法:

  • 预先估计某个大表的数据量,将其均分为固定数量表(自增id取模、自增id两位尾数取模、对某个字段进行hash)
  • 时间增长较快的数据可以按时间拆分(按天、按月、按年等)
  • 按每个表固定记录行数拆分
  • 将很久之前的数据迁移到一张历史表

分表链接:www.cnblogs.com/johnnyzhang…

15、MySQL索引:
联合索引(复合索引)由两个或多个列的索引,可只使用索引中的一部分,更准确地说是最左侧部分(最左优先)
前缀索引对于列的值较长,比如BLOB、TEXT、VARCHAR,可建立前缀索引,即将值的前一部分作为索引
覆盖索引查询时只用去读取索引而取得数据,无需进行二次查询相关表,对于一个索引覆盖查询,通过使用explain,extra显示为using index来判断

假设建立有顺序的:c1,c2,c3,c4 这4个索引

  • 在等值查询时,更改索引列顺序,不会影响explain的执行结果,因为mysql底层会进行优化,但是推荐按照索引顺序列编写sql语句。
  • 在使用order by时,注意索引顺序、常量,以及可能会导致Using filesort的情况
  • 范围右边索引列失效,但是范围当前位置的索引是有效的
  • 范围右边索引列失效,是有顺序的:c1,c2,c3,c4,如果c3有范围,则c4失效;如果c4有范围,则没有失效的索引列,从而会使用全部索引。
  • 在最佳左前缀法则中,如果最左前列的索引失效,则后面的索引都失效。
  • 利用最佳左前缀法则:中间不能断,用到了c1和c2索引(查找),c3索引列用在排序过程中。
  • group by容易产生Using temporary

通俗理解口诀:

全值匹配我最爱,最左前缀要遵守;

带头大哥不能死,中间兄弟不能断;

索引列上少计算范围之后全失效;

LIKE百分写最右,覆盖索引不写星;

不等空值还有or,索引失效要少用。

参见:www.cnblogs.com/morewindows…

索引长度计算:
1.所有的索引字段,如果没有设置not null,则需要加一个字节。
2.定长字段,int占四个字节、date占三个字节、char(n)占n个字符。
3.对于变成字段varchar(n),则有n个字符+两个字节。
4.不同的字符集,一个字符占用的字节数不同。latin1编码的,一个字符占用一个字节,gbk编码的,一个字符占用两个字节,utf8编码的,一个字符占用三个字节。

16、

// 连接
$dbhost = 'localhost';  // mysql服务器主机地址
$dbuser = 'root';            // mysql用户名
$dbpass = '';          // mysql用户名密码
$conn = mysqli_connect($dbhost, $dbuser, $dbpass);
if (!$conn) {
    die('Could not connect: ' . mysqli_error());
}
echo '数据库连接成功!';


// 设置编码,防止中文乱码
mysqli_query($conn , "set names utf8");
 
$sql = 'SELECT id, name FROM user';
 
mysqli_select_db($conn, 'test');
$retval = mysqli_query($conn, $sql);
if(!$retval)
{
    die('无法读取数据: ' . mysqli_error($conn));
}

while($row = mysqli_fetch_array($retval, MYSQLI_ASSOC)) {
    print_r($row);
}

// 释放内存
mysqli_free_result($retval);
mysqli_close($conn);
复制代码

17、冒泡排序
如数组:$sort = [6,1,2,4,5,3]; 进行冒泡排序(从小到大)

第一轮:
 第一次:1,6,2,4,5,3
 第二次:1,2,6,4,5,3
 第三次:1,2,4,6,5,3
 第四次:1,2,4,5,6,3
 第五次:1,2,4,5,3,6

第二轮:
 第一次:1,2,4,5,3,6
 第二次:1,2,4,5,3,6
 第三次:1,2,4,5,3,6
 第四次:1,2,4,3,5,6

第三轮:
 第一次:1,2,4,3,5,6
 第二次:1,2,4,3,5,6
 第三次:1,2,3,4,5,6

第四轮:
 第一次:1,2,3,4,5,6
 第二次:1,2,3,4,5,6

第五轮:
 第一次:1,2,3,4,5,6

<?php
$arr = [6, 7, 3, 5, 9, 10, 1];
$length = count($arr);
// 轮
for ($i = 1; $i < $length; $i++) {
    // 次
    for ($j = 0; $j < $length - $i; $j++) {
    	if ($arr[$j] > $arr[$j + 1]) {
            $tmp = $arr[$j];
            $arr[$j] = $arr[$j + 1];
            $arr[$j + 1] = $tmp;
    	}
    }
}
echo '<pre>';
print_r($arr);
复制代码

18、遍历出文件夹和他下面子文件的代码

function getAllFile($dir) {
    $allFileArr = [];
    if (is_dir($dir)) {
        $res = opendir($dir);
        while ($row = readdir($res)) {
            if ($row == '.' || $row == '..') {
                continue;
            }
            if (is_file($dir . '/' . $row)) {
                $allFileArr[] = $row;
            } else if (is_dir($dir . '/' . $row)) {
                $allFileArr[$row] = getAllFile($dir . '/' . $row);
            }
        }
        closedir($res);
    }
    return $allFileArr;
}

$dir = 'E:\ruanjian\wamp64\www\learn';
echo '<pre>';
print_r(getAllFile($dir));
复制代码

19、如何防止SQL注入,XSS攻击和CSRF攻击

SQL注入:mysqli_real_escape_string()转义关键字符;

CSRF攻击:跨站攻击。防止:token、验证码

XSS攻击:alert把一些cookie信息打印出来;
过滤掉<>等关键字符串;
对数据解码,再过滤掉危险标签、属性和事件等;
DOM XSS的发生主要是在JS中使用eval造成的,所以应当避免使用eval语句
复制代码

XSS危害

  • 通过document.cookie盗取cookie
  • 使用js或css破坏页面正常的结构与样式
  • 流量劫持(通过访问某段具有window.location.href定位到其他页面)
  • Dos攻击:利用合理的客户端请求来占用过多的服务器资源,从而使合法用户无法得到服务器响应。
  • 利用iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作。
  • 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动。

20、PHP程序工作的具体过程

  PHP的运行原理就是Apache、PHP、浏览器之间的协作过程:

  ①当用户在浏览器地址中输入要访问的PHP页面文件名,然后回车就会触发这个PHP请求,并将请求传送化支持PHP的WEB服务器(apache)。

  ②WEB服务器(apache)接受这个请求,并根据其后缀进行判断如果是一个PHP请求,WEB服务器(apache)从硬盘或内存中取出用户要访问的PHP应用程序,并将其发送给PHP引擎程序。

  ③PHP引擎程序将会对WEB服务器(apache)传送过来的文件从头到尾进行扫描并根据命令从后台读取,处理数据,并动态地生成相应的HTML页面。

  ④PHP引擎将生成HTML页面返回给WEB服务器(apache)。WEB服务器(apache)再将HTML页面返回给客户端浏览器,最后一个完整的页面基于通过浏览器展现在我们眼前。

21、HTTP协议
HTTP请求由三个部分组成,分别是:请求行、请求头部、空行和请求正文。
HTTP响应由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
第一部分:状态行,由HTTP协议版本号、状态码、状态消息三部分组成。
第一行为状态行,(HTTP/1.1)表明HTTP版本为1.1版本,状态码为200,状态消息为(ok)

第二部分:消息报头,用来说明客户端要使用的一些附加信息
第二行和第三行为消息报头, Date:生成响应的日期和时间;Content-Type:指定了MIME类型的HTML(text/html),编码类型是UTF-8
第三部分:空行,消息报头后面的空行是必须的
第四部分:响应正文,服务器返回给客户端的文本信息。
空行后面的html部分为响应正文。

请求类型GET、POST、HEAD 1.1版还新增了许多动词方法:PUT、PATCH、HEAD、 OPTIONS、DELETE

HTTP请求报文头属性:
Accept:告诉服务端 客户端接受什么类型的响应。
Cookie:客户端的Cookie就是通过这个报文头属性传给服务端的
Referer:表示这个请求是从哪个URL过来的,假如你通过google搜索出一个商家的广告页面,你对这个广告页面感兴趣,鼠标一点发送一个请求报文到商家的网站,这个请求报文的Referer报文头属性值就是http://www.google.com。
Cache-Control:对缓存进行控制

HTTP响应报文头属性:
Cache-Control:响应输出到客户端后,服务端通过该报文头属告诉客户端如何控制响应内容的缓存
ETag:一个代表响应服务端资源(如页面)版本的报文头属性,如果某个服务端资源发生变化了,这个ETag就会相应发生变化。它是Cache-Control的有益补充,可以让客户端“更智能”地处理什么时候要从服务端取资源,什么时候可以直接从缓存中返回响应。
Location:让页面Redirect到一个某个A页面中,其实是让客户端再发一个请求到A页面,这个需要Redirect到的A页面的URL,其实就是通过响应报文头的Location属性告知客户端的
Set-Cookie:服务端可以设置客户端的Cookie

常见状态码
1xx 消息,一般是告诉客户端,请求已经收到了,正在处理,别急...
2xx 处理成功,一般表示:请求收悉、我明白你要的、请求已受理、已经处理完成等信息.
3xx 重定向到其它地方。它让客户端再发起一个请求以完成整个处理。
4xx 处理发生错误,责任在客户端,如客户端的请求一个不存在的资源,客户端未被授权,禁止访问等。
5xx 处理发生错误,责任在服务端,如服务端抛出异常,路由出错,HTTP版本不支持等。

具体如下:
2XX系列:代表请求已成功被服务器接收、理解、并接受。
200状态码:请求已成功,请求所希望的响应头或数据体将随此响应返回
201状态码:表示请求成功并且服务器创建了新的资源,且其 URI 已经随Location 头信息返回。假如需要的资源无法及时建立的话,应当返回 '202 Accepted'

4XX系列:表示请求错误。代表了客户端看起来可能发生了错误,妨碍了服务器的处理。
401状态码:请求要求身份验证。对于需要登录的网页,服务器可能返回此响应。
403状态码:服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。
404状态码:请求失败,请求所希望得到的资源未被在服务器上发现。

5xx系列:代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。
500状态码:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。
503状态码:由于临时的服务器维护或者过载,服务器当前无法处理请求。

blog.csdn.net/u010256388/… 22、设计模式
参考链接:www.cnblogs.com/leedaily/p/…

23、向php脚本传递参数:

  • php -r "var_dump($argv);" -- -h(如果要传递的参数开头为-,那么得使用参数列表分隔符 -- 才能正确传参)
  • test.php 假设该文件在当前目录下,代码:
#!/usr/bin/php   
<?php var_dump($argv);?>    

// 在php文件开头加入#!/usr/bin/php,即可直接传递以-为开头得参数
./test.php -h -- foo  
复制代码

24、redis和memcached区别

  • redis 系统库有个快照,即突然断电,数据还会存在,而memached 就没了
  • memcached 是简单的键值对,Key-Value, redis 支持的存储方式(字符串,双向链表,哈希,集合,有序集合)很多,应用场景很多
  • redis 性能比memached 要高
  • Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路 IO 复用模型。

25、SQL注入
SQL注入攻击是黑客对数据库进行攻击的常用手段之一。在编写代码的时候,没有对用户输入数据的合法性进行判断,注入者可以在表单中输入一段数据库查询代码并提交,程序将提交的信息拼凑生成一个完整sql语句,服务器被欺骗而执行该条恶意的SQL命令。注入者根据程序返回的结果,成功获取一些敏感数据,甚至控制整个服务器,这就是SQL注入。

26、HTTP与HTTPS的区别?
HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HTTP协议传输隐私信息非常不安全,为了保证这些隐私数据能加密传输,于是网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。简单来说,HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。 HTTPS和HTTP的区别主要如下:

  • https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
  • http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
  • http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
  • http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

27、从输入URL到页面加载发生了什么
segmentfault.com/a/119000000…

28、消息队列
从本质上说消息队列就是一个队列结构的中间件,也就是说消息放入这个中间件之后就可以直接返回,并不需要系统立即处理,而另外会有一个程序读取这些数据,并按顺序进行逐次处理。
也就是说当你遇到一个并发特别大并且耗时特别长同时还不需要立即返回处理结果,使用消息队列可以解决这类问题。

业务系统入队->消息队列出队->队列处理系统
由一个业务系统进行入队,把消息逐次插入到消息队列中,插入成功之后直接返回成功的结果,后续会有一个消息处理系统,这个系统会把消息系统中的记录逐次进行取出并进行处理,完成一个出队的流程。

www.cnblogs.com/dump/p/8243…

29、定时脚本
blog.csdn.net/xf_come_on/…

30、网络7层协议
7 应用层
6 表示层
5 会话层
4 传输层
3 网络层
2 数据链路层
1 物理层
7、6、5、4层定义了应用程序的功能
3、2、1层主要面向通过网络的端到端的数据流

TCPUDP
是否连接面向连接面向非连接
传入可靠性可靠不可靠
引用场景传输大量数据传输小量数据
速度
举例银行windows的ping命令 qq发消息

HTTP协议即超文本传送协议(Hypertext Transfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。由于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”。
Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口。创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

WebSocket同HTTP一样也是应用层的协议,但是它是一种双向通信协议,是建立在TCP之上的。在WebSocket中,只需要服务器和浏览器通过HTTP协议进行一个握手的动作,然后单独建立一条TCP的通信通道进行数据的传送。

http和scoket区别:
HTTP是基于应用层,socket是基于传输层(tcp/udp)

HTTP连接使用的是"请求—响应"的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。在请求结束后,会主动释放连接。
通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。

视频,图片,断点续传的情况下要用socket,http的协议的无状态性实现不了这个功能。

http不断请求发送的缺点:会导致过多不必要的请求,浪费流量和服务器资源,每一次请求、应答,都浪费了一定流量在相同的头部信息上

WebSocket与HTTP的相同点:
1、都是一样基于TCP的,都是可靠性传输协议。
2、都是应用层协议
不同点:
1、WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
2、WebSocket是需要握手进行建立连接的。

31、 mysql时间
date_sub('2012-05-25',interval 1 day) 表示 2012-05-24
date_sub('2012-05-25',interval 0 day) 表示 2012-05-25
date_sub('2012-05-25',interval -1 day) 表示 2012-05-26
date_sub(curdate(),interval 1 day) 表示 2013-05-19
date_sub(curdate(),interval -1 day) 表示 2013-05-21
date_sub(curdate(),interval 1 month) 表示 2013-04-20
date_sub(curdate(),interval -1 month) 表示 2013-06-20
date_sub(curdate(),interval 1 year) 表示 2012-05-20
date_sub(curdate(),interval -1 year) 表示 2014-05-20

// 获取昨天 跟 今天 00:00:00的 时间戳
select unix_timestamp(DATE_SUB(CURDATE(),INTERVAL 1 day)), unix_timestamp(date_sub(curdate(), interval 0 day));

// 日期转时间戳
SELECT UNIX_TIMESTAMP('2018-10-31');

// 时间戳转日期
select FROM_UNIXTIME(1540915200, '%Y-%m-%d');

32、

//奇偶数
$a = [6, 7, 8, 9];
$arr = array_filter($a, function ($v) {
    return ($v & 1);
});
返回:
[
  1 => 7
  3 => 9
]

第一种:
$file = 'E:\php1\wamp64\www\test.txt';
$content = file($file);
foreach ($content as $key => $value) {
    $value = mb_convert_encoding($value, 'utf-8', 'gbk');
    $v = explode("\t", $value);
}

第二种:
$handle = fopen($file, 'r');
if ($handle) {
    while (($row = fgets($handle)) !== false) {
        $row = mb_convert_encoding($row, 'utf-8', 'gbk');
        $v = explode("\t", $row);
    }
    fclose($handle);
}

// 当前月份的第一天跟最后一天
$monthFirstDay = date('Y-m-01', strtotime(date("Y-m-d")));
$monthLastDay = date('Y-m-d', strtotime($monthFirstDay . ' +1 month -1 day'));

// 指定日期的上个月的最后一天
$lastDay = date('Y-m-t', strtotime('last month', strtotime('20181116'))); //2018-10-31

$arr = range('a', 'z');
$str = implode($arr);// abcdefghijklmnopqrstuvwxyz

$a = "aa";
$b = "bb";
// 交换两个变量的值
var_dump([$a, $b]); // ['aa', 'bb']
list($a, $b) = [$b, $a];
var_dump([$a, $b]); ['bb', 'aa']

// 反转字符串
function mb_strrev($str)
{
    $r = '';
    for ($i = mb_strlen($str); $i >= 0; $i--) {
        $r .= mb_substr($str, $i, 1);
    }
    return $r;
}
echo mb_strrev("☆❤world我"); 
// 我dlrow❤☆
复制代码
echo mb_internal_encoding(); // UTF-8
$str = "AB. cb 测试的"; 
echo strlen($str);//一个UTF8的中文字符=3个字节,所以为3+1+2+1+9=16
echo mb_strlen($str, "utf-8");//UTF-8会将中文字符当成一个字符,所以为3+1+2+1+3=10
echo mb_strlen($str, "gbk");//gbk,一个中文字符当成1.5个字符,3+1+2+1+4.5=11.5
复制代码
empty() 可以用来判定所有的数据类型是否为空或假,而 is_null 与 isset 基本一样,只能用来判断是否为NULL和未定义。
复制代码
echo count(strlen('https://www.baidu.com/'));
// 结果:1,count(var)是用来统计数组或对象的元素个数的。当var是null或者空数组时,结果为0。如果var是普通变量,则返回1。正常情况下返回var中的元素或属性个数。
复制代码

PHP不鼓励加结束标签
可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白
影响最多的时候应该是在使用 include 和 require 的时候,加了结束标签如果又在后面加了空格都有可能会引起多余的输出、php错误、之后的输出无法显示、空白页,因为session_start()之类的函数的原因(HTTP报文是header在前,body在后。当你在session_start()之前有了body输出,就不能再设定header set-cookie了,而session就是依赖cookie)

依赖注入
ORM
mysql主从复制 读写分离
分布式
单元测试

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值