1.什么是面向对象?
面向对象是程序的一种设计方式,它利于提高程序的重要性,使程序更加清晰。
主要特征:封装、继承、多态。
三大特点:
a.封装性:也称为信息隐藏,就是将一个类的使用和实现分开,只保留部分接口和方法与外部联系,或者说只公开了一些供开发人员使用的方法。于是开发人员只需要关注这个类如何使用,不用去关心具体的实现过程,这样就能实现MVC的分工合作,也可以有效的避免程序之间相互依赖,从而实现代码模块之间的松耦合。
b.继承性:子类自动继承父类中的属性和方法,并且可以添加新的属性和方法或者对父类的部分属性和方法进行重写。继承增加了代码的可重用性。PHP只支持单继承,一个子类只能继承一个父类。
c.多态性:子类继承了父类中的属性和方法,并对其中部分方法进行重写。于是多个子类中虽然都具有用一个方法,但是这些子类实例化的对象调用这些相同的方法后可以得到不同的结果,这就是多态性。
2.面向对象的七大原则:
一个类只负责一项职责。
- 开放封闭原则
一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭
子类可扩展父类功能,但不能改变父类原有的功能。
高层模块不应该依赖底层模块,二者都应该依赖细节,细节应该依赖抽象。
- 接口隔离原则
客户端不应该依赖它不需要的接口,并尽力实现单一职责原则。例:订单接口可分为下单接口、发货接口、退货接口等,而不能将订单相关的方法都定义到一个接口中。
- 迪米特原则
又称为 最少知道法则,只与朋友通信,表示一个对象应该对其他对象表示最少的了解,也就是一个类除了提供公共方法,不对外泄露任何信息。
- 合成/聚合复用原则
它要求在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
如果要使用继承关系,则必须严格遵循里式替换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
3.合并两个数组有几种方式,比较他们的异同
方式:
array_merge()、+、array_merge_recursive()
异同:
array_merge()简单的合并数组;
array_merge_recursive()合并两个数组,如果数组中有完全一样的数据,将它们递归合并;array_merge()和‘+’:合并两个数组,前者将值作为新数组的键。
4.PHP的is_writeable()函数存在bug,无法准确判断一个目录/文件是否可写,请写一个函数来判断目录/文件是否绝对可写
答:其中bug存在两个方面,
1.在Windows中,当文件只有只读属性时,is_writeable()函数才返回FALSE,当返回TRUE时,改文件不一定是可写的。
如果是目录,在目录中新建文件并通过打开文件来判断;
如果是文件,可通过打开文件(fopen),来测试文件是否可写。
2.在Unix中,当PHP配置文件中开启safe_mode时(safe_mode=on),is_writeable()同样不可用。
函数:
function is_really_writable($file)
{
if (DIRECTORY_SEPARATOR === '/') {
return is_writable($file);
}
if (is_dir($file)) {
$file = rtrim($file, '/') . '/' . md5(mt_rand());
if (($fp = @fopen($file, 'ab')) === FALSE) {
return FALSE;
}
fclose($fp);
@chmod($file, 0777);
@unlink($file);
return TRUE;
} elseif (!is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE) {
return FALSE;
}
fclose($fp);
return TRUE;
}
5.PHP的垃圾收集机制是怎样的?
PHP可以自动进行内存管理,清除不再需要的对象。
PHP使用了引用计数(reference counting)这种单纯的垃圾回收(garbage collection)机制。
每个对象都内含一个引用计数器,每个reference连接到对象,计数器加1。当reference离开生存空间或被设为null,计数器减1。当某个对象的引用计数器为零时,PHP知道你将不再需要这个对象,就会释放所占的内存空间。
6.写一个函数,尽可能高效的,从一个标准的URL里提取出文件的扩展名
例如:http://www.abc.com/de/wander.php?id=001 需要取出 ‘php’ 或者 ‘.php’
//方案一
function getExt1($url){
$arr = parse_url($url);
//Array([scheme]=>http [host]=>www.abc.com [path]=>/de/wander.php [query]=>id=001)
$file = basename($arr['path']); //wander.php?id=001
$ext = explode('.',$file);
return $ext[count($ext)-1];
}
//方案二
function getExt2($url){
$url = basename($url); //wander.php?id=001
$pos1 = strpos($url,'.'); //6
$pos2 = strpos($url,'?'); //10
if (strstr($url,'?')) {
return substr($url,$pos1+1,$pos2-$pos1-1);
} else {
return substr($url,$pos1);
}
}
$url= "http://www.abc.cn/de/wander.php?id=001";
echo getExt1($path);
echo "<br />";
echo getExt2($path);
7.使用正则表达式提取一段表示语言(html或XML)
代码段中指定标签的指定属性值(需要考虑属性值不规则的情况,如大小写不敏感,属性名值与等号之间有空格等)此处假设需要提取test标签的attr属性值,请自行构建改标签的串(腾讯)
代码如下:
<?php
header("content-type:text/html;charset=utf-8");
function getAttrValue($str,$tagName,$attrName){
$pattern1="/<".$tagName."(s+w+s*=s*(['"]?)([^'"]*)())*s+".$attrName."s*=s*(['"]?)([^'"]*)()(s+w+s*=s*(['"]?)([^'"]*)(9))*s*>/i";
$arr=array();
$re=preg_match($pattern1,$str,$arr);
if($re){
echo"<br/>$arr[6]={$arr[6]}";
}else{
echo"<br/>没找到。";
}
}
// 示例
$str1="<test attr='ddd'>";
getAttrValue($str1,"test","attr");//找test标签中attr属性的值,结果为ddd
$str2="<test2 attr='ddd'attr2='ddd2't1="t1 value"t2='t2 value'>";
getAttrValue($str2,"test2","t1");//找test2标签中t1属性的值,结果为t1 value
?>
8.php中web上传文件的原理是什么,如何限制上传文件的大小?
上传文件的表单使用post方式,并且要在form中添加enctype=“multipart/form-data“。
一般可以加上隐藏域:<input type= hidden name = 'MAX_FILE_SIZE' value=1024>,位置在file域前面。value的值一般是上传文件的客户端字节限制。可以避免用户在花时间等待上传大文件之后才发现文件上传过大失败的麻烦。
使用file文件域来选择上传的文件,当点击提交按钮之后,文件会被上传到服务器的临时目录,在脚本运行结束时会被销毁,所以应该在在脚本结束之前,将其移动到服务器的某个目录下,可以通过函数move_uploaded_file()来移动临时文件,获取临时文件的信息可以使用 $_FILES。
限制文件大小的因素有:
客服端隐藏域的MAX_FILE_SIZE的数值(可以被绕开)
服务器端的upload_max_filesize,post_max_size和memory_limit。这几项不能够用脚本来设置。
自定义文件大小限制逻辑。即使服务器的限制是能够自己决定,也会有特殊情况考虑,所以这个限制方式经常是必要的。
9.请说明PHP中传值和传引用的区别,什么时候传值什么时候引用?
按值传递:函数范围内对值的任何改变在函数外部都会被忽略。
按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改
优缺点:按值传递时,PHP必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。按引用传递不需要复制值。对于性能提高很有好处。
10.mysql数据库中的字段类型varchar和char的主要区别是什么?
char:
- char表示定长字符串,长度是固定的;
- 如果插入数据的长度小于char的固定长度时,则用空格填充;
- 因为长度固定,所以存取速度要比varchar快很多,甚至能快50%,但正因为其长 度固定,所以会占据多余的空间,是空间换时间的做法;
- 对于char来说,最多能存放的字符个数为255,和编码无关
varchar:
- varchar表示可变长字符串,长度是可变的; 插入的数据是多长,就按照多长来存储;
- varchar在存取方面与char相反,它存取慢,因为长度不固定,但正因如此,不占 据多余的空间,是时间换空间的做法;
- 对于varchar来说,最多能存放的字符个数为65532
日常的设计,对于长度相对固定的字符串,可以使用char,对于长度不确定的,使用 varchar更合适一些。
11.php7的新特性
标量类型声明:PHP7中的函数的形参类型声明可以为标量。在PHP5中只能是类名、接口、array或者callable(PHP5.4,既可以是函数,包括匿名函数),现在能使用string、int、float、和bool。
返回值类型声明:增加了对返回值类型声明的支持。类似于参数类型声明,返回值类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同。
null合并运算符:由于日常使用中大量同时使用三元表达式和isset()的情况,null合并运算符使得变量存在且值不为null,它就会返回自身值,否则返回它的第二个操作数。
use加强:从同一namespace导入的类、函数和常量现在可以通过单个use语句一次性导入匿名类,现在支持通过new class 来实例化一个匿名类。
12.如何处理负载,高并发?
1、html静态化
效率最高、消耗最少的就是纯静态化的HTML页面,所有我们尽可能使我们的网站页面采用静态化实现,这个最简单的方法其实也是最有效的方法。
2、图片服务器分离
把图片单独存储,尽可能减收图片等大流量的开销,可以放在一些相关的平台上,如七牛云、腾讯云等。
3、数据库集群和库表散列及缓存
数据库的并发链接为100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来入手。另外尽量减少数据库的访问,可以使用缓存数据库如memcache、redis等。
4、镜像
尽量减少下载,可以把不同的请求分发到多个镜像端。
5、负载均衡
Apache的最大并发连接为1500,只能增加服务器,可以从硬件上着手,如F5服务器,当然硬件的成本比较高,我们往往是从软件方面着手。
13.常见的PHP安全性攻击SQL注入:
用户利用在表单字段输入SQL语句的方式来影响正常SQL的执行。
防止:使用mysql_real_escape_string()过滤数据 手动检查每一数据是否为正确的数据类型,使用预处理语句并绑定变量。
参数化SQL: 是指在设计与数据库链接并访问数据时,需要再填入数值或数据的地方,试用参数(parameter)来给值,用@或?来表示参数。
XSS攻击:跨站点脚本攻击,由用户输入一些数据到你的网站,其中包括客户端脚本(通常JavaScript)。如果你没有过滤就输出数据到另一个web页面,这个脚本将被执行。
防止:为了防止xss攻击,使用PHP的htmlentitles()函数过滤在输出到浏览器。
CSRF:跨站点请求伪造,是指一个页面发出的请求,看起来像网站的信任用户,但是是伪造的。
防止:一般来说,确保用户来自你的表单,并且匹配每一个你发出去的表单。有两点一定要记住:对用户会话采用适当的安全措施,例如:每一个会话更新id和用户使用SSL。生成另一个一次性的令牌并将其嵌入表单,保存在会话中(一个会话变量),在提交时检查它。如laravel中的_token。
代码注入:代码注入是利用计算机漏洞通过无效数据造成的。问题在于,当你不小心执行任意代码,通常通过文件包含。写的很糟糕的代码可以允许一个远程文件包含并执行。如许多PHP函数,如require可以包含URL或文件名。
防止:过滤用户输入,在php.ini中设置禁用allow_url_fopen和allow_url_include。这将禁用require、include、fopen的远程文件。
14.静态化如何实现?伪静态如何实现?
1、静态化是指页面静态化,就是实实在在的静态化文件,不需要查询数据库就可以直接从文件中获取数据,指的是真静态。
实现方式主要有两种:
a、我们在添加信息入库的时候就生成的静态文件,也成为模本替换技术。
b、用户在访问我们的页面时先判断是否有对应的缓存文件存在,如果存在直接读取缓存,不存在就读取数据库,同时生成缓存文件。
2、伪静态不是真正意义上的静态化,之所以使用伪静态,主要是为了SEO推广,搜索引擎对动态的文件获取难度大,不利于网站推广。
实现原理:基于Apache或Nginx的rewrite。
方式主要有两种:
a、直接在配置虚拟机的位置配置伪静态,这个每次修改都要重启web服务器。
b、采用分布式的,可以在网站的根目录上创建‘.htaccess’的文件,在里面配置相应的重写规则来实现伪静态,这种方式重写时不需要重启web服务器,且结构上比较清晰。
15、说说对SQL语句优化有哪些方法?
1、where子句中:where表之间的连接必须写在其他where条件之前,那些可以过滤最大数量记录的条件必须写在where子句的末尾,having写在最后。
2、用exists代替in、用not exists代替 not in。
3、避免在索引列上使用计算。
4、避免在索引列上使用is null 和is not null 。
5、对查询进行优化,应该尽量避免全表扫描,首先应该考虑在where及order by 涉及的列上建立索引。
6、应该尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用而进行全表扫描。
7、应尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。
8、应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描。
如:
select id from t where num=10 or num=20 #可以这样查询: select id from twhere num=10union allselect id from twhere num=20
9、索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
10、在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。
16、MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?
1、设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。
2、选择合适的表字段数据类型和存储引擎,适当的添加索引。
3、做mysql的主从复制读写分离。
4、对数据表进行分表,减少表单中的数据提高查询速度。
5、添加缓存机制,如Redis,memcached等。
6、对不经常改动的页面,生成静态页面(比如做ob缓存)。
7、书写高效率SQL。比如select*from tabel 改为 select field_1,field_2 from table。
17、对于大流量的网站,采用什么样的方法来解决各页面访问量统计问题?
1、确认服务器是否能支持当前访问量。
2、优化数据库访问。
3、禁止外部访问链接(盗链),比如图片盗链。
4、控制文件下载。
5、做负载均衡,使用不同主机分流。
6、使用浏览统计软件,了解访问量,有针对性的进行优化。
18、谈谈你对mysql引擎中的MyISAM与InnoDB的区别理解?
1、存储结构
MyISAM:每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD(MYData)。索引文件的扩展名是.MYI(MYIndex)。
InnoDB:所有的表都保存在弄一个数据文件中(也可能是多个文件,或者独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。
2、存储空间
MyISAM:可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。
InnoDB:需要更多地内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。
3、可移植性、备份及恢复
MyIASM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。
InnoDB:免费的方案可以是拷贝数据文件、备份binlog,或者用mysqldump,在数据量达到几十G的时候就相对痛苦了。
4、事务支持
MyIASM:强调的是性能,每次查询都具有原子性,其执行速度比InnoDB类型更快。但是不提供事务支持。
InnoDB:提供事务支持事务,外部键等高级数据库功能。具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe(ACID compliant))型表。
5、AUTO_INCREMENT
MyISAM:可以和其他字段一起建立联合索引。引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。
InnoDB:InnoDB中必须包含该字段的索引。引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列。
6、表锁差异
MyISAM:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。
InnoDB:支持事务和行级锁,是innodb的最大特色。行锁大幅度提高了多用户并发操作的新能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。
7、全文索引
MyISAM:支持 FULLTEXT类型的全文索引
InnoDB:不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。
8、表主键
MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。
InnoDB:如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。
9、表的具体行数
MyISAM:保存有表的总行数,如果select count(*) from table;会直接取出出该值。
InnoDB:没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。
10、CURD操作
MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。
InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令。
11、外键
MyISAM:不支持
InnoDB:支持
通过上述的分析,基本上可以考虑使用InnoDB来替代MyISAM引擎了,原因是InnoDB自身很多良好的特点,比如事务支持、存储 过程、视图、行级锁定等等,在并发很多的情况下,相信InnoDB的表现肯定要比MyISAM强很多。另外,任何一种表都不是万能的,只用恰当的针对业务类型来选择合适的表类型,才能最大的发挥MySQL的性能优势。如果不是很复杂的Web应用,非关键应用,还是可以继续考虑MyISAM的,这个具体情况可以自己斟酌。
19.Redis和memcached缓存的区别?
总结一:
1、数据类型
Redis数据类型丰富,支持set list 等类型
memcached支持简单数据类型,需要客户端自己处理复杂对象
2、持久性
Redis支持数据落地持久化存储
memcached不支持数据持久存储
3、分布式存储
Redis支持master-slave复制模式
memcached可以使用一致性hash做分布式
value大小不同
memcache是一个内存缓存,key的长度小于250字符,单个item存储要小于1M,不适合虚拟机使用,
4、数据一致性不同
Redis使用的是单线程模型,保证了数据按顺序提交。
memcache需要使用cas保证数据一致性。CAS(Check and Set)是一个确保并发一致性的机制,属于‘乐观锁’范围;原理和简单:拿到版本号,操作,对比版本号,如果一致就操作,不一致就放弃任何操作。
5、cup利用
Redis单线程模型只能使用一个cup,可以开启多个Redis进程。
总结二:
1、Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcache相比一个最大的区别。
2、Redis不仅仅支持简单的k/v类型的数据,同时还提供list、set、hash等数据结构的存储。
3、Redis支持数据的备份,即master-slave模式的数据备份。
4、Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
我个人认为最本质的不同是Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而memcached只是简单的k/v缓存。
总结三:
Redis和memcached的不同在于:
1、存储方式:
memcached把数据全部存在之中,断点后会挂掉,数据不能超过内存大小
Redis有部分存在硬盘上,这样能保证数据的持久性。
2、数据支持类型:
Redis在数据支持上要比memcached多的多。
3、使用底层模型不同:
新版本的Redis直接自己构建了VM机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4、运行环境不同:
Redis目前官方只支持Linux上运行,从而省去了对于其他系统的支持,这样的话可以把更好的把精力用于本系统环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上。
redis的内容是可以落地的,就是说跟MongoDB有些类似,然后redis也可以作为缓存,并且可以设置master-slave
20、Redis消息队列先进先出需要注意什么?
答:通常使用一个list来实现队列操作,这样有一个小限制,所有的任务统一都是先进先出,如果想优先处理某个任务就不太好处理了,这就需要让队列有优先级的概念,我们就可以优先处理高级别的任务,实现方式有以下几种方式:
1)单一列表实现:队列正常的操作是左进右出(lpush,rpop)为了先处理高优先级任务,在遇到高级别任务时,可以直接插队,直接放入队列头部(rpush),这样,从队列头部(右侧)获取任务时,取到的就是高优先级的任务(rpop)。
2)使用两个队列,一个普通队列,一个高级队列,针对任务的级别放入不同的队列,获取任务时也很简单,redis的BRPOP命令可以按顺序从多个队列中取值,BRPOP会按照给出的 key 顺序查看,并在找到的第一个非空 list 的尾部弹出一个元素,redis> BRPOP list1 list2 0
list1 做为高优先级任务队列 list2 做为普通任务队列 这样就实现了先处理高优先级任务,当没有高优先级任务时,就去获取普通任务 方式1 最简单,但实际应用比较局限,方式3可以实现复杂优先级,但实现比较复杂,不利于维护 方式2 是推荐用法,实际应用最为合适
21、Redis如何防止高并发?
答:其实Redis是不会存在并发问题的,因为它是单线程的,再多的命令都是一个接一个的去执行的。我们用的时候,可能会出现并发问题,比如获得和设定这一对。
Redis的为什么有高并发问题?
Redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。由于单线程所以redis本身并没有锁的概念,多个客户端连接并不存在竞争关系,但是利用jedis等客户端对redis进行并发访问时会出现问题。发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。
同时,单线程的天性决定,高并发对同一个键的操作会排队处理,如果并发量很大,可能造成后来的请求超时。
在远程访问redis的时候,因为网络等原因造成高并发访问延迟返回的问题。
解决办法:
在客户端将连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
服务器角度,利用setnx变向实现锁机制。
22、PHP与那些编程语言相似?
Perl、C
23、PHP的全程?
hypwetext Perprocessor (超文本预处理器)
24、PHP是否支持多继承?
PHP只支持单继承。使用关键字extends。
25、使用final修饰的类和方法代表什么意思?
final修饰的类不允许被继承,修饰的方法不允许被重写。
26、PHP中如何比较两个对象?
可以使用 ‘==’ 来比较两个对象是否为同一实例,并且拥有相同的属性和属性值。
27、PHP和JavaScript是如何交互的?
PHP和JavaScript无法直接进行交互,因为PHP是一种服务器端语言,而JavaScript是一种浏览器语言。但是可以交换变量,因为PHP可以生成将由浏览器执行的JavaScript代码,并且通过URL将特定的变量传递回PHP。
28、PHP处理图片需要添加什么扩展?
需要添加GD库执行处理图片功能。
29、获取图片属性(size、width和height)的函数是什么?
- 获取图片大小size:gettimagesize()
- 获取图片宽度width: imagesx()
- 获取图片高度height:imagesy()
30、include() 和 require() 在执行失败的情况下有什么不同?
- include() 会产生一个禁告,不影响后去程序的执行
- require() 会产生一个致命错误,后去程序停止执行
31、函数的作用?
- is_numeric():检查是否为数字。
- ctype_alnum():检查是否为字母数字字符。
- empty():检查变量是否具有值。
- unlink():用于文件系统处理,删除文件。
- unset():用于变量管理,可以是变量变为未定义。
- stripslash():删除字符串中的转义字符。
- get_magic_quotes_gpc():告诉我们魔术引号
32、怎么在PHP中定义常量?
- 使用define()函数定义,语法“define(常量名, 常量值,是否大小写敏感)”;
- 使用const关键字定义,语法“const 常量名 = 常量值;”。
33、如何在PHP中强制转化类型?
1. (int) (bool) (float) (string) (array) (object)
2. intval() floatval() strval()
3.settype()
34、PHP中三元运算符如何使用?
(条件)? (返回值1) : (返回值2)
若条件为真,则返回值1,
若条件为假,则返回值2.
35、函数func_num_args()的作用是什么?
函数 func_num_args() 用于提供传递给函数的参数数量
36、如果变量$var1 = 10,变量$var2 = 'var1' ,那么$$var2的值为多少?
$$var2 = $var1 ,$var1 = 10
所有 $$var2 值为10
37、通过 ::访问意味着什么?
:: 用于访问不需要对象初始化的静态方法。
38、永久性cookie的含义是什么?
永久性的cookie存储在浏览器计算机的cookie文件中,默认情况下,cookie是临时的,关闭浏览器后,cookie会被删除。
39、会话合适结束?
会话在PHP建表完成时自动结束,也可以使用session_write_close()手动结束。
40、session_unregister()和session_unset()有什么区别?
- session_unregister():从当前会话中注销全局变量
- session_unset():释放所有会话变量
41、$_FILES['userfile']['name']和$_FILES['userfile']['tmp_name']有什么区别?
- $_FILES['userfile']['name'] :表示客户端上传文件原始名称
- $_FILES['userfile']['tmp_name']:表示服务器上存储的文件的临时文件名
42、上传文件出问题时,如何获取错误信息?
$_FILES['userfile']['error'] 包括了上传文件有关的错误代码。
43、如何更改上传文件大小的最大值?
通过修改php.ini中的upload_max_filesize来修改上传文件大小的最大值。
44、函数strstr() 和函数stristr() 有什么区别?
函数 strstr ($haystack, $needle, $before_needle = null)
区别:stristr() 除了不区分大小写之外,与 strstr() 完全相同。
45、PHP中默认会话时间是什么?
PHP中默认会话时间是直到浏览器关闭为止。
46、http状态码
1、状态码分类:
- 1××:信息,服务器收到请求
- 2××:成功
- 3××:重定向
- 4××:客户端错误
- 5××:服务端错误
2、常用状态码
- 200:请求成功
- 301:永久重定向
- 302:临时移动
- 400 bad request:客户端请求语法错误
- 401 unauthorized:客户端没有权限
- 403 forbidden :服务器拒绝客户端请求
- 404 not found :客户端请求资源不存在
- 500 Internal Server Error : 服务器内部错误
- 502 bad gateway :作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接受到无效的响应。
- 503 service unavailable :超载或系统维护
- 504 Gateway timeout :网关超时
3、502的原因及解决办法
原因:Nginx将请求提交给网关(php-fpm)处理异常导致
1)fastcgi 缓冲区设置过小
fastcgi_buffer_size 32k;
2)php-cgi的进程数设置过少
查看FastCgi进程数:
netstat -anpo | grep "php-cgi"| wc -l
调整参数最大子进程数:
max_children
一般按照单个进程20M计算需要需要设置的子进程数
3)max_requests(内存溢出或频繁重启)
参数指明每个children最多能处理的请求数量,到达最大值之后会重启children。
设置过小可能导致频繁重启children:
php将请求轮询给每个children,在大流量的场景下,每一个children 到达最大值的时间差不多,如果设置过小可能多个children 在同一时间关闭,nginx无法将请求转发给php-fpm,cpu降低,负载变高。
设置过大可能导致内存泄露
4)php执行时间超过nginx等待时间
fastcgi_connect_timeout
fastcgi_send_timeout
fastcgi_read_timeout
5)fastcgi执行时间
max_execution_time
47、http和HTTPS的区别
- 端口:http:80 HTTPS:443
- http无状态 ,https是http+ssl构建的可进行加密传输的协议
- http明文传输 ,HTTPS加密传输
- http更快 ,三次握手三个包,HTTPS需要12个包(3个tcp包和9个ssl握手包)
48、mysql的几个概念
- 主键(primary key):能够唯一表示表中某一行的属性或属性组。一个表只能有一个主键,但可以有多个候选索引。主键常常与外键构成参照完整性约束,防止数据不一致。主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,所以主键也是一个特殊的索引。
- 外键(foreign key):是用于建立和加强两个表数据之间的链接的一列或多列。外键约束主要用来维护两个表之间数据的一致性。简言之,表的外键就是另一表的主键,外键将两表联系起来。一般情况下,要删除一张表中的主键必须首先要确保其它表中的没有相同外键(即该表中的主键没有一个外键和它相关联)。
- 索引(index):是用来快速地寻找那些具有特定值的记录。主要是为了检索的方便,是为了加快访问速度, 按一定的规则创建的,一般起到排序作用。所谓唯一性索引,这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。
总结:
主键一定是唯一性索引,唯一性索引并不一定就是主键。
一个表中可以有多个唯一性索引,但只能有一个主键。
主键列不允许空值,而唯一性索引列允许空值。
主键可以被其他字段作外键引用,而索引不能作为外键引用。
49、数据库主从复制,读写分离
* 什么是主从复制:
主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;
* 主从复制的原理:
数据库有个bin-log二进制文件,记录了所有的sql语句。
只需要把主数据库的bin-log文件中的sql语句复制。
让其从数据的relay-log重做日志文件中在执行一次这些sql语句即可。
* 主从复制的作用:
做数据的热备份,作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。
架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问频率,提高单机的I/O性能
主从复制是读写分离的基础,使数据库能制成更大的并发。例如子报表中,由于部署报表的sql语句十分慢,导致锁表,影响前台的服务。如果前台服务使用master,报表使用slave,那么报表sql将不会造成前台所,保证了前台的访问速度。
* 主从复制的几种方式:
同步复制:所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,...,slave-n完成后才能返回。
异步复制:如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
半同步复制:master只保证slaves中的一个操作成功,就返回,其他slave不管。
这个功能,是由google为MYSQL引入的。
* 关于读写分离
在完成主从复制时,由于slave是需要同步master的。所以对于insert/
delete
/update这些更新数据库的操作,应该在master中完成。而select的查询操作,则落下到slave中。
50、常见的排序算法
1. 冒泡排序
思路分析:在要排序的一组数中,对当前还未排好的序列,从前往后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即,每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
代码实现:
$arr=array(1,43,54,62,21,66,32,78,36,76,39); function bubbleSort($arr) { $len=count($arr); //该层循环控制 需要冒泡的轮数 for($i=1;$i<$len;$i++) { //该层循环用来控制每轮 冒出一个数 需要比较的次数 for($k=0;$k<$len-$i;$k++) { if($arr[$k]>$arr[$k+1]) { $tmp=$arr[$k+1]; $arr[$k+1]=$arr[$k]; $arr[$k]=$tmp; } } } return $arr; }
2. 选择排序
思路分析:在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
代码实现:
function selectSort($arr) { //双重循环完成,外层控制轮数,内层控制比较次数 $len=count($arr); for($i=0; $i<$len-1; $i++) { //先假设最小的值的位置 $p = $i; for($j=$i+1; $j<$len; $j++) { //$arr[$p] 是当前已知的最小值 if($arr[$p] > $arr[$j]) { //比较,发现更小的,记录下最小值的位置;并且在下次比较时采用已知的最小值进行比较。 $p = $j; } } //已经确定了当前的最小值的位置,保存到$p中。如果发现最小值的位置与当前假设的位置$i不同,则位置互换即可。 if($p != $i) { $tmp = $arr[$p]; $arr[$p] = $arr[$i]; $arr[$i] = $tmp; } } //返回最终结果 return $arr; }
3.插入排序
思路分析:在要排序的一组数中,假设前面的数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。
代码实现:
function insertSort($arr) { $len=count($arr); for($i=1, $i<$len; $i++) { $tmp = $arr[$i]; //内层循环控制,比较并插入 for($j=$i-1;$j>=0;$j--) { if($tmp < $arr[$j]) { //发现插入的元素要小,交换位置,将后边的元素与前面的元素互换 $arr[$j+1] = $arr[$j]; $arr[$j] = $tmp; } else { //如果碰到不需要移动的元素,由于是已经排序好是数组,则前面的就不需要再次比较了。 break; } } } return $arr; }
4.快速排序
思路分析:选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。
代码实现:
function quickSort($arr) { //先判断是否需要继续进行 $length = count($arr); if($length <= 1) { return $arr; } //选择第一个元素作为基准 $base_num = $arr[0]; //遍历除了标尺外的所有元素,按照大小关系放入两个数组内 //初始化两个数组 $left_array = array(); //小于基准的 $right_array = array(); //大于基准的 for($i=1; $i<$length; $i++) { if($base_num > $arr[$i]) { //放入左边数组 $left_array[] = $arr[$i]; } else { //放入右边 $right_array[] = $arr[$i]; } } //再分别对左边和右边的数组进行相同的排序处理方式递归调用这个函数 $left_array = quick_sort($left_array); $right_array = quick_sort($right_array); //合并 return array_merge($left_array, array($base_num), $right_array); }
51、接口和抽象类的区别:
1、接口
- 对接口的使用是通过关键字implements
- 接口不能定义成员变量(包括类静态变量),能定义常量
- 子类必须实现接口定义的所有方法
- 接口只能定义方法不能实现方法
- 接口中没有构造函数
- 接口中的方法和实现他的;类默认都是public类型的
2、抽象类
- 对抽象类的使用是通关关键字extends
- 不能被实例化,可以定义子类必须实现的方法
- 子类必须实现父类中的所有抽象方法,这些方法的访问控制必须和父类中的一样(或者更加宽松)
- 如果一个类中有一个抽象方法。则该类必须定义为抽象方法
- 抽象类中可以有构造函数
- 抽象类种的方法可以使用private、protected、public来修饰
- 一个类可以同时实现多个接口,但是一个类只能继承一个抽象类
3、final类/方法
- final类不能被继承
- final方法不能比重写
4、static类/方法
- 可以不实例化类而直接访问
- 静态属性不可以由对象通过—>操作符来访问,用::方式来调用
52、常见的设计模式
策略模式:策略模式是对象的行为模式,动态的选择需要调用的类。
1 策略模式三个角色:
- 抽象策略角色
- 具体策略角色
- 环境角色
2 策略模式实现步骤:
- 定义抽象角色类
- 定义具体策略类
- 定义环境角色类
3 抽象类原则:
- 抽象类不能被实例化
- 有抽象方法的类一定是抽象类;类必须要 abstract 修饰
- 抽象方法不能有函数体;即 abstract function fun();
- 抽象类中的非抽象方法,可以被子类调用
- 非抽象子类继承抽象类,子类必须实现父类的所有抽象方法
- 抽象子类继承抽象类,无需继承父类的抽象方法
// 策略接口 约定策略的行为 interface UserStrategy { public function showAD(); } // 女性 class FemaleUser implements UserStrategy { public function showAD(){ echo "女"; } } // 男 class MaleUser implements UserStrategy { public function showAD(){ echo "男"; } } // 展示类 // page类依赖Female和MaleStrategy,但是现在只是依赖UserStrategy,Female和male依赖UserStrategy,从而实现反转, // 一般依赖反转的实现方案:一个类依赖另一个类,一般是依赖几个方法,将这几个方法抽象处一个接口,依赖的类,实现这个借口,就实现了倒置 详情见DIP原则 class Page { private $s; public function index(){ $this->s->showAD(); } public function setStrategy(UserStrategy $class){ $this->s = $class; } } // 只在一个地方判断,配置策略对象(Page),其他地方使用 if($type=='male' ){ $obj = new MaleUser(); } if($type == 'Female'){ $obj = new FemaleUser(); } $p = new Page(); $p->setStrategy($obj); $p->index();
策略模式的特点
- 功能:具体算法从具体业务处理中独立
- 多个if-else出现考虑使用策略模式
- 策略算法是形同行为的不同实现(多态)
- 客户端选择,上下文来具体实现策略算法
优缺点
优点:
- 避免让客户端涉及到重要算法和数据
- 避免使用难以维护的多重条件选择语句
- 易扩展
缺点:
- 判断逻辑在客户端,需求改变时,要更改客户端的程序。
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
- 增加了对象的数目
- 只适合扁平的算法结构
工厂模式:
简单工厂模式包含如下三种角色:
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现或者继承抽象产品的子类。
- 具体工厂:提供了创建产品的方法,使用者通过该方法来获取产品。
<?php class A { function __construct() { echo "我是A类"; } } class B { function __construct() { echo "我是B类"; } } class Factory { public static function create($name) { if ($name == 'A') { return new A(); } elseif ($name == 'B') { return new B(); } } } $a = Factory::create('A'); $b = Factory::create('B');
优缺点:
- 优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责;
- 缺点在于工厂类不够灵活,增加新的产品时需要修改工厂类的代码,一旦产品较多时,工厂类将会变得异常复杂。
53、说一说计算机网路体系结构
计算机网络体系结构一般有三种:OSI七层模型、TCP/IP四层模型、五层结构
简单说,OSI是一个理论上的网络通信模型,TCP/IP是实际上的网络通信模型,五层结构就是为了介绍网络原理而折中的网络通信模型。
OSI 七层模型
OSI 七层模型是国际标准化组织(International Organization for Standardization)制定 的一个用于计算机或通信系统间互联的标准体系。
- 应用层:通过应用进程之间的交互来完成特定网络应用,应用层协议定义的是应用进程间通信和交互的规则,常见的有:HTTP、FTP、SMTP、SNMP、DNS;
- 表示层:数据的表示、安全、压缩。确保一个系统的应用层所发送的消息可以被另一个系统的应用层读取;
- 会话层:建立、管理、终止会话,是用户应用程序和网络之间的接口;
- 运输层:提供源端与目的端之间提供可靠的透明数据传输,传输层协议为不同主机上运行的进程提供逻辑通信;
- 网络层:将网络地址翻译成对应的物理地址,实现不同网络之间的路径选择,协议有ICMP、IGMP、IP等;
- 数据链路层:在物理层提供比特流服务的基础上,建立相邻节点之间的数据链路;
- 物理层:建立、维护、断开物理连接。
TCP/IP四层模型
- 应用层:对应于 OSI 参考模型的(应用层、表示层、会话层)。
- 传输层: 对应 OSI 的传输层,为应用层实体提供端到端的通信功能,保证了数据 包的顺序传送及数据的完整性。
- 网际层:对应于 OSI 参考模型的网络层,主要解决主机到主机的通信问题。
- 网络接口层:与 OSI 参考模型的数据链路层、物理层对应。
五层体系结构
- 应用层:对应于 OSI 参考模型的(应用层、表示层、会话层)。
- 传输层:对应 OSI 参考模型的的传输层
- 网络层:对应 OSI 参考模型的的网络层
- 数据链路层:对应 OSI 参考模型的的数据链路层
- 物理层:对应 OSI 参考模型的的物理层。
54、说一说每一层对应的网络协议有哪些?
一张表格总结常见网络协议:
55、那么数据在各层之间是怎么传输的呢?
对于发送方而言,从上层到下层层层包装,对于接收方而言,从下层到上层,层层 解开包装。
- 发送方的应用进程向接收方的应用进程传送数据
- AP先将数据交给本主机的应用层,应用层加上本层的控制信息H5就变成了下一 层的数据单元
- 传输层收到这个数据单元后,加上本层的控制信息H4,再交给网络层,成为网 络层的数据单元
- 到了数据链路层,控制信息被分成两部分,分别加到本层数据单元的首部 (H2)和尾部(T2)
- 最后的物理层,进行比特流的传输
这个过程类似写信,写一封信,每到一层,就加一个信封,写一些地址的信息。到 了目的地之后,又一层层解封,传向下一个目的地。
56、从浏览器地址栏输入URL到显示主页的过程?
这道题,大概的过程比较简单,但是有很多点可以细挖:DNS解析、TCP三次握 手、HTTP报文格式、TCP四次挥手等等。
- DNS 解析:将域名解析成对应的 IP 地址。
- TCP连接:与服务器通过三次握手,建立 TCP 连接
- 向服务器发送 HTTP 请求
- 服务器处理请求,返回HTTp响应
- 浏览器解析并渲染页面
- 断开连接:TCP 四次挥手,连接结束
我们以输入www.baidu.com 为例:
各个过程都使用了哪些协议?
57、URL和URI有什么区别?
- URI:统一资源标识符(Uniform Resource Identifier ,URI),标识的是Web上每一种可用的资源,如:HTML文档、图像、视频片段、程序等都是由一个URI进行标识的。
- URL:统一资源定位符(Uniform Resource Location ,URL),它是URI的一种子集,主要作用是提供资源的路径。
区别:
URL除了提供资源的标识,还可以提供资源访问的方式。这么比喻,URI像是身份证,可以唯一标识一个人,而URL更像一个住址,而我们可以通过这个URL找到这个人——人类住址协议://地球/中国/湖南/长沙/岳麓区/xx大学/xx号宿舍/530/张三.男。
58、说说HTTP/1.0,1.1,2.0的区别?
区别:
- HTTP/1.0默认是短连接,可以强制开启,
- HTTP/1.1默认长链接,
- HTTP/2.0采用多路复用。
HTTP/1.0:
- 默认使用短连接,每次请求都需要建立一个TCP连接。它可以设置Connetion:Keep-alive这个字段,强制开启长链接。
HTTP/1.1:
- 引入了持久连接,即TCP默认不连接,可以被多个请求复用。
- 分块传输编码,即服务端每产生一块数据,就发送一块,用“流模式”取代“缓存模式”。
- 管道机制,即在同一个TCP连接里面,客户端可以同时发送多个请求
HTTP/2.0:
- 二进制协议,1.1 版本的头信息是文本(ASCII 编码),数据体可以是文本或者 二进制;2.0 中,头信息和数据体都是二进制。
- 完全多路复用,在一个连接里,客户端和浏览器都可以同时发送多个请求或回 应,而且不用按照顺序一一对应。
- 报头压缩,HTTP 协议不带有状态,每次请求都必须附上所有信息。Http/2.0 引 入了头信息压缩机制,使用 gzip 或 compress 压缩后再发送。
- 服务端推送,允许服务器未经请求,主动向客户端发送资源。
59、HTTP/3了解吗?
HTTP/3主要有两大变化,传输层基于UDP、使用QUIC保证UDP的可靠性。
HTTP/2存在的一些问题,比如重传等等,都是由于TCP本身的特性导致的,所以 HTTP/3在QUIC的基础上进行发展而来,QUIC(Quick UDP Connections)直译为快速UDP网络连接,底层使用UDP进行数据传输。
HTTP/3主要有这些特点:
- 使用UDP作为传输层进行通信
- 在UDP的基础上QUIC协议保证了HTTP/3的安全性,在传输的过程中就完成了 TLS加密握手
- HTTPS 要建⽴⼀个连接,要花费 6 次交互,先是建⽴三次握⼿,然后是 TLS/1.3 的三次握⼿。QUIC 直接把以往的 TCP 和 TLS/1.3 的 6 次交互合并成了 3 次, 减少了交互次数。
- QUIC 有⾃⼰的⼀套机制可以保证传输的可靠性的。当某个流发⽣丢包时,只会 阻塞这个流,其他流不会受到影响。
我们拿一张图看一下HTTP协议的变迁:
60、如何理解HTTP协议是无状态的?
这个无状态的状态值是什么?是客户端的状态,所以字面意思,就是HTTP协议中服务端不会保存客户端的任何信息。
比如当浏览器第一次发送请求给服务器时,服务器响应了;如果同个浏览器发起第二次请求给服务器时,它还是会响应,但是呢,服务器不知道你就是刚才的那个浏览器。
有什么办法记录状态呢?
主要有两个办法:Session和Cookie
61、说说Cookie和Session有什么联系和区别?
- Cookie是保存在客户端的一小块文本串的数据。客户端向服务器发起请求时,服务器会向客户端发送一个Cookie,客户端就把Cookie保存起来。在客户端下次向同一个服务器在发起请求时,Cookie被携带发送到服务器。服务器可以根据这个Cookie判断用户的身份和状态。
- Session指的是服务器和客户端一次会话的过程。它是另一种记录客户状态的机制。不同的是,cookie保存在客户端的浏览器中,而session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上, 这就是session。客户端浏览器再次访问时只需要从该session中查找用户的状态。
区别:
- 存储位置不一样,Cookie 保存在客户端,Session 保存在服务器端。
- 存储数据类型不一样,Cookie 只能保存ASCII,Session可以存任意数据类型,一 般情况下我们可以在 Session 中保持一些常用变量信息,比如说 UserId 等。
- 有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功 能,Session 一般有效时间较短,客户端关闭或者 Session 超时都会失效。
- 隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用 户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安 全性相对 Cookie 要好一些。
- 存储大小不同, 单个Cookie保存的数据不能超过4K,Session可存储数据远高于 Cookie。