【面试笔试-php】某公司php方向面试题总结。

1.  写一个 函数,array_remove(),要求最简洁的清除数组中值为$v的项。

解析:

   问题的表述很简洁,无需过多解释,假设函数原型为array_remove($v , $array)。需要注意的几点有:

    <1> 对于参数的检查.如果$array不是数组的话,返回错误或者抛出异常。

    <2> 如何比较数组的值与$v相等?是== 还是 ===?这里存在分歧。为了简单起见,我们假设是==比较。

   现在我们加一些限制条件,对于以下一些限制条件,应该如何解决:

    a.如果不使用系统函数。如何解决?

    b.参数传递问题:传递引用和传值对于函数的编写有何影响?分别实现之。

    c.可以使用系统函数的情况下,如何解决。


    我们先看条件一:如果不使用系统函数。如何解决?直接遍历吧,遇到value等于$v的项目,就删除它(或者遇到不等于value的元素,就记录下来)。因而有两种形式:

$value){
			if($value == $v){
				unset($array[$key]);
			}
		}
	}
	
	/*
	 *  方式2.传递值。返回修改后的新数组。
	 */
	function array_remove_return($v,$array){
		if(!is_array($array)){
			throw new Exception("input param is not a legel ,should be array\n");
		}
		$result = array();
		foreach($array as $key=>$value){
			if($value != $v){
				$result[$key] = $value;
			}
		}
		return $result;
	}
	
	$test = array(1,2,3,4,5);
	$test2 = array(1,2,3,4,5);
	array_remove(3,$test);
	print_r($test);
	$res = array_remove_return(3,$test2);
	print_r($res);

对于限制条件b。两种解法分别见限制条件a的两种解法。

限制条件c:如果可以用系统函数的话。有哪些解法?

这个解法也有很多。最基本的,我们可以用array_search找出value等于$v的索引,然后删除相应的元素。代码如下:

	function array_remove_with_inside($v,&$array){
		if(!is_array($array)){
			throw new Exception("input param is not a legel ,should be array\n");
		}
		$key = array_search($v,$array);
		if($key !== false){
			unset($array[$key]);
		}
	}
代码中需要注意的地方是第六行: if($key !== false)  。这里的比较是 !==而不是 != 。为什么呢?这是因为:

 array_search($v,$array);的结果可能是0(数组的第一个元素)。而在php中0==false但是0!== false.这是一个需要注意的地方。与这个情况类似的是遍历目录时候。
 while(($file = readdir($handler))!==false)这也是防止出现名字为0的目录或文件而产生错误。
当然也可以使用array_walk删除相应的元素。代码稍后补上。

类似的题目还有:reverse($string)的编写等,对于库函数的编写是一项基本能力,主要的考点是:效率,参数检测,错误处理等大多数需要考虑十分仔细和周全。

2. 以下登陆代码安全上有什么问题?

    $m = $_GET['m'];
    $user = $_GET['user'];
    $pass = $_GET['pass'];
    include($m.”do.php”);
    $sql = ”select count(*) as b from user where username=’”.$user.”‘and password=’”.$pass.”‘;
    $r = mysql_query($sql);
    list($count) = @mysql_fetch_array($r);
    if($count>1){

         ……登陆成功操作
    }
?>

解析:

仔细观察代码。我们发现,代码中的安全隐患还是很多的。大致有一下几种。

<1>用户名和密码都是通过get方式明文传递的。这是一个很严重的问题。虽然post方式也并不是安全的,但是对于这种表单提交,还是post方式最好。

<2>没有过滤用户的输入。存在者严重的sql注入隐患。应该htmlspecialchars ,trim,strip_tags处理用户输入。有一个原则叫:永远不要相信用户的输入。这里就是这个道理。

<3>sql查询部分。貌似数据库中保存的明文?至少应该做md5加密,然后比较md5加密的结果。

<4>include($m.”do.php”); 把用户的输入作为参数,而且不做处理的话,这里很容易出现“文件不存在”的异常

当然还有不是安全隐患的错误地方:if($count>1) 题目错误,会有两个以上同用户名同密码的用户吗?if($count >= 1)(好吧假设有,这里起码应该有=1)

3.写一个函数,算出两个文件的相对路径

例如:

  1. $a = ‘/a/b/c/d/e.php’;
  2. $b =’/a/b/12/34/c.php’;
则$a 相对于$b 的相对路径为 ../../../c/d/e.php  。对于任意两个给定的目录(目录的形式是有效的,不必做校验)。求出目录一相对于目录二的相对路径。

函数原型为 getRelativeDir($dir1,$dir2)求出$dir1相对于$dir2的相对路径。

解析:

最简单的想法。记录两个目录相同的部分并计数。如果计算出记录dir2跳出到相同目录下需要的次数。并添加 “ ../”。最后可以求出目录一相对于目录二的相对路径。

代码如下:

	function getRelativePath($dest_dir,$relative_dir){
		$path_dest = explode('/',dirname($dest_dir));
		$path_relative = explode('/',dirname($relative_dir));
		$aLen = count($path_dest);
		$bLen = count($path_relative);
		$minLen = min($aLen,$bLen);
		
		$count = 0;
		for($i = 0; $i < $minLen; $i++){
			if(  $path_dest[$i] == $path_relative[$i] ){
				$count++;
			}
		}
		$path = '';
		$res_count = $bLen - $count - 1;
		for($i = 0;$i < $res_count;$i++){
			$path.= "../";
		}
		for($i = $res_count;$i < $aLen;$i++){
			$path.= $path_dest[$i]."/";
		}
		$path.= basename($dest_dir);
		return $path;
	}
	
	$a = '/a/b/c/f/d/e.php';
	$b = '/a/b/f/g/k/h/j.php';
	echo getRelativePath($a,$b);

3. 写一个程序,远程抓取 http://www.google.cn/search?q=php 网页内容,并匹配出该网址网页内的所有超链接地址,写入url.txt。

解析:基本考点:file_get_contents 或者curl获取网络内容 .正则表达式匹配。file_put_contents或者文件操作函数。并无太大难点。

作为测试,(谷歌被墙了),抓取baidu的相关搜索结果。测试代码如下:

$value){
			if($value != "#"){
				$content.= $value."\n";
			}
		}
		file_put_contents('url.txt',$content);
	}catch(Exception $e){
		echo $e->getMessage();
	}
	
	function getContentFromUrl($url){
		if(!$url){
			return null;
		}
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
		$content = curl_exec($ch);
		if($content === false){
			throw new Exception("[ curl ]:".curl_erron().":".curl_error());
		}
		curl_close($ch);
		//$content = file_get_contents($url);
		$result = array();
		preg_match_all('/]*)? *href *= *"([^"]*)" *[^>]*?>(?:.*)<\/a>/i',$content,$result);
		var_dump( $result[1] );
		return $result[1];
	}

mysql部分:
1. 如何检验sql语句的效率索引使用情况?

解析:explain sql语句。可以从表中看出相应的结果。


更多详细的介绍可参考这篇文章:http://www.1983blue.com/index.php/posts/mysql-explain-index_1

js部分:


如何当age的值填入18的时候,form的action变更为?do=login_bak  ?

解析:简单的事件监听和js函数。

onchange的时候检测value值,如果为18.则form.login.action = ?do=login_bak.


服务器部分:
1. 查看当前服务器负载命令是?

解析:uptime ,top命令。loadavg。 proc系统。

  推荐文章:http://www.flybaaa.com/help/69_1.html。讲解很清晰,很清晰。

2. 如何查看当前服务器1111端口的链接总数是?

netstat -nat |grep :1111 |wc -l

3. 如何列出当前进程里有多少包含apache名字的进程?

ps -ef | grep apache

其他
你现在要做的是一套图片管理系统。关于用户图片的上传。你是如何尽量避免1,图片被盗用。2,图片重复上传。你的上传保存目录如何设置的?

解析:需要注意的是“防止盗用”与“防止盗链”是不同的概念。

为了防止被盗用,你需要做的是类如图片水印之类的东西(例如新浪博客上上传的图片会自动加上你的微博id,就是一种防盗用技术)。

    怎样防止图片被盗用,可以参考本文章:http://blog.sina.com.cn/s/blog_5e3e2a6a0100e658.html

为了防止被盗链,需要做目录或文件权限设置,或者域名检测(不是本网站的域名时,或跳出提示,或显示替代图片)。apache的目录设置可以实现这个功能。

具体的细节可看:http://blog.csdn.net/mygood322/article/details/7582531。

上传目录设置一般为:一个用户一个大目录。目录下面可以分多个具体的目录。

为了防止图片重复上传,可以:

      禁止短时间内多次提交按钮(js控制,点击按钮后几秒内上传按钮失效);

      防止刷新提交按钮;关于这点,看到一个很简练的方式:

用 令牌机制
先生成个随机字符串,存在session里.
例如:
if(!isset($_SESSION['verify'])){
   $_SESSION['verify'] = gmmktime();
}
然后在 html的表单中加个隐藏字段


在表单提交的时候,检查提交上来的verify的值 是否等于 session里存的
if($_POST['verify']!=$_SESSION['verify']){
       die('请勿重复提交');
}else{
         unset($_SESSION['verify']);
         //做上传需要做的事情.....
} 


本次php面试题目基本总结完成。

你可能感兴趣的:(【面试笔试-php】某公司php方向面试题总结。)