php基础(二)
一、PHP基础
1.对于0,空值,'=','=='等的考察
以下代码输出什么
<?php
function judge(){
$num = 0;
if($num = ''){
echo 'a';
}else{
echo 'b';
}
}
?>
输出b,if中的空值赋值给$num,因此if条件必定为false,还有其他一些大同小异的题目,用=和==判断for循环的,只要把握好基本的概念就行了
2.对于empty、isset概念的考察
isset()和empty()函数的区别在于,前者只验证一个值是否存在,后者在此基础上还会检验它的值是否非空和非0
注:empty()只检测变量,检测任何非变量的东西都将导致解析错误
isset() 判断一个变量是否已经设置
当设置一个变量值为0,empty() 认为这个变量同等于空,即相当于没有设置
可以定义一个变量,设置值为'',0,null,'aaa'几种不同情况下,用if判断empty、isset看看结果
3.预定义变量
如:php中输出当前脚本文件名的预定义变量是$_SERVER['PHP_SELF']
与DOCUMENT_ROOT
有关。如:地址为http://baidu.com/test/kkk.php的脚本,$_SERVER['PHP_SELF']='/test/kkk.php'
还有一些重要的如$_SERVER['DOCUMENT_ROOT']
,输出网站所在的根目录,如D:/work/www $_SERVER['SCRIPT_FILENAME']
,输出'D:/work/www//kkk.php' $_SERVER['HTTP_USER_AGENT']
,获取客户端浏览器,操作系统等等
其他一些可以通过print_r($_SERVER)
测试获得,当然不止这些,还有其他一些预定义变量,系统常量如FILE也是需要稍微去看一下
4.函数、算法考察
主要考察php的原生函数,暂时分为数组函数、字符串处理函数、时间函数、文件操作函数、数据库函数,后面再看看需不需要扩展。注意这些函数一定都要去过一遍。
(1.1)遍历指定文件夹下的所有文件夹及所有子文件夹
确定是文件夹 —— 打开文件夹(产生dh句柄) —— 循环读取文件夹内容(读取句柄的内容,即为file/folder) —— 递归读取上一步判断为folder且文件夹不为'.'或者'..'的文件夹内容
<?php
$dir = "D:/www/project/";
function readDirectory($dir){
if(is_dir($dir)){ //
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) != false) {
if (is_dir($dir.$file) && $file!="." && $file!="..") {
echo $dir.$file."<br/>";
readDirectory($dir.$file."/");
}
}
closedir($dh);
}
}
}
readDirectory($dir);
?>
(1.2)遍历指定文件夹下的所有文件及其子文件夹中的所有文件
<?php
$dir = "D:/www/project/";
function readDirectory($dir){
if(is_dir($dir)){ //
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) != false) {
if (is_file($dir.$file)) {
echo "filename:".$file."<br/>";
// echo $dir.$file."<br/>";
echo "filetype:".filetype($dir.$file)."<br/>";
}
if (is_dir($dir.$file) && $file!="." && $file!="..") {
readDirectory($dir.$file."/");
}
}
closedir($dh);
}
}
}
readDirectory($dir);
?>
(2)写一个方法获取url中的文件类型
如$url = 'http://www.qq.com/test.php?a=...'; 取出'php'
function getFileName($url){
$a = explode('?', $url);
$b = strrpos($a[0], '.'); //strrpos(被搜索字符串,要查找字符串,[查找开始的位置]) 查找字符串最后一次出现的位置: 找到则返回最后一次出现的位置;未找到则返回false
$c = substr($a[0], $b+1, 3); //substr(被操作字符串,开始位置,[结束位置]) 返回字符串的一部分
return $c;
}
(3)接口知识的考察
eg.
用户登录认证,请求地址为http://www.aa.com/user.php,后台需要有一个接口,验证是否正确
请求参数:时间戳 Time 什么鬼参数忘了,即为param 还有一个是token,token值是Time+param的MD5加密,中间有加号
返回参数:
成功:res['ret'] = 0; res['msg'] = 'success';
失败:res['ret'] = 1; res['msg'] = 'fail';
返回数据格式:json
下面是我的思路:
function valid(){
$data = $_GET['data'];
if(!$data){
$res['ret'] = 1;
$res['msg'] = 'fail';
echo json_encode($res);
}
$str = $data['Time'] . '+' . $data['param'];
if($data['token'] != md5($str)){
$res['ret'] = 1;
$res['msg'] = 'fail';
echo json_encode($res);
}else{
$res['ret'] = 0;
$res['msg'] = 'success';
echo json_encode($res);
}
}
其实今天笔试的时候做这道题忘了怎么返回json格式的数据了,就直接用了Thinkphp的ajaxReturn,后来回来的时候查了一下才知道原来直接echo,这么简单,框架还是为辅吧,要多写原生。今天笔试的是一家手游公司,对数据库操作和原生要求比较多。
5.对缓存的了解
二、数据库知识
1.数据库的基本增删查改
基本的增删改查语句,关联语句,函数等过一遍
2.谈谈数据库优化的方法
(1)创建表的时候避免使用NULL默认值,因为NULL对于大多数数据库都需要进行特殊处理和索引逻辑等等。所以大多数时候不用NOT NULL,可以用特殊值0或1代替
(2)尽可能使用更小的字段类型,因为mysql从磁盘读取数据之后是存到内存当中,这意味着更小的数据类型使得从磁盘读取或者打包到内存效率会更好
(3)字符集的转换:客户端或者应用程序使用的字符集可能和数据库使用的字符集不一致,需要在mysql运行过程中隐含转化
(4)创建索引,如果一张表很大然后符合条件的值很多,那么创建索引就能带来性能的提升。但是如果像性别,只有两个值,就没必要建索引,而是用enum。一张表的索引最好不超过6个,太多的话会影响Insert和Update的效率,因此要考虑删除使用不频繁的索引
(5)先考虑在where和order by这两列上建立索引。尽量少在where子句中进行表达式操作、函数操作等等
(6)尽量避免使用select * ,只查询需要用到的字段。尽量用betwwen and 代替in 和not in,也要避免在大量数据的where子句中使用or
(7)模糊查询优化:
使用FULLTEXT全文搜索(注意前提是MyISAM存储引擎)
FULLTEXT解析器用“ ”(空格)、“,”(逗号)“.”(点号)作为默认的单词分隔符,因此对于不使用这些分隔符的语言如汉语来说,FULLTEXT解析器不能正确的识别单词,对于这种情况需做额外处理。
(8)尽量满足范式(有的情况下要用反范式)下面是三大范式的区别,也要去看一下
第一范式:数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。如果实体中的某个属性有多个值时,必须拆分为不同的属性
第二范式:满足第一范式前提,当存在多个主键的时候,才会发生不符合第二范式的情况。比如有两个主键,不能存在这样的属性,它只依赖于其中一个主键,这就是不符合第二范式
第三范式:满足第二范式前提,如果某一属性依赖于其他非主键属性,而其他非主键属性又依赖于主键,那么这个属性就是间接依赖于主键,这被称作传递依赖于主属性。
3.谈谈Myisam和Innodb存储引擎
(1)MyISAM强调性能,其执行速度比InnoDB类型更快,但不支持事务,而InnoDB提供事务支持以及外部键、行级锁等高级数据库功能
(2)如果增删改操作比较多,或者需要事务支持,则使用Innodb,如果是读的操作比较多,则使用Myisam
(3)MyISAM表锁,Innodb行锁
4.谈谈memcached和redis的异同
一、关于读写性能(QPS)
memcache更加快速,在性能上比redis快,缺点是仅支持字符串。
Redis支持丰富的数据结构类型,字符串,散列(哈希),集合,有序集合还支持订阅发布,地理位置等。
实际运用中可以结合二者,memcache可作为session存储的方式,session都是kv键值对。
Redis提供了多种不同级别的持久化方式:
RDB持久化可以在指定的时间间隔内生成数据集的时间点快照;
AOF持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。
AOF文件中的命令全部以Redis协议的格式来保存,新命令会被追加到文件的尾部,Redis还可以在后台对AOF文件进行重写(rewrite),使得AOF文件的体积不会超出保存数据集状态所需的实际大小。
Redis还可以同时使用AOF持久化和rob持久化,在这种情况下,当Redis重启时,它会优先使用AOF文件来还原数据集,因为AOF文件保存的数据集通常比rob保存的数据更完整。
工作原理
memcache是把所有的数据保存在内存中,采用hash表的方式,每条数据由key,value组成,每个key都是独一无二的,当要访问某个值得时候,先按照键找到值然后返回结果。memcache采用LPU(least recently used)算法来逐渐把过期数据清理掉。
三、算法
1.写一个函数判断数组的深度
function getDepth($arr){
$max_depth = 1;
foreach($arr as $key=>$val){
if(is_array($val)){
$depth = getDepth($val) + 1;
if($depth > $max_depth){
$max_depth = $depth;
}
}
}
return $max_depth;
}
四、计算机网络
1.说一下常见的HTTP状态码
(1)消息(临时响应):1字头。
这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。由于 HTTP/1.0 协议中没有定义任何 1xx 状态码,所以除非在某些试验条件下,服务器禁止向此类客户端发送 1xx 响应。
eg.
100: 服务器仅接收到部分请求
101: 服务器已经理解了客户端的请求,并将通过Upgrade 消息头通知客户端采用不同的协议来完成这个请求。
(2)成功:2字头。
代表请求已经被服务器所接收、理解、并接受
eg.
200: 请求成功(其后是对GET和POST请求的应答文档。)
201: 请求被创建完成,同时新的资源被创建。
(3)重定向:3字头。
表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
eg.
300: 多重选择。链接列表。用户可以选择某链接到达目的地。
301: 页面永久重定向
302: 页面临时重定向
304: 资源未被修改,服务器告诉客户,原来缓冲的文档还可以继续使用
(4)请求错误:4字头。
这些状态代码表示请求可能出错,妨碍了服务器的处理
eg.
400: 服务器未能理解请求
401: 被请求的页面需要用户名和密码。
403: 对请求页面的访问被禁止。(通常为没有读权限)
404: 服务器无法找到被请求的页面。
408: 超出服务器等待时间
413: 由于所请求的实体的太大,服务器不会接受请求。
414: 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
(5)服务器错误:5字头。
这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错
eg.
500: 请求未完成。服务器遇到不可预知的情况。
502: 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。
503: 服务器临时过载或当机。
504: 网关超时。
五、前端
1.考察函数
<input type="text" good="" />
获取input标签中的good属性值所用的函数是getAttribute("good")
2.考察jquery
<div id='table'></div>
用ajax方法,把请求返回的参数(格式是json)填充到table中,以表格形式列出
var html = '';
$(function(){
$.ajax({
type:'post',
url:'.....',
data:(忘了发送的参数是什么了,随便写一下){
a:111,
b:222
},
dataType:json,
success:function(data){
var res = jQuery.parseJSON(data);
for(var i=0;i<res.length;i++){
html += '<tr><td>' + res[i].Time + '</td><td>' + res[i].num + '</td></tr>';
}
$('#table').html('<table>' + html + '</table>');
},
error:function(){
}
})
})
六、其他
1.遇到问题时怎么解决(错误日志)
首先开启错误日志,配置php.ini
error_reporting = E_ALL ;将会向PHP报告发生的每个错误,包括ERROR、NOTICE、WARNING等等
display_errors = Off ;本地测试开启,项目上线要关闭,防止服务器重要信息泄露
log_errors = On ;开启错误日志
log_errors_max_len = 1024 ;设置每个日志项的最大长度
error_log = /www/phpernote/error.log ;指定产生的错误报告写入的日志文件位置
配置完之后重启服务器即可,参考了php的异常和处理文章的一小段代码,自己另外做了测试
<?php
set_error_handler('myErrorHandler');
function myErrorHandler($errno,$errmsg,$file,$line){
echo "<b>错误代码:</b>[{$errno}] {$errmsg} <br/>".PHP_EOL;
echo "<b>错误行号:</b>{$file}文件中的第 {$line} 行<br/>".PHP_EOL;
echo "<b>PHP版本:</b>".PHP_VERSION."(".PHP_OS.") <br/>".PHP_EOL;
$datetime = date('Y-m-d H:i:s',time());
error_log('时间:' . $datetime . '错误的信息:' . $errmsg . '错误文件所在位置:' . $_SERVER['SCRIPT_FILENAME']);
}
echo $test;
test();
echo 'good';
?>
手动分割线
在上面提到的内容,其实有一些可以自己去拓展看一下的,比如提到innodb和myisam,前者是使用行锁,后者是使用表锁,那可以去拓展一下,什么是表锁什么事行锁,逐渐增大自己的知识面