PHPer面试取经路-PHP篇

563次阅读  |  发布于2年以前

“小编整理了一份计算机类的资料,包含打造PHP程序员简历、java、Linux、Go语言等。获取方式:关注公众号:爱码仕,回复:1024,就可以获得这份超级大礼!

1表单提交中的Get和Post的异同点

2echo(),print(),print_r()的区别

3数组[‘a’, ‘b’, ‘c’] 转换成字符串 ‘abc’

echo implode(‘’,[‘a’, ‘b’, ‘c’]);
echo join([‘a’, ‘b’, ‘c’],'');

4获取字符串’aAbB’中A首次出现的位置

$str=‘aAbB’;
echo strpos($str,"A");

5编写一段用最小代价实现将字符串完全反序, e.g. 将 “1234567890” 转换成 “0987654321”

(1)使用函数
echo strrev("Hello World!");
(2) 不使用函数
$s = '1234567890';
$o = '';
$i = 0;
while(isset($s[$i]) && $s[$i] != null) {
$o = $s[$i++].$o;
}
echo $o;

6请用递归实现一个阶乘求值算法 F(n): n=5;F(n)=5!=54321=120

function F($n){
  if($n==0){
    return 1;
  }else{
    return $n* F($n-1);
  }
}
var_dump(F(5);

7将字符长fang-zhi-gang 转化为驼峰法的形式:FangZhiGang

//方法一
//ucfirst() 函数:把字符串中的首字符转换为大写,字符串参数为string。
function Fun($str){
  if(isset($str) && !empty($str)){
    $newStr='';
    if(strpos($str,'-')>0){
      $strArray=explode('-',$str);
      $len=count($strArray);
      for ($i=0;$i<$len;$i++){
        $newStr.=ucfirst($strArray[$i]);
      }
    }
    return $newStr; 
  }
}

//方法二
//ucwords() 函数:把字符串中每个单词的首字符转换为大写。该函数是二进制安全的。
function Fun($str){
  $arr1=explode('_',$str);
  $str = implode(' ',$arr1);
  return ucwords($str);
}
var_dump(Fun("fang-zhi-gang")); //FangZhiGang

8数组内置的排序方法有哪些?

sort($array); //数组升序排序
rsort($array); //数组降序排序
asort($array); //根据值,以升序对关联数组进行排序
ksort($array); //根据建,以升序对关联数组进行排序
arsort($array); //根据值,以降序对关联数组进行排序
krsort($array); // 根据键,以降序对关联数组进行排序

9用PHP写出显示客户端IP与服务器IP的代码

$_SERVER["REMOTE_ADDR"]
$_SERVER["SERVER_ADDR"]

10include和require的区别是什么?为避免多次包含同一文件,可用(?)语句代替它们?

加载失败的处理方式不同

include与require除了在处理引入文件的方式不同外,最大的区别就是:

  • include在引入不存在的文件时,产生一个警告且脚本还会继续执行
  • require则会导致一个致命性错误且脚本停止执行。
<?php
include 'hello.php';
echo 'world';
?>
//如果hello.php不存在,echo ‘world’这句是可以继续执行的。
<?php
require 'hello.php';
echo 'world';
?>
//如果hello.php不存在,echo ‘hello’这句是不会执行的,到require时就停止了。

include()是有条件包含函数,而 require()则是无条件包含函数。

if(FALSE){
include 'file.php'; //file.php不会被引入
}
if(FALSE){
require 'file.php'; //file.php将会被引入
}

文件引用方式

//include有返回值,而require没有
$retVal = include(’somefile.php’);
if(!empty($retVal)){
echo "文件包含成功";
}else{
echo "文件包含失败";
}
//可以用include_once,require_once代替,
//表示文件只引入一次,引入之后则不在引入,作为优化点

11PHP 不使用第三个变量实现交换两个变量的值

list($b,$a)=array($a,$b);
var_dump($a,$b);

12写一个方法获取文件的扩展名

//方法一
function get_extension($file){
  return substr(strrchr($file,'.'), 1);
}

//strrchr() 函数查找字符串在另一个字符串中最后一次出现的位置,并返回从该位置到字符串结尾的所有字符。

//方法二
function get_extension($file){
return end(explode('.', $file));
}
echo get_extension('fangzhigang.png'); //png

//end() 函数将内部指针指向数组中的最后一个元素,并输出。

13用PHP打印出前一天的时间格式是2017-3-22 22:21:21

$a = date("Y-m-d H:i:s", strtotime("-1 days"));

14PHP 如何接口调用?

public function authenticationApi($data,$url){
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  //输出格式可以转为数组形式的json格式
  $tmpInfo = curl_exec($ch);
  curl_close($ch);
  return $tmpInfo;
}

15用PHP header()函数实现页面404错误提示功能

Header("HTTP/1.1 404 Not Found");

16composer是什么?Composer和PHP有什么关系?

Composer是PHP的一个依赖(dependency)管理工具,在我们的项目中声明所依赖的外部工具库 (libraries),Composer 可以帮助我们安装这些依赖的库文件。Composer可以全局安装也可以局部安装,默 认不是全局安装的,是基于指定项目的某个目录进行安装的。

17composer团队协作怎么保证版本统一?

18OOP思想,特征和其意义

19OOP的七大设计原则是什么?

20mvc框架的生命周期说一下

用户请求进来,先加载配置文件,框架初始化,然后匹配路由地址,寻找到对应的controller的文件地址,引入加载文件,实例化controller,根据路由匹配得到的方法和参数,调用并传参到方法,此处可能需要读取db,model层则负责数据库存取,提供封装好的方法给到controller层调用,controller层得到数据后,通过引入 view 层文件,传递数据到view层,渲染html模板后输出。

  1. session与cookie的区别是什么?

1、保持状态:

2、使用方式:

3、存储内容:

4、存储的大小:

5、安全性:

22为什么session的安全性大于cookie?

23session与cookie的应用场景有哪些?

cookie:

session:

Session用于保存每个用户的专用信息,变量的值保存在服务器端,通过SessionID来区分不同的客户。

24php7新特性

25php8新特性

JIT 和 opcache 区别

26手写一个单例模式

所谓单例模式,即在应用程序中最多只有该类的一个实例存在,一旦创建,就会一直存在于内存中! 单例设计模式常应用于数据库类设计,采用单例模式,只连接一次数据库,防止打开多个数据库连接。 单例模式的编写遵循三私一公,代码如下:

<?php
class Database {
  private $instance;
  private function__construct() {
    // Do nothing.
  }
  private function__clone() {
    // Do nothing.
  }
  public static function getInstance() {
    if (!(self::$instance instanceof self)) {
      self::$instance = new self();
    }
    return self::$instance;
  }
}

$a = Database::getInstance();
$b = Database::getInstance();
// true var_dump($a === $b);

27php垃圾回收机制

关键词:使用了引用计数器

  1. PHP可以自动进行内存管理,清除不需要的对象,主要使用了引用计数。
  2. 在zval结构体中定义了ref_count和is_ref , ref_count是引用计数 ,标识此zval被多少个变量引用 , 为0时会被销毁 。is_ref标识是否使用的 &取地址符强制引用。
  3. 为了解决循环引用内存泄露问题 , 使用同步周期回收算法。
  4. 当数组或对象循环的引用自身 , unset掉数组的时候 , 当refcount-1后还大于0的 , 就会被当成疑似垃圾 , 会进行遍历 ,并且模拟的删除一次refcount-1如果是0就删除 ,如果不是0就恢复。

28php-fpm 是什么?

PHP5.3.3开始集成了php-fpm 模块,不再是第三方的包了。PHP-FPM 提供了更好的 PHP 进程管理方式,可以有效控制内存和进程、可以平滑重载 PHP 配置。

重点:php-fpm是fastcgi的实现。

29php-fpm 的运行模型?

多进程同步阻塞模式

30cgi,php-cgi,php-fpm,fastcgi 的区别?

31php-fpm如何完成平滑重启?

修改php.ini之后,php-cgi 进程的确是没办法平滑重启的。php-fpm 对此的处理机制是新的 worker用新的配置,已经存在的 worker 处理完手上的活就可以歇着了,通过这种机制来平滑过度。

32php-fpm 和 nginx 的通信机制是怎么样的?

看下nginx的配置文件:

Nginx中fastcgi_pass 的配置:

location ~ .php$ {
root /home/wwwroot;
fastcgi\_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
#fastcgi_pass unix:/tmp/php-cgi.sock;
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

因为nginx不能直接执行 php,所以需要借用 fastcgi 模块,和 php-fpm 进行通信。有两种方式;

  1. TCP
  2. UNIX Domain Socket
方式1:
php-fpm.conf: listen = 127.0.0.1:9000
nginx.conf: fastcgi_pass 127.0.0.1:9000;
方式2:
php-fpm.conf: listen = /tmp/php-fpm.sock
nginx.conf: fastcgi_pass unix:/tmp/php-fpm.sock;

值得一提的是,MySQ命令行客户端连接mysqld服务也类似有这两种方式:

mysql -uroot -p --protocol=socket --socket=/tmp/mysql.sock
mysql -uroot -p --protocol=tcp --host=127.0.0.1 --port=3306

33怎么选定用tcp还是套接字的方式和nginx通信?

34画下 php-fpm 在请求链路的体现?

35php-fpm有几种工作模式?

动态

会初始化创建一部分worker,在运行过程中,动态调整worker数量,最大worker数受 pm.max_children 和 process.max

listen = 127.0.0.1:9001
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 6
  1. 当空闲进程数小于min_spare_servers时,创建新的子进程,总子进程数小于等于pm.max_children,小于 等于process.max
  2. 当空闲进程数大于max_spare_servers,会杀死启动时间最长的子进程
  3. 如果子进程(idle状态)数大于max_children,会打印warning日志,结束处理
  4. process小于 max_children ,计算一个num,启动num个worker
  5. 优点:动态扩容,不浪费系统资源
  6. 缺点:所有worker都在工作,新的请求到来需要等待创建worker进程,最长等待1s(内部存在一个1s的定时器,去查看,创建进程),频繁启停进程消耗cpu,请求数稳定,不需要频繁销毁

静态

启动固定大小数量的worker,也有1s的定时器,用于统计进程的一些状态信息,例如空闲worker个数,活动 worker个数

pm.max_children = 10 #必须配置这个参数,而且只有这个参数有效
  1. 优点:不用动态判断负载,提升性能
  2. 缺点:如果配置成static,只需要考虑max_children数量,数量取决于cpu的个数和应用的响应时间,一次启动固定大小进程浪费系统资源

按需分配

php-fpm启动的时候不会启动worker进程,按需启动worker,有链接进来后,才会启动

listen = 127.0.0.1:9001
pm = ondemand
pm.process_idle_timeout = 60
pm.max_children = 10

连接到来时(只有链接,不没有数据也会创建,telnet也会创建),创建新worker进程,worker进程数的创建收 max_children 设置限制,也受限于全局的 process.max 设置(三种模式都受限此,下文中有全局配置项讲解),如果空闲时间超过了 process_idle_timeout 的设置就会销毁 worker 进程

36怎么选定php-fpm的worker进程数?

注意:PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始的时候一个 php-fpm 进程只占用 3M 左右内存,运行一段时间后就会上升到 20-30M。所以需要每个 worker 进程处理完一定的请求后,销毁重新创建。

cpu密集型的 pm.max_children 不能超过 cpu 内核数,但是 web 服务属于 IO 密集型的,可以将 pm.max_children 的值设置大于 cpu 核数。

37php-fpm如何优化?

在负载较高的服务器上定时重载php-fpm,reload可以平滑重启而不影响生产系统的php脚本运行,每15分钟 reload一次,定时任务如下:

0-59/15 * * * * /usr/local/php/sbin/php-fpm reload

pm.max_requests = 1024

38说下你最常用的php框架(laravel框架)的生命周期?

Laravel 是单入口文件的mvc重型框架,里面集成了消息队列,orm,ioc等功能模块。laravel的生命周期简述如下:

protected $app;
protected $router;
protected $bootstrappers \= \[
\\Illuminate\\Foundation\\Bootstrap\\LoadEnvironmentVariables::class,
# 加载 .env 中的配置信息
\\Illuminate\\Foundation\\Bootstrap\\LoadConfiguration::class,
# 加载 config 目录中所有配置文件的配置信息
\\Illuminate\\Foundation\\Bootstrap\\HandleExceptions::class,
# 异常处理
\\Illuminate\\Foundation\\Bootstrap\\RegisterFacades::class,
# 注册门面
\\Illuminate\\Foundation\\Bootstrap\\RegisterProviders::class,
# 注册Service Providers
\\Illuminate\\Foundation\\Bootstrap\\BootProviders::class,
# 注册启动器
\];

中间件

Middleware ,在 Kernel 以及它的基类 Illuminate\Foundation\Http\Kernel 中定义了一系列的 middlewares,借助这些中间件,就可以完成对用户请求的过滤和安全检查等等功能。

public function __construct(Application $app, Router $router){
  $this->app = $app;
  $this->router = $router;
  $route->middlewarePriority = $this->middlewarePriority;
  foreach ($this->middlewareGroups as $key => $middleware) {
    $router->middlewareGroup($key, $middleware);
  }
  foreach ($this->routeMiddleware as $key => $middleware) {
    $router->aliasMiddleware($key, $middleware);
  }
}

中间件的作用:所有请求在处理前需要经过的 HTTP中间件,这些中间件处理 HTTP 会话的读写、判断应用是否处于维护模式、验证CSRF 令牌等等。

39怎么理解 依赖注入(DI)与控制反转(Ioc)?

40php的弱类型是怎么实现的?

php 是通过 c 语言进行实现,但是 c 语言为强类型,那 php 的弱语言类型是通过 PHP 底层设计了一个zval(“Zendvalue”的缩写)的数据结构,可以用来表示任意类型的 PHP 值。通过共同体实现弱类型变量声明。

41简单说下对php 底层变量(zval)数据结构的理解

  1. 变量存储结构 变量的值存储到以下所示zval结构体中。 zval结构体定义在Zend/zend.h文件,其结构如下:
typedef struct _zval_struct zval;
...
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};

PHP使用这个结构来存储变量的所有数据。和其他编译性静态语言不同, PHP在存储变量时将PHP用户空间的变 量类型也保存在同一个结构体中。这样我们就能通过这些信息获取到变量的类型。

zval结构体中有四个字段,其含义分别为:

2 . 变量类型: zval结构体的type字段就是实现弱类型最关键的字段了,type的值可以为: IS_NULL、IS_BOOL、IS_LONG、IS_DOUBLE、IS_STRING、IS_ARRAY、IS_OBJECT和IS_RESOURCE 之一。 从字面上就很好理解,他们只是类型的唯一标示,根据类型的不同将不同的值存储到value字段。 除此之外,和他们定义在一起的类型还有 IS_CONSTANT 和 IS_CONSTANT_ARRAY。 这和我们设计数据库时的做法类似,为了避免重复设计类似的表,使用一个标示字段来记录不同类型的数据。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8