1:mvc是是什么?相互间有什么关系?
mvc是一种设计模式,m(model)模型层,v(view)视图层,c(controller)逻辑层
客户端发起请求->控制器处理请求,如果用到数据则请求模型层->返回视图层
2:oop是什么?
oop是面向对象编程,面向对象编程是一种计算机编程架构,与之相对的是面向过程编程
oop具有3大特点:
①封装性:就是信息隐藏,就是实现类中的public,protected,private3个关键字的使用上,把类的使用和实现分开,只保留 部分接口和和方法与外部联系,大量的实现过程被封装对外不可见
②继承性:就是子类自动继承其父类的属性和方法,就是extends关键字的使用,并且可以添加新的属性和方法,可以修过已有的属性和方法,继承性增加了代码的可重用性,php只支持单继承(通过接口可以实现多继承),别担心,c#、java也是单继承,c++是多继承
③多态性:子类继承了来自父类中的属性和方法,并对其进行重写。多个子类就得到多个结果。或者对interface和abstract的实现上得到不同的实现方式,这个叫多态性。多态性增强了软件的灵活性
oop的好处:
易维护,易扩展, 效率高,质量高(两易,两高)
3:smarty是什么,有什么作用?
smarty是用php写出来的模版引擎,是业内最名气最大的那一款,它分离了逻辑代码和外在的显示;
通俗点就是我们的php视图层是html和php糅合到一起的,模版引擎就是去分离它们的;
相应的就可以设置缓存参数把对应的html代码缓存下来,生成静态页面;
不过在现在模版引擎已经慢慢的不经常用了,因为更多的项目是采用前后端分离的架构模式
4:简述一下数据库的优化?
数据库的优化可以从四方面来优化:
①从结构层:web服务器采用负载均衡服务器,mysql服务器采用主从复制,读写分离
②从存储层:采用合适的存储引擎,采用三范式
三范式:通俗讲,第一范式,关系模型中,属性不可在分,确保每一列的原子性;第二范式,满足第一范式前提下,表中每一行 的数据只能和其中一列属性相关,只要数据列中出现数据重复,就要把表拆分开来;第三范式,数据不存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。
③设计层:采用分区分表,索引,表的字段采用合适的字段属性,适当的采用逆范式,开启mysql的缓存
④sql语句层:结果一样的情况下,采用效率高,速度快节省资源sql语句执行
5:php如何解决异常?
抛出异常:使用try...catch,异常的代码放在try代码块内,如果没有触发异常,则代码继续执行,如果触发异常,则抛出一个异常,catch代码块捕获异常,并创建一个包含异常信息的对象。$e->getMessage(),输出异常的错误信息。
解决异常:使用set_error_handler函数获取异常(也可以使用try()和catch()函数),然后使用set_exception_handler()函数设置默认的异常处理程序,register_shutdown_function()函数来执行,执行机制是:php把要调用的函数加载到内存中,当页面所有php语句执行完毕时,再调用此函数
6:权限关系(RBAC)的实现?
基于角色权限的访问控制(Role-Based Access Control)
简单实现:①首先创建用户表:id name auto(保存格式是:控制器-方法)
②后台创建一个基类控制器,控制器里封装一个构造方法,用户登录成功后,使用框架封装好的session函数获取对应的sessionId,通过用户id获取数据表中的auth数据,使用explode函数进行分割获取数据 ,得到登录者具有的控制器和方法,也可以把它们组装成字符串,使用in_array函数进行判断是否在一个定义好的数组中,以此判断是否具有控制器和方法的访问权限
7:登录的实现?
登录分两种普通登录和第三方登录,主要介绍下第三方登录,第三方登录主要实用的是author协议,比如qq第三方登录,首先是站点会引导用户跳转到qq的登录授权界面,当用户 输入qq和密码成功登录后会自动跳转到我们站点设置好的回调页面,并附带一个code参数,接着我们使用code再次请求qq的授权页面,就可以从中获取到一个 access_token(访问令牌),通过这个 access_token,我们可以调用qq提供给我们的接口,比如 获取open_id,可以获取用户的基本信息。获取后我们需要拿到用户的授权信息和open_id和我们平台的普通用户进行绑定,这样便实现了第三方登录
8:接口安全方面是怎么处理的 ?
①利用http中的post请求方式
②定义好前后端的验证规则:一般的是固定参数+附加参数进行数字签名(进行按照key的字母a-z顺序排列)(加上一个双方规定好的key),使用md5进行加密的到签名sign。也可以加个时间戳进行验证请求时间范围(比如5分钟有效),服务器得到数据后利用同样的规则进行解密验证
9:用的什么技术实现短信发送,在哪调用
主要用的是第三的短信接口,在申请接口的时候进行相应的信息配置,然后在我们站点需要用到短信验证的地方进行调用,我们通常在用户注册的使用使用到短信验证
10:写过接口?如果定义接口?
这里的接口有两层含义:①数据型接口,Interface定义,是一种语法结构,是一种结构规范,规范实现类的格式,团队比较大时用到
②应用型接口:俗称api(application interface)数据对外访问的一个入口,按照客户端需要的数据进行设计,主要以json、xml的格式进行返回,并配有文档
11:redis如何防止高并发问题?
首先解释一下什么是并发:高并发是互联网分布式系统架构设计中必须考虑的因素之一,它通常指,通过设计保证系统能够同时并行处理很多请求
另外并发和并行的区别:
- 你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行
- 你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发
- 你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行
并发:你有处理多个任务的能力,不一定同时(一个CPU轮流)
并行:有同时处理多个任务的能力(多个CPU同时)
并发关乎结构,并行关乎执行
回到问题上,redis本身是单进程,再多的command的都是 one by one执行的,其实没有所谓的高并发问题,我们指的高并发是指使用的时候出现get和set操作问题
redis是单线程机制的nosql数据库,基于key-value,数据可持久化落盘,单线程的先天性基因决定了,高并发对一个键的操作会排列处理,如果并发量很大,可能造成后来的请求超时。如在远程访问redis的时候,因为网络等原因造成高并发访问延迟返回的问题
解决办法:
在客户端将连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
服务器角度,利用setnx变向实现锁机制。
12:支付宝支付流程怎么实现?
①首先一个支付宝账号,接下来向支付宝申请在线支付业务 ,签署协议。协议生效后支付宝一方给网站合作伙伴ID,和安全校验码,有了这两样东西就可以按照支付宝接口文档开发支付接口了,中间主要涉及到一个安全问题。
②整个流程是这样的,我们网站通过post传递相应的参数(订单的总金额,订单号)到支付页面;
③支付页面把一系列的参数经过处理,以post的方式提交个支付宝服务器,支付宝服务器进行验证,并对接收的数据进行处理;④把处理后的结构返回给我们网站设置的异步和同步回调地址,通过相应的返回参数,来处理相应的业务逻辑,比如返回的参数代表支付成功,更改订单状态
13:什么是单点登录?
单点登录SSO(Single sign on),就是指在一个多系统共存的系统环境下,用户在一处登录后,就不用在其他系统中进行登录而能获得所有系统的信任
实现:第一次访问系统时候,因为没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证凭证--ticket,作为自己的认证凭证;应用系统接收到请求之后会把ticket送到认证系统进行校验,检验ticket的合法性,如果合法则顺利访问其他系统
应用技术点:
①多个站点共用一个数据验证系统
②主要通过跨域请求的方式来实现验证及session处理
14:如何处理负载,高并发?
从低成本,高性能和高扩展性的角度来分析和提出解决方案
①html的静态化
②图片服务器的分离 把图片单独存储,尽量减少图片等大流量的开销,可以放到相关的平台上,如七牛等
③数据库的集群和库表散列及数据库缓存(利用redis,memcache进行数据缓存)
④负载均衡 利用服务器apache和nginx的设置来实现
⑤镜像 把不同的请求发送到多个镜像端
15:封装一个简单的框架
框架基于mvc模型,模型层,控制器层,视图层;路由的分配的单个入口文件,模版引擎的应用,单例模式,工厂模式应用;第三方的类库的引入等
16:session和cookie区别
①cookie是放在客户端浏览器中的,session是存放到服务器中的
②cookie不安全,因为cookie可以被脚本获取,进行cookie欺骗
③session是存放到服务器端,相对于cookie比较安全,但是因为放到服务器端,当访问量增多时,会比较占用服务器性能
④单个cookie保存数据不能超过4k,很多很多浏览器限制一个站点最多保存20个cookie
所以对应登录的重要信息保存到session中,其他信息可以放到cookie中
17:echo ,print print_r的区别?
echo可以同时输出多个值,它是一种语言结构,是php的内部指令,不是函数,因此不能作为表达式的一部分使用
print()函数,打印一个值,此函数有返回值,如果成功打印则返回true,否则返回false,只能打印简单类型的数据类型变量
printf()函数,输出格式化的字符串
print_r()函数,可以打印复杂的数据和简单的数据,有返回值
var_dump()函数,判断变量的类型与长度,并输出变量的数值,显示出数据的结构
18:单双引号的区别?
①单引号比双引号速度快
②双引号可以解析所有的特殊字符,单引号只能解析部分特色字符
19:get和post的区别?
①get从服务器获取数据,post向服务器传送数据
②get是把参数数据队列加到提交表单的action属性所指的url中,值和表单内各个字段一一对应,在url中可以看到。post请求是http post机制,将表单内各个字段与其内容放置在html header内一起传送到action属性所指的url地址。用户 看不到
③get传递的数据量较小,不能大于2kb。post传递的数据量较大,一般默认不做限制
④post比get的安全型高,效率上get比post快
20:修过session的生成时间
①配置文件中php.ini,session.gc_maxlifetime = 1440 //默认时间
②代码层面
$lifeTime = 24*3600; //保存一天
session_set_cookie_params($lifeTime);
session_start();
21:常用魔术常量(8个)
魔术(magic),常量我们知道是定义好之后不可变,直到销毁;但是这里的php预定义的常量会随着所除位置值发生变化,所以也可以称为魔术变量
__LINE__:文件中的当前行号
__FILE__:文件的完整路径和文件名。如果用在被包含的文件中,则返回被包含的文件名
__DIR__:文件所在的目录,如果用在被包含 的文件中,则返回被包含的文件所在的目录
__FUNCTION__:用在函数内部,返回函数被定义时的名字(区分大小写)
__CLASS__:用在类内部,返回类被定义时的名字(区分大小写)
__METHOD__:用在类的方法中,返回该方法被定义时的名字(区分大小写)
__NAMESPACE__:当前命名空间的名称,此常量是在编译时定义的
22:常用超全局变量(9个)
$GLOBALS:存储全局作用域中的变量
$_SERVER:获取服务器相关信息
$_REQUEST:获取POST和GET请求的参数
$_POST:获取表单提交的 POST请求参数
$_GET:获取表单请求的GET请求参数
$_FILES:获取上传文件的变量
$_ENV:获取 服务器端环境变量的数组
$_COOKIE:获取浏览器cookie的数据
浏览器cookie的操作
设置cookie:setcookie(name,value,expire,path,domain);
获取cookie:$_COOKIE['user'];
删除cookie:setcookie('user','',time()-3600);//设置过期时间
$_SESSION:服务端session的 操作
使用session前一定要 session_start()启动session
存储session:$_SESSION['name'] = 'what';//数组操作
销毁session:unset($_SESSION['views']);//销毁一个
session_destroy()和unset($_SESSION);//销毁所有
23:魔术方法(13个)
__construct()
实例化对象的时候被调用
__destruct()
当删除一个对象或者对象操作终止时被调用,大意就是说只要类中包含这个方法,那么程序结束或者主动去删除实例化的对象 时 都会调用 这个方法
__call()
对象调用某个方法,如果方法存在,则直接调用,如果方法不存在,那么就会调用__call()方法
__get()
读取一个对象的属性时, 若属性存在,则直接返回属性值;如果不存在,则会调用__get()方法
__set()
设置对象的属性时,若属性存在,则直接赋值,如果不存在,则会调用__set()函数
__toString()
打印一个对象的时候被调用,如echo $obj或者print $obj
__clone()
克隆对象的时候被调用。如:$t=new Test(); $t1=clone $t;
__sleep()
serialize之前被调用,如果对象比较大,想删减一点东东再序列化,可以考虑此函数
__wakeup()
unserialize时被调用,做些对象的初始化工作
__isset()
检测一个对象的属性是否存在时被调用,如isset($c->name)
__unset()
unset一个对象的属性时被调用,如unset($c->name)
__set_state()
调用var_export时,被调用。用__set_state的返回值作为var_export的返回值
这里介绍一下var_export()函数的用法:此函数当$str = var_export($arr,true);可以得到保留数据结构的字符串数据,把相应的字符串数据转变成数组则 $arr = eval("return $a;"); 主要用于存储数据库得到的数组数据信息和file_put_content配合使用
__autoload()
实例化一个对象时,如果对应的类不存在,则该方法会被调用;目前看来只有这个方法是放到类外部的
24:常用的数组函数
①数组的基本函数
数组的键名和值
array_values($arr); 获得数组的值
array_keys($arr);获得数组的键名
array_flip($arr) ; 数组中的值与键名互换(如果有重复,前面的会被后面的覆盖)
in_array('str',$arr);在数组中检索str
array_search('str',$arr) ; 在数组中检索apple,如果存在返回键名
array_key_exists('str',$arr) ; 检索给定的键名是否存在数组中
isset($arr['str']) ; 检索给定的键名是否 存在数组中
②数组的分段和填充
数组的分段
array_slice($arr,0,3);可以将数组中的一段取出,此函数忽略键名
array_splice($arr,0,3,array('black','marron'));可以将数组中的一段取出,与上一个函数不同在于返回的序列从原数组中删除
分割多个数组
array_chunk($arr,3,true);可以将一个数组分割成多个,true为保留原数组的键名
填充数组
array_pad($arr,5,'x');将一个数组填充到指定的长度
③数组与栈
④数组与队列
⑤数组的排序
通过元素值对数组排序
sort($arr);由小到大的顺序排列,忽略键名的数组排序
rsort($arr);由大到小的顺序排序,忽略键名的数组排序
asort($arr);由小到大的顺序排序,保留键名的数组排序
arsort($arr);由大到小的顺序排序,保留键名的数组排序
通过键名对数组进行排序
ksort($arr);按照键名的正序排序
krsort($arr);按照键名的逆序排序
⑥数组的计算
数组元素的求和
array_sum($arr);对数组内部的所有元素求和运算
数组的合并
array_merge($arr1,$arr2);合并两个或者多个数组(规则如下:相同的字符串键名,后面覆盖前面,相同的数字键名,后面的附加的后面)
$arr1+$arr2,两个或者多个数组相加,(规则是 ,相同的键名只保留前一个,无论键名是数字还是字符串)
array_merge_recursive($arr1,$arr2);递归合并操作,如果数组中有相同的字符串键名,这些值被合并到一个数组中去;如果一个值本身是一个数组,按照相应的键名把它合并为另一个数组。当数组具有相同的数组键名时,后一个值将不会覆盖原来的值,而是附加到后面
25:常用的字符串函数
包含8大类的字符串类型函数:
①字符串长度的函数
strlen()和mb_strlen(),后者需要开启mbstring扩展
②比较字符串
strcmp(),strcasecmp(),strspn(),strcspn()
③分割连接反转
str_split(),split(),explode(),implode()
④html与字符串相互转化
htmlspecialchars(),strip_tags(),get_html_translation_table(),addcslashes(),htmlentities()
⑤填充和剔除字符串
trim(),ltrim(),rtrim(),str_pad(),chunk_split()
⑥统计字符串和单词个数
count_chars(),str_word_count()
⑦查找替换截取
strpos(),str_replace(),substr_replace(),substr(),strstr()
⑧大小写处理
strtolower(),strtoupper(),ucfirst(),ucwords()
借鉴网站:https://blog.csdn.net/u011330276/article/details/79597200