PHP核心技术面试题,跳槽必备!

122 阅读19分钟

1 oop是什么?

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

OOP具有三大特点

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

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

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

1、易维护

采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是在局部模块,所以维护起来是非常方便和较低成本的。

2、质量高

在设计时,可重用现有的,在以前的项目的领域中已被测试过的类使系统满足业务需求并具有较高的质量。

3、效率高

在软件开发时,根据设计的需要对现实世界的事物进行抽象,产生类。使用这样的方法解决问题,接近于日常生活和自然的思考方式,势必提高软件开发的效率和质量。

4、易扩展

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

2 合并两个数组有几种方式,试比较它们的异同

方式:

1、array_merge()

2、’+’

3、array_merge_recursive

异同:

array_merge 简单的合并数组

array_merge_recursive 合并两个数组,如果数组中有完全一样的数据,将它们递归合并

array_combine 和 ‘+’ :合并两个数组,前者的值作为新数组的键

3 PHP的is_writeable()函数存在Bug,无法准确判断一个目录/文件是否可写,请写一个函数来判断目录/文件是否绝对可写

答:其中bug存在两个方面,

1、在windowns中,当文件只有只读属性时,is_writeable()函数才返回false,当返回true时,该文件不一定是可写的。

如果是目录,在目录中新建文件并通过打开文件来判断;

如果是文件,可以通过打开文件(fopen),来测试文件是否可写。

2、在Unix中,当php配置文件中开启safe_mode时(safe_mode=on),is_writeable()同样不可用。

读取配置文件是否safe_mode是否开启。

/**
* Tests for file writability
*
* is_writable() returns TRUE on Windows servers when you really can't write to
* the file, based on the read-only attribute. is_writable() is also unreliable
* on Unix servers if safe_mode is on.
*
* @access   private
* @return   void
*/

if ( ! function_exists('is_really_writable'))
{
    function is_really_writable($file){

    // If we're on a Unix server with safe_mode off we call is_writable
    if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE){
        return is_writable($file);
    }

    // For windows servers and safe_mode "on" installations we'll actually
    // write a file then read it. Bah...
    if (is_dir($file)){

        $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100));

        if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE){
            return FALSE;
        }

        fclose($fp);
        @chmod($file, DIR_WRITE_MODE);
        @unlink($file);
        return TRUE;

    } elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) {

        return FALSE;
    }

    fclose($fp);
    return TRUE;

    }

}

4 PHP的垃圾收集机制是怎样的?

PHP可以自动进行内存管理,清除不再需要的对象。PHP使用了引用计数(reference counting)这种单纯的垃圾回收(garbage collection)机制。每个对象都内含一个引用计数器,每个reference连接到对象,计数器加1。当reference离开生存空间或被设为NULL,计数器减1。当某个对象的引用计数器为零时,PHP知道你将不再需要使用这个对象,释放其所占的内存空间。

5 写一个函数,尽可能高效的,从一个标准url里取出文件的扩展名,

例如:www.startphp.cn/abc/de/fg.p…

<?php

    // 方案一
    function getExt1($url){

        $arr = parse_url($url);
        //Array ( [scheme] => http [host] => www.startphp.cn [path] => /abc/de/fg.php [query] => id=1 )

        $file = basename($arr['path']);
        $ext = explode('.', $file);
        return $ext[count($ext)-1];
    }



    // 方案二
    function getExt2($url){

        $url = basename($url);
        $pos1 = strpos($url,'.');
        $pos2 = strpos($url,'?');

        if (strstr($url,'?')) {
            return substr($url,$pos1+1,$pos2-$pos1-1);

        } else {
            return substr($url,$pos1);
        }
    }

    $path = "http://www.startphp.cn/abc/de/fg.php?id=1";
    echo getExt1($path);
    echo "<br />";
    echo getExt2($path);

?>

6 使用正则表达式提取一段标识语言(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

?>

7 php中WEB上传文件的原理是什么,如何限制上传文件的大小?

上传文件的表单使用post方式,并且要在form中添加enctype=‘multipart/form-data’。

一般可以加上隐藏域:,位置在file域前面。

value的值是上传文件的客户端字节限制。可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。

使用file文件域来选择要上传的文件,当点击提交按钮之后,文件会被上传到服务器中的临时目录,在脚本运行结束时会被销毁,所以应该在脚本结束之前,将其移动到服务器上的某个目录下,可以通过函数move_uploaded_file()来移动临时文件,要获取临时文件的信息,使用$_FILES。

限制上传文件大小的因素有:

客户端的隐藏域MAX_FILE_SIZE的数值(可以被绕开)。

服务器端的upload_max_filesize,post_max_size和memory_limit。这几项不能够用脚本来设置。

自定义文件大小限制逻辑。即使服务器的限制是能自己决定,也会有需要个别考虑的情况。所以这个限制方式经常是必要的。

8 请说明 PHP 中传值与传引用的区别,什么时候传值什么时候传引用?

按值传递:函数范围内对值的任何改变在函数外部都会被忽略

按引用传递:函数范围内对值的任何改变在函数外部也能反映出这些修改

优缺点:按值传递时,php必须复制值。特别是对于大型的字符串和对象来说,这将会是一个代价很大的操作。按引用传递则不需要复制值,对于性能提高很有好处。(优缺点会考到)

9 MySQL数据库中的字段类型varchar和char的主要区别是什么?

Varchar是变长,节省存储空间,char是固定长度。查找效率要char型快,因为varchar是非定长,必须先查找长度,然后进行数据的提取,比char定长类型多了一个步骤,所以效率低一些。

10 静态化如何实现的?伪静态如何实现?

1、 静态化指的是页面静态化,也即生成实实在在的静态文件,也即不需要查询数据库就可以直接从文件中获取数据,指的是真静态。

实现方式主要有两种:一种是我们在添加信息入库的时候就生成的静态文件,也称为模板替换技术。一种是用户在访问我们的页面时先判断是否有对应的缓存文件存在,如果存在就读缓存,不存在就读数据库,同时生成缓存文件。

2、伪静态不是真正意义上的静态化,之所以使用伪静态,主要是为了SEO推广,搜索引擎对动态的文件获取难度大,不利于网站的推广。实习原理是基于Apache或Nginx的rewrite机智

主要有两种方式:一种是直接在配置虚拟机的位置配置伪静态,这个每次修改完成后需要重启web服务器。另一种采用分布式的,可以在网站的根目录上创建.htaccess的文件,在里面配置相应的重写规则来实现伪静态,这种每次重写时不需要重启web服务器,且结构上比较清晰。

11 如何处理负载,高并发?

1、HTML静态化

效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的 网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。

2、图片服务器分离

把图片单独存储,尽量减少图片等大流量的开销,可以放在一些相关的平台上,如七牛等

3、数据库集群和库表散列及缓存

数据库的并发连接为100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如memcache、redis。

4、镜像:

尽量减少下载,可以把不同的请求分发到多个镜像端。

5、负载均衡:

Apache的最大并发连接为1500,只能增加服务器,可以从硬件上着手,如F5服务器。当然硬件的成本比较高,我们往往从软件方面着手。

12 PHP7的新特性?

标量类型声明:PHP 7 中的函数的形参类型声明可以是标量了。在 PHP 5 中只能是类名、接口、array 或者 callable (PHP 5.4,即可以是函数,包括匿名函数),现在也可以使用 string、int、float和 bool 了。

返回值类型声明:增加了对返回类型声明的支持。类似于参数类型声明,返回类型声明指明了函数返回值的类型。可用的类型与参数声明中可用的类型相同。NULL 合并运算符:由于日常使用中存在大量同时使用三元表达式和 isset()的情况,NULL 合并运算符使得变量存在且值不为NULL, 它就会返回自身的值,否则返回它的第二个操作数。

use 加强:从同一 namespace 导入的类、函数和常量现在可以通过单个 use 语句 一次性导入了 匿名类:现在支持通过new class 来实例化一个匿名类

13 常见的 PHP 安全性攻击 SQL注入:

用户利用在表单字段输入SQL语句的方式来影响正常的SQL执行。

防止:使用mysql_real_escape_string()过滤数据 手动检查每一数据是否为正确的数据类型 使用预处理语句并绑定变量 参数化SQL:是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,用@或?来表示参数。

XSS攻击 :跨站点脚本攻击,由用户输入一些数据到你的网站,其中包括客户端脚本(通常JavaScript)。如果你没有过滤就输出数据到另一个web页面,这个脚本将被执行。

防止:为了防止XSS攻击,使用PHP的htmlentities()函数过滤再输出到浏览器。

CSRF:跨站点请求伪造,是指一个页面发出的请求,看起来就像是网站的信任用户,但是是伪造的

防止:一般来说,确保用户来自你的表单,并且匹配每一个你发送出去的表单。有两点一定要记住:对用户会话采用适当的安全措施,例如:给每一个会话更新id和用户使用SSL。生成另一个一次性的令牌并将其嵌入表单,保存在会话中(一个会话变量),在提交时检查它。如laravel中的 _token

代码注入:代码注入是利用计算机漏洞通过处理无效数据造成的。问题出在,当你不小心执行任意代码,通常通过文件包含。写得很糟糕的代码可以允许一个远程文件包含并执行。如许多PHP函数,如require可以包含URL或文件名。
防止代码注入 过滤用户输入 在php.ini中设置禁用allow_url_fopen和allow_url_include。这将禁用require/include/fopen的远程文件

16 面向对象的特征有哪些方面?

主要有封装,继承,多态。如果是4个方面则加上:抽象。

封装:

封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的高内聚,低耦合,防止程序相互依赖性而带来的变动影响.

继承:

在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。

多态:

多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。

抽象:

抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽象。

17说说对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 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描

18 MySQL数据库作发布系统的存储,一天五万条以上的增量,预计运维三年,怎么优化?

(1)设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。

(2) 选择合适的表字段数据类型和存储引擎,适当的添加索引。

(3) 做mysql主从复制读写分离。

(4)对数据表进行分表,减少单表中的数据量提高查询速度。

(5)添加缓存机制,比如redis,memcached等。

(6)对不经常改动的页面,生成静态页面(比如做ob缓存)。

(7)书写高效率的SQL。比如 SELECT * FROM TABEL 改为 SELECT field_1, field_2, field_3 FROM TABLE.

19 对于大流量的网站,您采用什么样的方法来解决各页面访问量统计问题?

(1) 确认服务器是否能支撑当前访问量。

(2) 优化数据库访问。

(3)禁止外部访问链接(盗链), 比如图片盗链。

(4)控制文件下载。

(5)做负载均衡,使用不同主机分流。

(6)使用浏览统计软件,了解访问量,有针对性的进行优化。

20 谈谈你对 mysql 引擎中的 MyISAM与InnoDB的区别理解?

InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定。基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能。

以下是一些细节和具体实现的差别:

MyISAM与InnoDB的区别是什么?

1、 存储结构

MyISAM:每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。

InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。

2、 存储空间

MyISAM:可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。

InnoDB:需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。

3、 可移植性、备份及恢复

MyISAM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。

InnoDB:免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了。

4、 事务支持

MyISAM:强调的是性能,每次查询具有原子性,其执行数度比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的,这个具体情况可以自己斟酌。

点关注,不迷路

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。之前说过,PHP方面的技术点很多,也是因为太多了,实在是写不过来,写过来了大家也不会看的太多,所以我这里把它整理成了PDF和文档,如果有需要的可以

点击进入暗号: PHP+「平台」

在这里插入图片描述

在这里插入图片描述

更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的 PHP技术交流群