PHP面试/笔试题杂记 II

这里记一些零碎的题目

如何判断一个字符串中是否存在一个字符?

1
2
3
4
strstr('abcdefgh', 'cd');   // strstr — 查找字符串的首次出现
strrchr('abcdefgh', 'cd'); // strrchr — 查找指定字符在字符串中的最后一次出现
strpos('abcdefgh', 'cd'); // strpos — 查找字符串首次出现的位置
strrpos('abcdefgh', 'cd'); // strrpos — 计算指定字符串在目标字符串中最后一次出现的位置

如何判断一个字符串中一个字符出现的次数?

1
substr_count('abcdefg', 'cd');  // 计算字串出现的次数

如何去掉一个字符串的最后一个字符?

1
2
substr('abcdefg', 0, -1);  // 返回字符串的子串
mb_substr('abcdefg', 0, strlen('abcdefg') - 1); // 获取部分字符串

不用新变量直接交换现有两个变量的值?

1
2
3
list($a, $b) = array($b, $a);
// 或
a = a + b, b = a - b, a = a-b;

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

  • echo是语言结构,无返回值;
  • print功能和echo基本相同,不同的是print是函数,有返回值;
  • print_r是递归打印,用于输出数组或对象;

用PHP打印出前一天的时间,打印格式是2020年5月20日13:14:20?

1
echo date('Y-m-d H:i:s', strtotime('- day'));

用PHP打印出上个月初的时间,打印格式是2020年5月20日13:14:20?

1
echo date('Y-m-d H:i:s', strtotime('-1 month', strtotime(date('Y-m-01 00:00:00', time()))));

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

如:http://www.baidu.com/abc/de/fg.php/?id=1,需要取出 php 或者.php?

1
2
3
4
5
6
7
8
public function get_extension()
{
$url = 'http://www.baidu.com/abc/de/fg.php/?id=1';
$path = pathinfo($url, PATHINFO_DIRNAME);
$ext = pathinfo($path, PATHINFO_EXTENSION);

echo $ext;
}

多台web服务器如何共享SESSION?

一般是把session数据按照自己定义的加密规则,加密后后存在cookie中。 把session存到同一个数据库服务器或者缓存服务器上,如memcached/redis。

如何通过javascript判断一个窗口是否已经被屏蔽?

获取open()的返回值,如果是null,就是屏蔽了

为了避免多次包含同一文件,可以用语句什么来代替它们?

require_once()/include_once()

实现中文字串截取无乱码方法?

1
mb_substr($str, 1, 1, “GB2312”);

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

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

请写一段PHP代码,确保多个进程同时写入同一个文件成功?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$fp = fopen('lock.txt', 'w+');
if (flock($fp, LOCK_EX)) {
// 获得写锁, 写数据
fwrite($fp, "write something");

// 解除锁定
flock($fp, LOCK_UN);
} else {
echo "file is locking";
}

fclose($fp);

如何获取一个网页的内容?

1
2
3
4
5
6
7
8
// 方法一
$fp = fopen('http://blog.caoxl.com', 'rb');
$content = stream_get_contents($fp);
fclose($fp);
echo $content;

// 方法二
file_get_contents('http://blog.caoxl.com');

请写一个函数验证电子邮件的格式是否正确(要求使用正则)?

1
preg_match('/^[\w\-\.]+@[\w\-]+(\.\w+)+$/',$email);

PHP中,如何获得一个数组的键值?

  • 使用key()可以获得数组中当前元素的键名
  • 使用current()则可以返回当前元素的值
  • 使用array_keys()则可以得到数组中所有的键名。
  • 使用foreach结构foreach($arr as key=>value)可以通过key和value分别获取键名和值。

PHP单点登录哪个的解决方案比较好点?

SSO Single Sign On 单点登录
Session多端登录,其实可以拆解为Session共享+登录,不是什么高级的东西,无非是需要的Session值在让不同服务器不同域名的情况下都可以访问,让大家都读取同一个Session值,重要的是同一个session_id()值。这样的话,每台(服务器/项目)读取的都是同样的数据,既然都是读取同样的数据(尤其读取同样的session_id()值),那么我们不就可以凭借此标识符让不同用户显示不同的内容,多点登陆的问题不就解决了

session共享的关键技术点在于两点:

  1. 让客户端访问同一个sessionId,
  2. 让所有域名对应的服务器访问的Session的数据的位置必须一致

Session共享大概有四种情况:

同服务器同域名同服务器不同域名不同服务器同域名不同服务器不同域名。

  • 同服务器同域名(不同子域名)的实现
1
2
3
4
5
6
7
8
9
10
11
12
// 1. 在php页面的最开始(在任何输出之前,并且在session_start()之前的地方进行以下设置
ini_set('session.cookie_path', '/');
ini_set('session.cookie_domain', '.mydomain.com');
ini_set('session.cookie_lifetime', '1800');

// 2. 在php.ini里设置
session.cookie_path = '/';
session.cookie_domain = .mydomain.com
session.cookie_lifetime = 1800

// 3. 在php页面最开始的地方调用函数
session_set_cookie_params(1800, '/', '.mydomain.com');
  • 同服务器不同域名的实现

不同域名的话就要先将cookie(‘PHPSESSID’)跨域,然后通过这个sessionid值从MySQL数据库或者Nosql中取得对应数据,这样就实现了同服务器不同域名的session共享。
然后是Redis数据共享,key就是session_id,值就是需要共享的数据,使用到的就是Redis的集群技术

  • 不同服务器同域名的实现

此种情况与 <同服务器不同域名的实现> 差不多,但在此种情况下不需要考虑cookie跨域的问题了,那么着重实现数据共享即可,同上,key为sessio_id,值为具体的数据值.

  • 不同服务器名不同域名的实现

此种情况和 <同服务器不同域名的实现> 类似,也是要实现两个目标,同一个sessionId,同样的数据源。不同域名的话就要先将cookie(‘PHPSESSID’)跨域,然后通过这个sessionid值从MySQL数据库或者Nosql中取得对应数据,这样就实现了同服务器不同域名的session共享。

如何实现session共享?

要解决session共享,就必须解决两个问题:

  1. 多台服务器用同一个session_id

这个比较容易解决,只要在php中设置存session_id的cookie域名为网站主域就可以了
打开PHP.ini, 设置session.cookie_domain = .caoxl.com,
当然也可以在php代码当中设置ini_set(“session.cookie_domain”,”caoxl.com”);

  1. 多台服务器用同一个session_id访问到相同的session内容

要实现这点,就必须把session内容存储到让所有服务器都能访问到的地方,php的session内容是默认存储到本服务器的文件中的,一般的解决方案是存入数据库,memcache或者redis这种缓存服务器,当然用默认的文件存储方式也可以,用NFS统一存储。

  1. 如何选择存储引擎
  • 默认文件存储

这种方式的session销毁依托于php垃圾收集器,在高并发或销毁时间较长的情况下,在SESSION目录下产生大量文件,当然可以设置分级目录进行 SESSION 文件的保存。这会导致两个问题:第一、查找文件慢;第二,每个目录下可容纳的文件数是有限的,可能会导致新SESSION储存失败。

  • 数据库存储

把Session存储在数据库里可以防止Session数据被垃圾收集器删除,可以固化存储session数据。但是用数据库来同步session,会加大数据库的IO,增加数据库的负担。而且数据库读写速度较慢,不利于session的适时同步

  • memcache存储
  • 以这种方式来同步session,不会加大数据库的负担,并且安全性比较高,把session放到内存里面,比从文件中读取要快很多。
  • 但是memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出
  • 那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源。
  • redis存储

与memcache相比,redis访问稍稍慢一点点,好处是:

  • redis支持的数据结构较多,可以存储数组或对象,而memcache只能存储字符串
  • 在session机器重启的情况下,memcache所有用户都必须重新获得 session,而redis不会
  • 在突然涌来大量用户产生了很多数据把存储 session 的机器内存占满了的情况下,memcache 会罢工,所有 key 都没过期的话就不停的覆盖最后写入的数据,而 redis 只是会变慢 ,不会影响程序的逻辑

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2023 Keep It Simple And Stupid All Rights Reserved.

访客数 : | 访问量 :