php面试题

一:PHP
1:isset() 和 empty()的区别:
答:PHP的isset()函数 一般用来检测变量是否设置,PHP的empty()函数 判断值为否为空

2:php有哪些魔术方法
答: __construct(), __destruct(), __call(), __callStatic(), __get(),
__set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(),
__invoke(), __set_state(), __clone() 和 __debugInfo() 等方法在 PHP 中
被称为魔术方法(Magic methods)。在命名自己的类方法时不能使用这些方法名,除非是想
使用其魔术功能

3:echo,print_r,print,var_dump有什么区别
答: echo()函数:输出一个或多个字符串。实际上它并不是一个函数,所以不必对它使用括号,直接用echo就行

print()函数:输出一个或多个字符串。同echo一样,实际上它并不是一个函数。print有返回值,而echo没有,
当其执行失败时返回false,成功则返回true,速度比echo稍慢。只能打印出简单类型变量的值,如:int、string。

print_r()函数:能打印出复杂类型变量的值。利用print_r()可以打印出整个数组内容及结构,按照一定格式显示键
和元素,事实上,它不仅仅用于打印,而是用于打印关于变量的易于理解的信息

var_dump()函数:判断一个变量的类型与长度,并输出变量的数值,如果变量有值,输出的是变量的值,并返回数据类型。
此函数显示关于一个或多个表达式的结构信息,包括表达式的类型和值。数组将递归展开值,通过缩进显示其结构

4:如何判断一个函数是否存在
答:函数检测用function_exists,注意待检测的函数名也需要使用引号,如:
if (function_exists('imap_open')) {
echo "存在函数imag_openn";
} else {
echo "函数imag_open不存在n";
}

5:@这个符号表示什么意思
答:阻止警告输出。 有些函数,在遇到入参不正确时,会提示警告,但程序也可以正常运行。其实只要把警告去掉就可以,所以
就有@这个符号

6:PHP获取客户端和服务器端IP
答:客户端的ip变量:
$_SERVER['REMOTE_ADDR'] :客户端IP,也有可能是代理IP
$_SERVER['HTTP_CLIENT_IP']:代理端的IP,可能存在,也可能伪造
$_SERVER['HTTP_X_FORWARD_FOR'] :用户在哪个ip上使用的id,可能存在,也可能伪造

服务端的ip变量:
$_SERVER['SERVER_NAME'] :需要使用函数gethostname()来获得,这个无论是服务器端还是客户端都能正常显示。
$_SERVER['SERVER_ADDR']:服务器端的ip地址,在服务器端测试ip地址,在客户端测试正常
getnev 获得系统的环境变量:

7:preg_replace()和str_ireplace()两个函数在使用上有什么不同
答:str_replace() 函数定义:使用一个字符串替换字符串中的另一些字符,对大小写敏感的搜索语法:
str_replace(find,replace,string,count)

str_ireplace() 函数
定义:使用一个字符串替换字符串中的另一些字符,对大小写不敏感的搜索
语法:str_ireplace(find,replace,string,count)

二:MYSQL
1:MyISAM和InnoDB的基础区别
答:InnoDB:
支持事务处理等
不加锁读取
支持外键
支持行锁
不支持FULLTEXT类型的索引
不保存表的具体行数,扫描表来计算有多少行
DELETE 表时,是一行一行的删除
InnoDB 把数据和索引存放在表空间里面
跨平台可直接拷贝使用
InnoDB中必须包含AUTO_INCREMENT类型字段的索引
表格很难被压缩

MyISAM:
不支持事务,回滚将造成不完全回滚,不具有原子性
不支持外键
不支持外键
支持全文搜索
保存表的具体行数,不带where时,直接返回保存的行数
DELETE 表时,先drop表,然后重建表
MyISAM 表被存放在三个文件 。frm 文件存放表格定义。 数据文件是MYD (MYData) 。 索引文件是MYI (MYIndex)引伸
跨平台很难直接拷贝
MyISAM中可以使AUTO_INCREMENT类型字段建立联合索引
表格可以被压缩

选择:
因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原子性要求低。那么MyISAM最好的选择。且MyISAM恢复速度快。可直接用备份覆盖恢复。
如果系统读少,写多的时候,尤其是并发写入高的时候。InnoDB就是首选了。
两种类型都有自己优缺点,选择那个完全要看自己的实际类弄。

2:Mysql经常写的语句
答:1.创建数据库 CREATE DATABASE 数据库名;

2.删除数据库 drop database 数据库名;

3.选择数据库 mysql> use RUNOOB;

4.删除表
mysql> DROP TABLE runoob_tbl
update students settel=default where id=5;
将手机号为 13288097888 的姓名改为 “小明”, 年龄改为 19:
update students setname="小明", age=19 wheretel="13288097888";

5.删除
mysql> DELETE FROM runoob_tbl WHERE runoob_id=3;

6.like子句
mysql> SELECT * from runoob_tbl WHERE runoob_author LIKE '%COM';

7.排序
你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列。 默认情况下,它是按升序排列。
这是升序
mysql> SELECT * from runoob_tbl ORDER BY submission_date ASC;
order by code,name desc等同于order by code asc, name desc
这是降序
select * from a order by code desc, name desc;
1
2
3
4
5
6
7

8.常用聚合函数
1 count 2 sum 3 avg 4 max 5 min

9.多表查询
- as关键字可用来做别名识别
- 默认连接的是内连接(也叫做等值连接)
select * from book b inner join category c
on b.category_id = c.category_id;
1
2
相当于:
select * from book b ,category c
where b.category_id = c.category_id;
1
2
外连接有左右连接(如下):
- 左连接(以左边为基准):
查询出所有的书籍分类,及每个分类下的书籍信息;

select * from category c left (outer) join book b on c.category_id = b.category_id;
右连接(以右边为基准):
查询出所有的书籍分类,及每个分类下的书籍信息;
select c.*,b.* from book b right (outer) join category c on c.category_id = b.category_id;

10.NULL的处理
查找数据表中 runoob_test_tbl 列是否为 NULL
- 必须使用 IS NULL 和 IS NOT NULL

11.分页查询
查询第11到第15条数据
select * from table_name limit 10,5
1
limit关键字的用法:
LIMIT [offset,] rows
offset指定要返回的第一行的偏移量,rows第二个指定返回行的最大数目。
初始行的偏移量是0(不是1)。
1
2
3

12.创建视图
create view demo_view as select * from demo_table;
好处1:减少数据的冗余,方便对数据操作
数据库虽然可以存储海量数据,但是在数据表设计上却不可能每种关系创建数据表
例如,对于学生表,存储了学生信息,学生的属性包括学号、姓名、年龄、家庭地址等信息;而学生成绩表只存储了学生学号、
科目、成绩等信息。现获得学生姓名和成绩信息,那么就需要创建一个关系,该关系需要包含学生的姓名、科目、成绩。但是为
了该关系创建一个新的数据表,并利用实际信息进行填充,以备查询使用,是不合适的,这样会造成了数据库中数据的大量冗余。
视图就是解决这个问题的最佳策略,因此视图可以存储查询定义,一旦使用视图存储了查询定义,就如同存储了一个新的关系,用
户就可以直接对视图中所存储的关系进行各种操作,就如同面对的是真实的数据表。
好处2:数据的安全和保密
一个数据表可能包含很多列,但是这些列的信息,对于不同的角色来说,肯定不是全部公开的,对于员工表来说吧,一个普通的员
工只能看见这个员工表中的姓名和年龄这些信息,但是对于高层来说,他们要看见员工表中更多信息,不仅仅是上面的两列还有其他的
信息,包括员工的住址和员工的薪资待遇,这个时候都是同一张表,怎么办?视图可以解决呀,首先建立一个视图只有员工的姓名和年
龄,再建一个视图包含地址和薪资待遇的信息。这样就可以根据不同的角色分配两个视图的查询权限,与实际表隔离开来。这样就可以
提高数据访问的安全性了。

13.创建存储过程
DELIMITER //
CREATE PROCEDURE myproc(OUT s int)
BEGIN
SELECT COUNT(*) INTO s FROM students;
END
//
DELIMITER ;
1
2
3
4
5
6
7

14.触发器
CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt
trigger_name:触发器的名称
tirgger_time:触发时机,为BEFORE或者AFTER
trigger_event:触发事件,为INSERT、DELETE或者UPDATE
tb_name:表示建立触发器的表明,就是在哪张表上建立触发器
trigger_stmt:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句
1
2
3
4
5
6
所以可以说MySQL创建以下六种触发器:
BEFORE INSERT,BEFORE DELETE,BEFORE UPDATE
AFTER INSERT,AFTER DELETE,AFTER UPDATE
1
2
tips:一般情况下,mysql默认是以 ; 作为结束执行语句,与触发器中需要的分行起冲突为解决此问题可用DELIMITER,如:
DELIMITER ||,可以将结束符号变成||当触发器创建完成后,可以用DELIMITER ;来将结束符号变成;
mysql> DELIMITER ||
mysql> CREATE TRIGGER demo BEFORE DELETE
-> ON users FOR EACH ROW
-> BEGIN
-> INSERT INTO logs VALUES(NOW());
-> INSERT INTO logs VALUES(NOW());
-> END
-> ||
Query OK, 0 rows affected (0.06 sec)
mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql> delimiter $$
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account
-> FOR EACH ROW
-> BEGIN
->   IF NEW.amount < 0 THEN
->     SET NEW.amount = 0;
->   ELSEIF NEW.amount > 100 THEN
->     SET NEW.amount = 100;
->   END IF;
-> END$$
mysql> delimiter;

3:mysql explain的意义
答:模拟Mysql优化器是如何执行SQL查询语句的,从而知道Mysql是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈
(粗略的了解)

4:写出mysqldump的用法
答:(1)导出整个数据库(包括数据库中的数据)
mysqldump -u username -p dbname > dbname.sql

(2)导出数据库结构(不含数据)
mysqldump -u username -p -d dbname > dbname.sql

(3)导出数据库中的某张数据表(包含数据)
mysqldump -u username -p dbname tablename > tablename.sql

(4)导出数据库中的某张数据表的表结构(不含数据)
mysqldump -u username -p -d dbname tablename > tablename.sql

mysqldump常用参数说明:
--all-databases , -A 导出全部数据库
mysqldump -uroot -p --all-databases

--all-tablespaces , -Y导出全部表空间。
mysqldump -uroot -p --all-databases --all-tablespaces --no-tablespaces , -y不导出任何表空间信息。
mysqldump -uroot -p --all-databases --no-tablespaces

--add-drop-database每个数据库创建之前添加drop数据库语句。
mysqldump -uroot -p --all-databases --add-drop-database

--add-drop-table每个数据表创建之前添加drop数据表语句。(默认为打开状态,使用--skip-add-drop-table取消选项)
mysqldump -uroot -p --all-databases (默认添加drop语句)
mysqldump -uroot -p --all-databases --skip-add-drop-table (取消drop语句)

--add-locks在每个表导出之前增加LOCK TABLES并且之后UNLOCK TABLE。(默认为打开状态,使用--skip-add-locks取消选项)
mysqldump -uroot -p --all-databases (默认添加LOCK语句)
mysqldump -uroot -p --all-databases --skip-add-locks (取消LOCK语句)

--comments附加注释信息。默认为打开,可以用--skip-comments取消
mysqldump -uroot -p --all-databases (默认记录注释)
mysqldump -uroot -p --all-databases --skip-comments (取消注释)

--compact导出更少的输出信息(用于调试)。去掉注释和头尾等结构。可以使用选项:--skip-add-drop-table

--skip-add-locks --skip-comments --skip-disable-keysmysqldump -uroot -p --all-databases --compact

--complete-insert, -c使用完整的insert语句(包含列名称)。这么做能提高插入效率,但是可能会受到max_allowed_packet参数
的影响而导致插入失败。
mysqldump -uroot -p --all-databases --complete-insert

--compress, -C在客户端和服务器之间启用压缩传递所有信息
mysqldump -uroot -p --all-databases --compress

--databases, -B导出几个数据库。参数后面所有名字参量都被看作数据库名。
mysqldump -uroot -p --databases test mysql

--debug输出debug信息,用于调试。默认值为:d:t:o,/tmp/mysqldump.tracemysqldump -uroot -p --all-databases
--debugmysqldump -uroot -p --all-databases --debug=” d:t:o,/tmp/debug.trace”
--debug-info输出调试信息并退出
mysqldump -uroot -p --all-databases --debug-info

--default-character-set设置默认字符集,默认值为utf8
mysqldump -uroot -p --all-databases --default-character-set=latin1

--delayed-insert采用延时插入方式(INSERT DELAYED)导出数据
mysqldump -uroot -p --all-databases --delayed-insert

--events, -E导出事件。
mysqldump -uroot -p --all-databases --events

--flush-logs开始导出之前刷新日志。请注意:假如一次导出多个数据库(使用选项--databases或者--all-databases),
将会逐个数据库刷新日志。除使用--lock-all-tables或者--master-data外。在这种情况下,日志将会被刷新一次,相应的
所以表同时被锁定。因此,如果打算同时导出和刷新日志应该使用--lock-all-tables 或者--master-data 和--flush-logs。
mysqldump -uroot -p --all-databases --flush-logs

--flush-privileges在导出mysql数据库之后,发出一条FLUSH PRIVILEGES 语句。为了正确恢复,该选项应该用于导出mysql
数据库和依赖mysql数据库数据的任何时候。
mysqldump -uroot -p --all-databases --flush-privileges

--force在导出过程中忽略出现的SQL错误。
mysqldump -uroot -p --all-databases --force

--host, -h需要导出的主机信息
mysqldump -uroot -p --host=localhost --all-databases

--ignore-table不导出指定表。指定忽略多个表时,需要重复多次,每次一个表。每个表必须同时指定数据库和表名。例如:
--ignore-table=database.table1 --ignore-table=database.table2 ……
mysqldump -uroot -p --host=localhost --all-databases --ignore-table=mysql.user

--lock-all-tables, -x提交请求锁定所有数据库中的所有表,以保证数据的一致性。这是一个全局读锁,
并且自动关闭--single-transaction 和--lock-tables 选项。
mysqldump -uroot -p --host=localhost --all-databases --lock-all-tables

--lock-tables, -l开始导出前,锁定所有表。用READ LOCAL锁定表以允许MyISAM表并行插入。对于支持事务
的表例如InnoDB和BDB,--single-transaction是一个更好的选择,因为它根本不需要锁定表。请注意当导出多个数据库时,--lock-tables
分别为每个数据库锁定表。因此,该选项不能保证导出文件中的表在数据库之间的逻辑一致性。不同数据库表的导出状态可以完全不同。
mysqldump -uroot -p --host=localhost --all-databases --lock-tables

--no-create-db, -n只导出数据,而不添加CREATE DATABASE 语句。
mysqldump -uroot -p --host=localhost --all-databases --no-create-db

--no-create-info, -t只导出数据,而不添加CREATE TABLE 语句。
mysqldump -uroot -p --host=localhost --all-databases --no-create-info

--no-data, -d不导出任何数据,只导出数据库表结构。
mysqldump -uroot -p --host=localhost --all-databases --no-data

--password, -p连接数据库密码
--port, -P连接数据库端口号
--user, -u指定连接的用户名。

mysqldump常用实例:
mysqldump常用于数据库的备份与还原,在备份的过程中我们可以根据自己的实际情况添加以上任何参数,假设有数据库test_db,
执行以下命令,即可完成对整个数据库的备份:
mysqldump -u root -p test_db > test_db.sql

如要对数据进行还原,可执行如下命令:
mysql -u username -p test_db < test_db.sql

还原数据库操作还可以使用以下方法:
mysql> source test_db.sql

5:说说inner join与left join的区别
答:inner join 必须两边对应才能查处结果

left join 用主表关联副表,关联不出来依然显示结果

三,Thinkphp5
1:关联模型有哪些使用方法
答:一对多关联,例如一个用户有多个订单则需要在数据库的订单表中添加用户ID
//在订单model中使用 定义与用户表user的一对多关联
public function user()
{
return $this->belongsTo('user');
}
// 在用户model 中定义关联方法
public function advinfo()
{
return $this->hasMany('advinfo');//hasmany一对多关联,详细看开发手册
}

在订单方法中,直接通过foreach,动态的为每条数据新增用户姓名
foreach ($list as $value) {
$value -> user = $value -> user -> name;
}

2:数据进行增删查改操作有哪些方法
答: 2 // 1.thinkphp5添加记录
// 第一种方法
$result=Db::execute('insert into think_data (name,status) values ("thinkphp",1');
//第二种
Db::table('think_data')
->insert(['name'=>'thinkphp','status'=>1]);
// 第三种
Db::name('data')
->insert(['name'=>'thinkphp','status'=>1]);
// 第四种
$db=db('data');
$result=$db->insertGetId(['name'=>'thinkphp5']);
//返回id的方法
$data=['name'=>'thinkphp'];
$res=Db::name('data')->insertGetId($data);
//插入多条记录
$data1=[
['name'=>'1'],
['name'=>'2']
];
$res=$db->insertAll($data1);
// 2.thinkphp5更新记录
// 第一种方法
$result=Db::execute('update think_data set name="thinkphp" where id= 1');
// 第二种方法
Db::table('think_data')
->where('id',10)
->update(['name'=>'thinkphp']);
// 第三种方法
Db::name('data')
->where('id',10)
->update(['name'=>'thinkphp']);
//第四种方法db函数
$db=db('data');
$db->where('id',20)->update(['name'=>"thinkphp5.0"]);
// 3.查找记录
// 第一种方法
$res=Db::query('select * from think_data ');
// 第二种方法
$res=Db::table('think_data')
->where('id',10)
->select();
// 第三种方法
$res=Db::name('think_data')
->where('id',10)
->select();
//第四种方法
$db=db('data');
$res=$db->where('id',22)->select();
// 4.删除记录
// 第一种方法
$res=Db::execute('delete from think_data where id=3');
// 第二种方法
Db::table('think_data')
->where('id',20)
->delete();
// 第三种方法
Db::name('data')
->where('id',20)
->delete();
// 第四种方法
$db=db('data');
$db->where('id','<',10)
->delete();
//第五种方法
db('data')->delete(1);
db('data')->delete([1,2,3]);

3:闭包查询如何传入变量
答:普通闭包查询:
$items = ItemModel::all(function($query){$query->order('sort', 'asc');});

带参数的闭包查询:
$items = ItemModel::all(function($query)use($type){$query->where('type',$type)->order('sort', 'asc');});

通过代码我们可以发现,在ThinkPHP5闭包查询中传参使用的是use传递。

4:thinkphp5使用什么类进行数据验证
答:1:namespace app\validate;
/**
* 用户验证类User.php
*/
use think\Validate;
class User extends Validate
{
protected $rule = [
'name' => [
'require' => 'require',
'min' => 5,
'max' => 20,
],
'email' => [
'require' => 'require',
'email' => 'email',
],
'pass' => [
'require' => 'require',
'min' => 3,
'max' => 12,
'alphaNum'=> 'alphaNum',
],
'mobile' => [
'require' => 'require',
'mobile' => 'mobile',
'max' => 12,
],
];
}

----------

namespace app\index\controller;
use think\Controller;
use app\validate\User;
//Demo9.php
class Demo9 extends Controller
{

public function test()
{
# 要验证的数据
$data = [
'name' => 'Sam567',
'email' => 'sam@163.com',
'pass' => 'd123456ok',
'mobile' => '18521311599'
];
$validate = new User;
if(!$validate->check($data)){
return $validate->getError();
}
return '验证通过!';

}
}

5:如何进行分页参数的传递
答:paginate(15,false,[‘query’=>request()->param() ]);
说明:paginate有3个参数,第一个是一页显示的数量;第二个是简单模式或传入总计入数,默认为true,
简单模式为false;第三个就是分页传入的参数.
$name = input('get.searchKey/s');
if($name != ""){
$this->assign('searchKey', $name);
$map['name'] = ['like','%'.$name.'%'];
}
$map['delete'] = 0;
$list = Db::name('goods')->where($map)
->paginate(10,false,['query'=>request()->param()]);
$this->assign('list', $list)
->assign('empty', '<td colspan="9">暂无数据</td>');
return $this->fetch();

四;综合题
1:如何在网页之间传递变量
答:POST传值:
post传值是用于html的<form>表单跳转的方法,很方便使用。例如:
<html>
<form action='' method=''>
<input type='text' name='name1'>
<input type='hidden' name='name2' value='value'>
<input type='submit' value='提交'>
</form>
</html>

form中的action填入的是跳转页面的url路径,method填入post方法。form表单中的提交按钮按下后,
就会把form中有name的内容都传到填入的url中,可以通过$_POST['name']获取,例如:
$a=$_POST['name1'];
$b=$_POST['name2'];

这里有个很方便的小技巧,在input标签中把type选为'hidden'时,这个input标签会隐藏起来,不在页
面显示,但这input标签在 form中,并且有name值和value值,同样会跟随提交按钮传递过去,这种隐藏
标签可以传递一些不想显示出来的内容

GET传值:
GET传值是通过跟随url传递的,在页面跳转时,跟着url跳转。常用于<a>标签的使用。例如:
<a href='delete.php?id=value'>点我跳转</a>
跳转进入xxx.php后,就能通过$_GET['id']获取传递的值。GET方法常用于URL的目的是删除或读取某个id的php文件。

SESSION传值:
SESSION是全局变量的一种,经常用于用户登陆后保存用户id之类的常用数据。一旦保存到SESSION中,其他页面都可以
通过SESSION获取,SESSION的使用要开启session:
//session赋值
session_start();
$_SESSION['one']=value1;
$_SESSION['two']=value2;

//session值的读取:
$one = $_SESSION['one'];

//session值的销毁
unset($_SESSION['one']);

2:API接口中,针对数据传输安全性都有哪些做法
答:1、当用户登录APP时,使用https协议调用后台相关接口,服务器端根据用户名和密码时生成一个access_key,并将
access_key保存在session中,将生成的access_key和session_id返回给APP端。

2、APP端将接收到的access_key和session_id保存起来

3、当APP端调用接口传输数据时,将所传数据和access_key使用加密算法生成签名signature,并将signature和
session_id一起发送给服务器端。

4、服务器端接收到数据时,使用session_id从session中获取对应的access_key,将access_key和接收到的数
据使用同一加密算法生成对应signature,如果生成的签名和接收到的signature相同时,则表明数据合法



posted @ 2019-08-14 22:53  用代码砌墙的小白  阅读(324)  评论(0编辑  收藏  举报