php

php 面试题(一)

<?php echo count(strlen("http://php.net"))?>执行结果是什么?

1。

count($x)
$x 是数组或者实现 Countable 的对象 如果是数组,返回数组元素个数,如果是对象,返回 count 方法的返回值。
$x 是 null 0
$x 是其他类型 1

使用 list() 函数需要注意什么?

PHP 5 里,list() 从最右边的参数开始赋值; PHP 7 里,list() 从最左边的参数开始赋值。(不建议依赖于操作的顺序,在未来可能会再次发生修改。)

<?php
$info = array('coffee', 'brown', 'caffeine');
list($a[0], $a[1], $a[2]) = $info;
var_dump($a);
/**
php 7 输出:
array(3) {
  [0]=>
  string(6) "coffee"
  [1]=>
  string(5) "brown"
  [2]=>
  string(8) "caffeine"
}

php 5 输出:
array(3) {
  [2]=>
  string(8) "caffeine"
  [1]=>
  string(5) "brown"
  [0]=>
  string(6) "coffee"
}
*/

单引号、双引号区别是什么?

一、单引号中要表示 \' 需要在前面加上反斜杠,双引号不需要。

二、单引号中的变量和特殊字符的转义序列将不会被解析,而双引号会解析。

如何在命令行运行 php 代码(写出两种方式),如何在命令行向脚本传递参数?

一、php filename.php 或者 php -r "echo 'leonzai@github.com';

二、php filename.php arg1 arg2,如果第一个参数以 - 开头,那么必须在第一个参数前传递 --,如 php filename.php -- arg1 arg2

简述 php 垃圾回收机制

php 中的变量存储在变量容器 zval 中,zval 中除了存储变量类型和值外,还有 is_refrefcount 字段。refcount 表示指向变量的元素个数,is_ref 表示变量是否有别名。当 unset 一个变量,则进行 refcount-- 操作,如果此时 refcount 为 0 时,就回收该变量容器。如果此时 refcount 大于 0,它就会进入垃圾缓冲区。当缓冲区达到最大值后,回收算法会循环遍历 zval,判断其是否为垃圾,并进行释放处理。

在 php 中 zval 有了新的实现方式。最基础的变化就是 zval 需要的内存不再是单独从堆上分配,不再自己存储引用计数。复杂数据类型(比如字符串、数组和对象)的引用计数由其自身来存储。

什么是事务,什么是回滚,事务的作用是什么?

事务是数据库中进行数据操作的一个执行单元。
具有原子性、一致性、隔离性、持久性。
原子性表示该操作不会被分割、打断。
一致性表示数据库处理前后结果应与其所抽象的客观世界中真实状况保持一致。这种一致性是一种需要管理员去定义的规则。管理员如何指定规则,数据库就严格按照这种规则去处理数据。
隔离性表示各个事务之间不会相互干扰。
持续性表示一旦事务被提交,对数据库的影响将是永久性的。

回滚指的在事务运行的过程中发生了某种故障,事务不能继续执行,系统将事务中对数据库的所有已完成的操作全部撤销,滚回到事务开始时的状态。

事务是用来确保数据的一致性。

编写函数实现和 strtoupper() 一样的功能。

php 的 strtolower() 和 strtoupper() 函数在安装非中文系统的服务器下可能会导致将汉字转换为乱码,请写两个替代的函数实现兼容 Unicode 文字的字符串大小写转换。

// 研究了下,只在 utf8 下有效。
function str_to_upper($str)
{
    $res = "";
    foreach (str_split($str) as $v) {
        $v = ord($v);
        if ($v >= 97 and $v <= 122) {
            $v -= 32;
        }
        $res .= chr($v);
    }
    return $res;
}

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

function is_really_writable($file)
{
    if (DIRECTORY_SEPARATOR === '/') return is_writable($file);

    if (is_dir($file)) {
        $file = rtrim($file, "/") . "/" . md5(mt_rand());
        $fp = @fopen($file, "ab");
        if ($fp === false) return false;
        fclose($fp);
        @chmod($file, 0777);
        @unlink($file);
        return true;
    }

    if (!is_file($file)) return false;

    $fp = @fopen($file, "ab");
    if ($fp === false) return false;
    fclose($fp);
    return true;
}

实现斐波那契数列

function fbnq($number)
{
    $number = intval($number);
    if ($number === 0) return 0;
    if ($number === 1) return 1;
    return fbnq($number - 1) + fbnq($number - 2);
}

向函数中传一个多维数组,对数组中所有的值做判断,如果值是 ‘number’ 则设置该值为 0 ?(用递归思想实现)

function change_number_to_0($array)
{
    if (!is_array($array)) {
        return $array === 'number' ? 0 : $array;
    }
    foreach ($array as $key => $item) {
        if (is_array($item))  {
            $array[$key] = change_number_to_0($item);
        } elseif ($item === 'number') {
            $array[$key] = 0;
        }
    }
    return $array;
}

设计模式与应用场景(列举三个)

依赖注入模式:通过将依赖注入到应用类中来实现解耦。
池模式:准备一组已初始化的对象池,而不是按需分配和销毁。多用于数据库链接,套接字链接等。
门面模式:解耦,遵循迪米特原则,好的门面模式不需要向构造器传参,甚至不需要 new。

秒杀实现

排队队列和抢购结果队列及库存队列。高并发情况,先将用户进入排队队列,用一个线程循环处理从排队队列取出一个用户,判断用户是否已在抢购结果队列,如果在,则已抢购,否则未抢购,库存减 1,写数据库,将用户入结果队列。

发表评论