简述论坛中无限分类的实现原理。(新浪)
创建类别表如下:
CREATE TABLE category(
cat_id smallint unsigned not null auto_increment primary key comment'类别ID',
cat_name VARCHAR(30)NOT NULL DEFAULT''COMMENT'类别名称',
parent_id SMALLINT UNSIGNED NOT NULL DEFAULT 0 COMMENT'类别父ID'
)engine=MyISAM charset=utf8;
编写一个函数,递归遍历,实现无限分类
function tree(arr,pid=0,
static $list = array();
foreach (arr as v) {
//如果是顶级分类,则将其存到$list中,并以此节点为根节点,遍历其子节点
if (v['parent_id'] == pid) {
v['level'] = level;
list[] = v;
tree(arr,v['cat_id'],
}
}
return $list;
}
mysql_fetch_row()和mysql_fetch_array()有什么分别?
mysql_fetch_row()把数据库的一列储存在一个以零为基数的数组中,第一栏在数组的索引0,第二栏在索引1,依此类推。
mysql_fetch_assoc()把数据库的一列储存在一个关联数组中,数组的索引就是字段名称,例如我的数据库查询送回 “first_name”、“last_name”、“email”三个字段,数组的索引便是“first_name”、“last_name”和 “email”。
mysql_fetch_array()可以同时送回mysql_fetch_row()和mysql_fetch_assoc()的值。
Smarty的原理
smarty是一个模板引擎,使用smarty主要是为了实现逻辑和外在内容的分离,如果不使用模板的话,通常的做法就是php代码和html代码混编。使用了模板之后,则可以将业务逻辑都放到php文件中,而负责显示内容的模板则放到html文件中。
Smarty在执行display方法的时候,读取模板文件,并进行数据替换,生成编译文件,之后每次访问都会直接访问编译文件,读取编译文件省去了读取 模板文件,和字符串替换的时间,所以可以更快,编译文件里时间戳记录模板文件修改时间,如果模板被修改过就可以检测到,然后重新编译(编译是把静态内容保 存起来,动态内容根据传入的参数不同而不同)。
如果启用了缓存,则会根据编译文件生成缓存文件,在访问的时候如果有缓存文件并且缓存文件没有过期,则直接访问缓存文件。
相关题目1:能够使HTML和PHP分离开使用的模板
smarty,phplib等
相关题目2:您是否用过模板引擎?如果有您用的模板引擎的名字是?
Smarty
PHP如何实现页面跳转
方法一:php函数跳转,缺点,header头之前不能有输出,跳转后的程序继续执行,可用exit中断执行后面的程序。
header("Location:网址");//直接跳转
header("refresh:3;url=http://www.codingke.com/");//三秒后跳转
方法二:利用meta
echo"";
请对POSIX风格和兼容Perl风格两种正则表达式的主要函数进行类比说明
主要区别有以下三种:
preg_replace()里面的正则可以写成型如:"/.xxx/"而ereg_replace()里面的正则需写成型如 "xxx"
preg_replace()能操作数组,而ereg_replace()不可以
在逆向引用用preg_replace()可使用0-99个,而ereg_replace()最多为9个
使用Perl兼容正则表达式语法的preg_match()函数通常是比ereg()更快的替代方案。
请写出并说明如何在命令行下运行PHP脚本(写出两种方式)同时向PHP脚本传递参数?(腾讯)
首先进入php安装目录
php -f d:/wamp/www/1.php 其中-f参数指定要执行的php文件
php -r phpinfo(); 其中-r表示直接执行php代码,无需写开始结束标记
allow_call_time_pass_reference boolean
是否启用在函数调用时强制参数被按照引用传递。此方法已不被赞成并在 PHP/Zend 未来的版本中很可能不再支持。鼓励使用的方法是在函数定义中指定哪些参数应该用引用传递。鼓励大家尝试关闭此选项并确保脚本能够正常运行,以确保该脚本也能在未来的版本中运行(每次使用此特性都会收到一条警告,参数会被按值传递而不是按照引用传递)。
在函数调用时通过引用传递参数是不推荐的,因为它影响到了代码的整洁。如果函数的参数没有声明作为引用传递,函数可以通过未写入文档的方法修改其参数。要避免其副作用,最好仅在函数声明时指定那个参数需要通过引用传递。 当allow_call_time_pass_reference=Off时
<?php
function abc($a,$b){
echo "$a/n";
echo "$b/n";
$b = 'cde';
}
$a = 'abc';
$b = "bcd";
//不好的用法,会引发一个php warnning
abc($a ,&$b);
echo "$b/n";
?>
要想通过引用来传递参数$b,程序可改为
<?php
function abc($a,& $b){
echo "$a/n";
echo "$b/n";
$b = 'cde';
}
$a = 'abc';
$b = "bcd";
//正确的用法
abc($a ,$b);
echo "$b/n";
//output is:
//abc
//bcd
//cde
如果我的网站用的utf-8编码,为防止乱码出现,都需要注意哪些地方?
从以下几个方面考虑:
数据库中库和表都用utf8编码
php连接mysql,指定数据库编码为utf8 mysql_query(“set names utf8”);
php文件指定头部编码为utf-8header(“content-type:text/html;charset=utf-8”);
网站下所有文件的编码为utf8
html文件指定编码为utf-8
41.在url中用get传值的时候,若中文出现乱码,应该用哪个函数对中文进行编码?
urlencode()
42.写出两种对变量加密的函数?
md5(str);sha1(str);
php中WEB上传文件的原理是什么,如何限制上传文件的大小?
上传文件的表单使用post方式,并且要在form中添加enctype='multipart/form-data'。
一般可以加上隐藏域:,位置在file域前面。
value的值是上传文件的客户端字节限制。可以避免用户在花时间等待上传大文件之后才发现文件过大上传失败的麻烦。
使用file文件域来选择要上传的文件,当点击提交按钮之后,文件会被上传到服务器中的临时目录,在脚本运行结束时会被销毁,所以应该在脚本结束之前,将 其移动到服务器上的某个目录下,可以通过函数move_uploaded_file()来移动临时文件,要获取临时文件的信息,使用$_FILES。
限制上传文件大小的因素有:
客户端的隐藏域MAX_FILE_SIZE的数值(可以被绕开)。
服务器端的upload_max_filesize,post_max_size和memory_limit。这几项不能够用脚本来设置。
自定义文件大小限制逻辑。即使服务器的限制是能自己决定,也会有需要个别考虑的情况。所以这个限制方式经常是必要的
简述UBB code的实现原理。(YG)
UBB代码是HTML的一个变种,通过程序自定义我们的标签,比如“[a]PHP中UBB的使用[/a]”这样的标签,其实质就是查找[a][/a]标签,将其替换成的标准html,说白了,就是将标准的html标记通过技术手段使其简化,其输出出来的结果还是标准的html。
明白了ubb的原理,那么再制作一个简单的ubb编辑器就不难了,和fck之类的编辑器比较起来,ubb代码最大的优点就是代码简单,功能很少,简单的ubb只需要一个文件,而且ubb标签可以自己来定义,更改起来很方便,在php中就是利用替换函数就可以将
html进行标签化,输出时进行标签的转化。
什么是CSRF攻击?XSS攻击?如何防范?
CSRF:跨站请求伪造,可以通过通过判断来源和加 Token 的方式来防范。
XSS:跨站脚本攻击,可以通过对内容转义和过滤来防范,还有CSP
两条相交的单向链表,如何求它们的第一个公共节点
思想:
- 如果两个链表相交,则从相交点开始,后面的节点都相同,即最后一个节点肯定相同;
- 从头到尾遍历两个链表,并记录链表长度,当二者的尾节点不同,则二者肯定不相交;
- 尾节点相同,如果A长为LA,B为LB,如果LA>LB,则A前LA-LB个先跳过 如果两个单向链表有公共的结点,也就是说两个链表从某一结点开始,它们的m_pNext都指向同一个结点。但由于是单向链表的结点,每个结点只有一个m_pNext,因此从第一个公共结点开始,之后它们所有结点都是重合的,不可能再出现分叉。所以,两个有公共结点而部分重合的链表,拓扑形状看起来像一个Y,而不可能像X。
isset(null) isset(false) empty(null) empty(false)输出
PHP入门问题,isset和empty的区别
分别是false, true, true, true
优化MYSQL的方法
第一,数据超过一定数量或者体积,请拆分表,垂直或者水平分(最有效果的优化)
第二,务必有自增主键。通过自增主键来查数据是最快的。
第三,常用的查询字段建立联合索引,写SQL一定要尊从最左原则,用到这个索引。
第四,不要把逻辑运算放到sql里。言外之意是,不要写太复杂的SQL,你能写复杂的SQL 你肯定也能通过PHP实现。
PHP的数组和C语言的数组结构上有何区别?
但从PHP来讲,考的是PHP数组的实现。可以简单的认为,PHP的数组是hash桶 十字链表(实际上是数列Array,列表List,散列表/关联数组/字典Hashtable的聚合体)。优点是查询效率很高,遍历很方便,缺点是,占内存较多。(还是空间换时间的思路,毕竟现在内存又不值钱)
C语言的数组,就是定长定类型的数列。
26、Redis的跳跃表怎么实现的
跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
PHP的的这种弱类型变量是怎么实现的?
考zval的,PHP的八种类型,本质只有一个结构。
有两个文件文件,大小都超过了1G,一行一条数据,每行数据不超过500字节,两文件中有一部分内容是完全相同的,请写代码找到相同的行,并写到新文件中。PHP最大允许内内为255M。
将文件拆分成若干个小文件,根据内容计算hash值,分散到不同文件。
PHP如何实现不用自带的cookie函数为客户端下发cookie。对于分布式系统,如何来保存session值。
这个题有点绕。考的还是COOKIE和SESSION的基础知识。服务端通过set-cookie命令来通知客户端保存cookie。
只要按照domain path 过期时间等规则 用header函数就可以实现。
分布式系统session,集中处理。按我们公司的架构,为了实现高可用和高容灾,提供一个分布式的验签服务。具体的可以看下redis的分布式服务架构。
从用户在浏览器中输入网址并回车,到看到完整的见面,中间都经历了哪些过程。
入门问题。这个问题有一个很大的坑,面试官可能会从这个问题下手问你一大堆问题。
以PHP为例:通常最简单的回答,从用户的电脑找到最近的DNS服务,然后解析到对应的IP 然后双方开始HTTP连接,然后发送请求信息,服务器拿到请求信息就开始准备回应的信息,中间要经过nginx转发到frstCGI(PHP-FPM),然后PHP开始解析框架,解析请求头部,找到对应的API,该查数据库查数据,该组装HTML组装HTML,完事了就重新返回给用户。用户拿到返回数据,浏览器开始渲染页面,JS开始加载
如何分析一条sql语句的性能。
explain,具体的请百度。(基本很少用性能分析语句。MYSQL的表设计上尽量冗余一部分字段,避免在MYSQL里处理大量的逻辑运算。我们是做PHP服务开发的,mysql语句能简单尽量简单。逻辑运算的地方可以在PHP里做。)
48、ping一个服务器ping不通,用哪个命令跟踪路由包?
代码语言:javascript复制linux:traceroute,windows:tracert
a=[0,1,2,3]; b=[1,2,3,4,5]; a =b; var_dump(
基础问题。本质还是考PHP数组的结构和特点。
结果是01235。PHP用数字索引和STRING索引差别还是很大的
MYSQL主从服务器,如果主服务器是innodb引擎,从服务器是myisam引擎,在实际应用中,会遇到什么问题?
有10亿条订单数据,属于1000个司机的,请取出订单量前20的司机
(TIPS)不要中招。不要用常用思路来处理,10亿数据 你再怎么优化,全表求和,都是要死人的。
我们从设计上解决这个问题。只有一千个司机。我们可以做个简单哈希,分库分表,%求余数。保证这一千个司机分在一千个表里,每个人有每个人的单独表。引擎用MYSAIM,求表中数据的总数,效率飞快,遍历一千张表,求最大前二十即可。
php-fpm各配置含义,fpm的daemonize模式
php-fpm 的配置并不多,常用的就更少了。
参考:http://www.4wei.cn/archives/1002061
代码语言:javascript复制
static - 子进程的数量是固定的(pm.max_children)
ondemand - 进程在有需求时才产生(当请求时,与 dynamic 相反,pm.start_servers 在服务启动时即启动
dynamic - 子进程的数量在下面配置的基础上动态设置:pm.max_children,pm.start_servers,pm.min_spare_servers,pm.max_spare_servers
两台mysql服务器,其中一台挂了,怎么让业务端无感切换,并保证正常情况下讲台服务器的数据是一致的
不是核心业务的话,先停写,把备机拉起来,查看两台机器的日志,进行数据补偿,开写。
如果是核心业务的话,现在所有的写操作都在正常的状态机器上。把好的这台机器的备机拉起来,当主机。
以上全是应急操作。实际上数据库的容灾设计要复杂的多。
面试官要是问你,备机的数据不一致怎么办,你要勇敢怼回去,你们每秒多少写入操作。按照百万级表,每秒1000的写入效率,正常的设计是,分布在2台机器上每台500。这个级别的数据同步,出现差异的概率 可以忽略不计的。有一台出现问题,另一台也可以抗住。
(正常的操作,还是先停写,等数据一致,切换,开写。我们公司搞这些切换都是在凌晨4.00左右,核心业务的每秒写操作,只有十几个。前后耽搁不到20秒)。
72、rand与mt_rand的区别
我实习的时候遇到这个坑。
说是mt_rand比rand快4倍。
在随机数区间不大的情况下并没有很大的效率差距。但是出现重复数的几率,rand要比mt_rand高很多。
10瓶水,其中一瓶有毒,小白鼠喝完有毒的水之后,会在24小时后死亡,问:最少用几只小白鼠可以在24小时后找到具体是哪一瓶水有毒。
四只
二进制问题。薛定谔的老鼠。
一只老鼠有两个状态,死活,对应01。假设老鼠的个数为A,则有2^A>=10; A=4;
思路很简单,十瓶药编号:0,1,10,11....1001;
0不喝。第一只老鼠喝所有个位是1的:13579,第二只喝十位是1的,第三只和百位是1的,第四只喝千位是1的。
24小时后,看下死了的是1,活着的是0。按老鼠的顺序乖乖站好……假如第一只和第三只死了,那就是0101,就是5 有问题。
redis是如何进行同步的,同步的方式,同步回滚怎么办,数据异常怎么办,同时会问MYSQL的同步方式和相关异常情况
redis 集群主从同步的简单原理
Redis的复制功能是基于内存快照的持久化策略基础上的,也就是说无论你的持久化策略选择的是什么,只要用到了Redis的复制功能,就一定会有内存快照发生。
当Slave启动并连接到Master之后,它将主动发送一个SYNC命令( 首先Master会启动一个后台进程,将数据快照保存到文件中[rdb文件] Master 会给Slave 发送一个
Ping命令来判断Slave的存活状态 当存活时 Master会将数据文件发送给Slave 并将所有写命令发送到Slave )。
Slave首先会将数据文件保存到本地 之后再将 数据 加载到内存中。
当第一次链接 或者是 故障后 重新连接 都会先判断Slave的存活状态 在做全部数据的同步 , 之后只会同步Master的写操作(将命令发送给Slave)
问题:
当 Master 同步数据时 若数据量较大 而Master本身只会启用一个后台进程 来对多个Slave进行同步 , 这样Master就会压力过大 , 而且Slave 恢复的时间也会很慢!
redis 主从复制的优点:
代码语言:javascript复制 (1)在一个Redis集群中,master负责写请求,slave负责读请求,这么做一方面通过将读请求分散到其他机器从而大大减少了master服务器的压力,另一方面slave专注于提供
读服务从而提高了响应和读取速度。
(2)在一个Redis集群中,如果master宕机,slave可以介入并取代master的位置,因此对于整个Redis服务来说不至于提供不了服务,这样使得整个Redis服务足够安全。
(3)水平增加Slave机器可以提高性能
78、怎么解决跨域
- JSONP
- 添加响应头,允许跨域
- 代理的方式
79、json和xml区别,各有什么优缺点
(1)可读性方面:基本相同,XML的可读性比较好;
(2)可扩展性方面:都具有良好的扩展性;
(3)编码难度方面:相对而言,JSON的编码比较容易;
(4)解码难度:JSON的解码难度基本为零,XML需要考虑子节点和父节点;
(5)数据体积方面:JSON相对于XML来讲,数据体积小,传递的速度比较快;
(6)数据交互方面:JSON与javascript的交互更加方便,更容易解析处理,更好的数据交互;
(7)数据描述方面:XML对数据描述性比较好;
(8)传输速度方面:JSON的速度远远快于XML。
80、Trait优先级
在trait继承中,优先顺序依次是:来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法
80、Trait优先级
在trait继承中,优先顺序依次是:来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法
81、a引用b,报错c里面类重复定义,循环引用会出现什么问题
82、下面员工3的薪水大于其主管的薪水,一条SQL找到薪水比下属低的主管
id | username | salary | pid |
---|---|---|---|
1 | a | 3000 | null |
2 | b | 8000 | null |
3 | c | 5000 | 1 |
4 | d | 6000 | 3 |
SELECT a.*, b.*
FROM `user` as a
LEFT JOIN `user` as b ON a.pid = b.id AND a.salary > b.salary
WHERE b.id > 0;
82、在一个坐标系内有一个N个点组成的多边形,现在有一个坐标点,写代码或思路来判断这个点是否处于多边形内
分析一个问题:php-fpm的日志正常,但客户端却超时了,你认为可能是哪里出了问题,怎么排查?
检查nginx log,请求是否达到nginx 和是否正常转发给 php-fpm
进程间通信方式有哪些
1)管道 管道分为有名管道和无名管道 无名管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系一般指的是父子关系。无明管道一般用于两个不同进程之间的通信。当一个进程创建了一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。 有名管道也是一种半双工的通信方式,但是它允许无亲缘关系进程间的通信。
2)信号量 信号量是一个计数器,可以用来控制多个线程对共享资源的访问.,它不是用于交换大批数据,而用于多线程之间的同步.它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源.因此,主要作为进程间以及同一个进程内不同线程之间的同步手段.
3)信号 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生.
4)消息队列 消息队列是消息的链表,存放在内核中并由消息队列标识符标识.消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点.消息队列是UNIX下不同进程之间可实现共享资源的一种机制,UNIX允许不同进程将格式化的数据流以消息队列形式发送给任意进程.对消息队列具有操作权限的进程都可以使用msget完成对消息队列的操作控制.通过使用消息类型,进程可以按任何顺序读信息,或为消息安排优先级顺序.
5)共享内存 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问.共享内存是最快的IPC(进程间通信)方式,它是针对其它进程间通信方式运行效率低而专门设计的.它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步与通信.
6)套接字:可用于不同及其间的进程通信
88、主从复制,从服务器会读取到主服务器正在回滚的数据吗?主数据库写成功,从服务器因为一些原因写失败,最后会出现什么情况?主从复制如果键冲突怎么办?
不会;主从数据不一致;正常是不会出现这种情景,具体看情况,是否可以修复,恢复到之前的时间点,然后追回同步。
89、事务有几种隔离级别?事务的隔离级别是怎么实现的?
- 读未提交(read-uncommitted)
- 不可重复读(read-committed)
- 可重复读(repeatable-read)
- 串行化(serializable)
self和static的区别
static:如果在子类中重写了父类中的static方法、属性,父类就会去访问了子类的static方法
self: 是类内指针,不管子类有没有重写过父类中的方法、属性都指向本类的静态方法、属性
102、mysql中字段类型各占几个字节:smallint、int、bigint、datetime、varchar(8)
- smallint 2字节
- int 4字节
- bigint 8字节
- datetime 8字节
- varchar(8) 8*3字节
105、断开TCP连接时,timewait状态会出现在发起分手的一端还是被分手的一端
为什么建立TCP连接需要三次握手? 原因:为了应对网络中存在的延迟的重复数组的问题 例子: 假设client发起连接的连接请求报文段在网络中没有丢失,而是在某个网络节点长时间滞留了,导致延迟到达server。本来这是一个已经失效的连接报文,但是server接收到这个连接报文之后,误认为client发起了新的连接,于是向client发送确认报文段。此时因为没有了连接的3次握手,client不会对server的确认报文作出回应,也不会向server发送数据,server就以为连接已经建立,一直在空等client的数据,这样server的这一部分网络资源就被浪费了。
为什么断开TCP连接需要进行四次握手 ? 因为TCP连接是全双工的网络协议,允许同时通信的双方同时进行数据的收发,同样也允许收发两个方向的连接被独立关闭,以避免client数据发送完毕,向server发送FIN关闭连接,而server还有发送到client的数据没有发送完毕的情况。所以关闭TCP连接需要进行四次握手,每次关闭一个方向上的连接需要FIN和ACK两次握手。
TIME_WAIT状态的意义
在TCP连接中,当被动关闭连接的一方(图中client)发送的FIN报文到达时,被动关闭连接的一方会发送ACK确认报文,并且进入TIME_WAIT状态,并且等待2MSL时间段(MSL:maximum segment life)。这么做有下述两个原因:
被动关闭连接的一方(图中的server)在一段时间内没有收到对方的ACK确认数据包,会重新发送FIN数据包,因而主动关闭连接的一方需要停留在等待状态以处理对方重新发送的FIN数据包。否则他会回应一个RST数据包给被动关闭连接的一方,使得对方莫名其妙。
在TIME_WAIT状态下,不允许应用程序在当前ip和端口上和之前通信的client(这个client的ip和端口号不变)建立一个新的连接。这样就能避免新的连接收到之前的ip和端口一致的连接残存在网络中的数据包。这也是TIME_WAIT状态的等待时间被设置为2MSL的原因,以确保网络上当前连接两个方向上尚未接收的TCP报文已经全部消失。
、如果某个博客通过判断 referer 方式来进行图片防盗链,如何破解?
curl 设置来源地址来欺骗对方服务器验证
115、单例模式的优点是什么?抽象类是什么?还了解哪些设计模式?
单例模式又称为职责模式,它用来在程序中创建一个单一功能的访问点,通俗地说就是实例化出来的对象是唯一的。 所有的单例模式至少拥有以下三种公共元素:
- 它们必须拥有一个构造函数,并且必须被标记为private
- 它们拥有一个保存类的实例的静态成员变量
- 它们拥有一个访问这个实例的公共的静态方法 单例类不能再其它类中直接实例化,只能被其自身实例化。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。
抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
https://blog.csdn.net/mengziwudao/article/details/99456399