博客列表 >PHP编程结课考试答卷

PHP编程结课考试答卷

吾逍遥
吾逍遥原创
2020年12月18日 13:03:231198浏览

一、选择题

  • 设置cookie的方法以下哪种方式无效?( )

    • A: setcookie(key,value); B: $_COOKIE['username']="Chloe"; C: setrawcookie(); D:header('Set-cookie:a=4');
  • oop self 关键字的作用包括哪些?( ) 多选

    • A: self是类内部代替类名的关键字; B: self可以完成类成员方法与调用类的动态绑定 C: self可以用来在类内部完成静态成员的访问(包括类常量); D: self可以在类内部来实例化对象
  • PHP全局成员不包括以下哪项( )

    • A: 函数; B: 常量; C: 变量; D: 类
  • PHP类定义中不支持的访问控制是( )

    • A: public; B: protected; C:private ; D: friend
  • 以下不属于PHP标签的是: ( )

    • A: <?= ?>; B: < >; C:<? ?> ; D: <?php ?>

第一题:B,cookie设置目前只有setcookie、setrawcookie和header三种方法
第二题:ACD,static是完成调用类绑定
第三题:C,PHP全局成员有常量、函数、类(接口)
第四题:D,friend是C++的
第五题:B

二、判断题

  • 执行pdo对象中的exec()方法可以获取到PDOStatement对象。( )

  • sessionID是存在客户端cookie中的。( )

  • php.ini文件中开启了session,会与引入第三方代码中的session_start()冲突。( )

  • explode()函数可以完成数组转字符串的功能。( )

  • PHP重载是指通过魔术方法动态地创建类属性和方法。( )

第一题:错,返回影响记录的行数
第二题:对
第三题:对,sessioin_start()会产生新的 session_id。
第四题:错,它是字符串转数组,implode是数组转字符串
第五题:对,

三、填空题

  • MySQL服务器的默认连接端口是_;

  • 访问静态成员可以通过__完成;

  • PHP中跳出当前循环的语句是_, 跳过当前循环的语句是_;

  • 面向对象的主要特征有_ and _ and _;

  • 任何在composer.json文件中的修改都要执行__命令才能生效;

  • 服务容器被誉为自动产生类/对象的工厂,服务容器的三要素是_ , __ and _;

  • 我们可以通过__获取带有命名空间的类的完全限定名称;

  • MYSQL数据库查询操作中可以使用_字句指定查询结果的排序规则;

  • PHP命名空间中的use关键字有两种功能,分别是_and_;

  • psr-4规范是指将__进行绑定实现类的批量注册;

第一题:3306
第二题:self和static
第三题:break,continue
第四题:封装、继承和多态
第五题:composer dump-autoload
第六题:对象数组、绑定方法bind和获取方法make
第七题:类名::class
第八题:order by
第九题:引入命名空间的类和为命名空间的类取别名
第十是:命名空间和类所在的目录

四、问答题

第一题:你如何理解PHP的回调函数?并实例阐述php有哪些内置函数可以声明及调用回调函数(至少3个)?

答:PHP的回调函数也称为匿名函数或闭包Closure,主要应用场景有两个,一是内置函数提供了用户自定义处理机会,如array_map、array_reduce等数组函数,filter_var等过滤器函数,spl_autoload_register类拦截函数。另一个就是处理异步任务,说实在话,PHP本身对异步支持不友好,可通过swoole实现异步、并行的能力。回调函数使用外部变量可以使用普通函数两种形式:global关键字、$GLOBALS,PHP也提供了回调函数独有的形式:use。回调函数可以作为闭包Closure作为参数注入到函数中,可以给用户提供自定义处理的机会,另外call_user_func和call_user_func_array可调用普通函数或回调函数

第二题:页面间传值的方式有哪些?请举例?

答:页面间传值,目前我遇到主要有五种:
1、是url携带参数,如index.php?id=12&name=xiaoyao
2、是form表单提交数据,<form action="login.php" method="get">...</from>
3、ajax、fetch或axios与后端交互。

  1. `$.ajax({
  2. type: 'POST',
  3. url: url,
  4. data: data,
  5. dataType: dataType,
  6. success: function () {},
  7. error: function () {}
  8. });

4、cookie,setcookie('id',234);
5、session,$_SESSION['name']='xiaoyao

第三题:请使用pdo扩展完成数据库的CURD操作?

答:先完成PDO连接,然后进行query查询,exec增加、修改和删除操作。

  1. $dsn="mysql:host=localhost;dbname=test;charset=utf8";
  2. try{
  3. $pdo=new PDO($dsn,'root','root');
  4. // 原生查询
  5. $sql="select * from user";
  6. $res=$pdo->query($sql);
  7. if($res) print_r($res->fetchAll(PDO::FETCH_ASSOC));
  8. // 增加、更新和删除
  9. $sql="insert into user(uname,pwd) values('junren',md5('12321321'))";
  10. // $sql="update user set uname='haoren' where id=2";
  11. // $sql="delete from user where id=1";
  12. $res=$pdo->exec($sql);
  13. if(!empty($res)) echo "成功操作{$res}条数据";
  14. $pdo=null;
  15. } catch (Exception $e){
  16. die("数据库连接失败,原因是:".$e->getMessage());
  17. }

第四题:请实例辨析oop中$this,self::,static::,parent::等关键字?

答:四者都只能在类内使用,不同可分下面几种情况:

  • 访问谁? $this常访问非静态成员,self::和static::一般访问静态成员和常量,而parent::即可访问静态成员和常量,又可访问非静态方法,不可访问非静态属性。
  • 绑定谁? $this和static::绑定调用类,self::绑定声明类,parent::绑定父类。
  • 使用建议 $this常用于类内调用非静态成员,父类中常用static::替代self::,可解决单例继承问题,而parent::常用扩展父类功能,如提供防登录欺骗等检查功能

实例演示区别(其中self、static和parent区别是基于PHP官方代码进行扩展的):

  1. // $this
  2. class Animal{
  3. function test(){
  4. return $this;
  5. }
  6. function who(){
  7. echo __METHOD__.'<br>';
  8. }
  9. }
  10. class Bird extends Animal{
  11. }
  12. $obj=new Bird();
  13. var_dump($obj->test());//虽然test是Animal类成员方法,但是返回的是Bird类对象,即是调用类实例对象
  14. // 上面本以为返回Animal类对象呢,结果却是B类。这点要和静态成员继承区分开,非静态成员是真继承即内置了父类的成员,而静态则是虚继承,它是共享的,最终调用还是要到父类中成员
  15. // self、static和parent
  16. class A{
  17. static function foo(){
  18. echo static::who();
  19. }
  20. static function who(){
  21. echo __CLASS__.'<br>';
  22. }
  23. }
  24. class B extends A{
  25. static function test(){
  26. A::foo();
  27. // static是从调用类开始查找成员
  28. parent::foo();
  29. self::foo();
  30. // self是本类开始查找成员,而parent是从父类查找成员
  31. parent::who();
  32. self::who();
  33. }
  34. static function who(){
  35. echo __CLASS__.'<br>';
  36. }
  37. }
  38. class C extends B{
  39. // static function who(){
  40. // echo __CLASS__.'<br>';
  41. // }
  42. }
  43. C::test(); //输出是A B B A B

第五题:实例阐述类加载的三种方式(含composer自动加载器)

答:
第一种是传统类加载方式,就是使用require或include引入类文件,如include_once './demo.php',其中路径可是绝对路径,也可是相对路径,一般建议是相对路径,还有就是正反斜杠,由于是文件路径,在windows平台是正反斜杠都可以,若是Linux或MaxOS则要使用正斜杠。

  1. // 第一种类加载方式:require或include传递加载类文件
  2. include_once '.\demo.php';
  3. C::test();

第二种是spl_autoload_register类拦截加载

  1. // 第二种类拦截加载:spl_autoload_register
  2. // 要求类名和文件名要相同,比较适合psr-4规范
  3. spl_autoload_register(function ($classname) {
  4. $path = __DIR__ . DIRECTORY_SEPARATOR . $classname . '.php';
  5. echo $path;
  6. if (is_file($path)) include_once $path;
  7. });
  8. C::test();

第三种是composer自动加载器加载类,在使用前引入vendor/autoload.php,然后在composer.json增加autoload字段,可以采用三种方式:files加载类文件、classmap加载类文件目录,psr-4加载命名空间对应的类目录,不过最后一种建议是应用于命名空间的类,若是全局空间的类由于不符合psr-4规范,所以加载不了。修改composer.json后要调用composer dump-autoload使其生效。

  1. include_once './vendor/autoload.php';
  2. C::test();
  1. //files加载类文件
  2. "autoload": {
  3. "files": [
  4. "c.php"
  5. ]
  6. },
  1. //classmap加载类目录
  2. "autoload": {
  3. "classmap": [
  4. ".\\"
  5. ]
  6. },
  1. // psr-4加载只适合符合其规范的,下面是全局空间,加载是失败的
  2. "autoload": {
  3. "psr-4":{
  4. "\\":"./"
  5. }
  6. },

五、实战

第一题:请只用PHP完成简单的计算器功能?

  1. /**
  2. * 总体思路
  3. * 1、form表单提交两个数和操作符
  4. * 2、通过Get获取用户输入数据,进行判断是否合法,如除法时除数不能为0
  5. * 3、合法则计算结果并返回给用户
  6. */
  7. extract($_POST);
  8. // var_dump(get_defined_vars());
  9. $res = '';
  10. // 用户提供进行计算
  11. if ($btn === 'btn') {
  12. if ($opt === '4' || $opt === '5') {
  13. if (empty($num2)) $res = '除法或求余时,第二个数不能为0或空';
  14. }
  15. switch ($opt):
  16. case '1':
  17. $res=''.(intval($num1)+intval($num2));
  18. break;
  19. case '2':
  20. $res=''.(intval($num1)-intval($num2));
  21. break;
  22. case '3':
  23. $res=''.(intval($num1)*intval($num2));
  24. break;
  25. case '4':
  26. if (empty($num2)) break;
  27. $res=''.(intval($num1)/intval($num2));
  28. break;
  29. case '5':
  30. if (empty($num2)) break;
  31. $res=''.(intval($num1)%intval($num2));
  32. break;
  33. default:
  34. $res = '运算符不合法,无法计算';
  35. endswitch;
  36. }
  37. ?>
  38. <!DOCTYPE html>
  39. <html lang="zh">
  40. <head>
  41. <meta charset="UTF-8">
  42. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  43. <title>PHP实现简单计算器</title>
  44. </head>
  45. <body>
  46. <form action="calculator.php" method="POST">
  47. <label for="num1">第一个数:</label>
  48. <input type="number" name="num1" id="num1" value="<?php echo $num1; ?>" step="1">
  49. <select name="opt">
  50. <option value="1" <?php if ($opt == '1') echo 'selected'; ?>>+</option>
  51. <option value="2" <?php if ($opt == '2') echo 'selected'; ?>>-</option>
  52. <option value="3" <?php if ($opt == '3') echo 'selected'; ?>>*</option>
  53. <option value="4" <?php if ($opt == '4') echo 'selected'; ?>>/</option>
  54. <option value="5" <?php if ($opt == '5') echo 'selected'; ?>>%</option>
  55. </select>
  56. <label for="num2">第二个数:</label>
  57. <input type="number" name="num2" id="num2" value="<?php echo $num2; ?>" step="1">
  58. <button name="btn" value="btn">计算</button>
  59. </form>
  60. <div class="msg">
  61. <p>计算结果:<span><?php echo $res; ?></span></p>
  62. </div>
  63. </body>
  64. </html>

答:客户端cookie记录用户sessionID,并设置令牌和有效期,服务器端session同时保存了令牌和有效期,通过客户端令牌可以查询是否合法用户,从而完成自动登录

  1. //index.php
  2. <?php
  3. session_start();
  4. // 1、检测cookie中是否存在token
  5. if (!isset($_COOKIE['token'])) {
  6. exit("
  7. <script>
  8. alert('请您先登录');
  9. location.href='login.php';
  10. </script>
  11. ");
  12. }
  13. // 2、检测token是否过期
  14. $tokentime = intval(substr($_COOKIE['token'], -10));
  15. if (time() - $tokentime > 60 * 60 * 24 * 7) {
  16. exit("
  17. <script>
  18. alert('登录已过期,请重新登录');
  19. location.href='login.php';
  20. </script>
  21. ");
  22. }
  23. // 3、检测token是否非法
  24. $servertoken = $_SESSION['token'];
  25. if ($servertoken != $_COOKIE['token']) {
  26. exit("
  27. <script>
  28. alert('非法令牌,请重新登录');
  29. location.href='login.php';
  30. </script>
  31. ");
  32. }
  33. // 4、在session读取用户名id和密码
  34. $id = $_SESSION['id'];
  35. $pwd = $_SESSION['pwd'];
  36. // 5、从数据库中读取用户信息
  37. $salt = 'woxiaoyao';
  38. $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
  39. $stmt = $pdo->prepare('SELECT uname,pwd,id FROM user where id = ? and pwd = ?;');
  40. $stmt->execute(array($id, $pwd));
  41. $res = $stmt->fetch(PDO::FETCH_ASSOC);
  42. if ($stmt->rowCount() < 1) {
  43. exit("
  44. <script>
  45. alert('用户不存在,请重新登录或注册');
  46. location.href='login.php';
  47. </script>
  48. ");
  49. }
  50. ?>
  51. <!DOCTYPE html>
  52. <html lang="en">
  53. <head>
  54. <meta charset="UTF-8" />
  55. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  56. <title>首页</title>
  57. <style>
  58. nav {
  59. height: 40px;
  60. background-color: deepskyblue;
  61. padding: 0 20px;
  62. display: flex;
  63. justify-content: space-between;
  64. align-items: center;
  65. }
  66. nav>a {
  67. color: white;
  68. text-decoration: none;
  69. }
  70. </style>
  71. </head>
  72. <body>
  73. <nav>
  74. <a href="index.php">简书后台管理</a>
  75. <a href="" id="logout">
  76. <span style="color: yellow;"> 欢迎您<?php echo $res['uname']; ?></span> |
  77. 退出</a>
  78. </nav>
  79. <script>
  80. document
  81. .querySelector("#logout")
  82. .addEventListener("click", function(ev) {
  83. // 禁用链接跳转行为
  84. ev.preventDefault();
  85. // 询问用户是否退出,并执行对应操作
  86. if (confirm("是否退出?"))
  87. window.location.assign("login.php?action=logout");
  88. });
  89. </script>
  90. </body>
  91. </html>
  1. //login.php
  2. <?php
  3. if (isset($_GET['action']) && $_GET['action'] == 'logout') {
  4. setcookie('token');
  5. session_unset();
  6. session_destroy();
  7. }
  8. ?>
  9. <!DOCTYPE html>
  10. <html lang="zh">
  11. <head>
  12. <meta charset="UTF-8">
  13. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  14. <title>用户登录</title>
  15. <style>
  16. .container {
  17. width: 30em;
  18. margin: 2em auto;
  19. border-radius: 1em;
  20. background-color: #007d20;
  21. color: white;
  22. padding: 0.2em 0.5em 1em;
  23. text-align: center;
  24. }
  25. form {
  26. display: grid;
  27. grid-template-columns: 5em 1fr;
  28. grid-template-rows: repeat(4, 2em);
  29. place-items: center initial;
  30. gap: 0.5em;
  31. }
  32. form>button {
  33. grid-column: 2/3;
  34. }
  35. form>input[type="checkbox"] {
  36. width: 2em;
  37. height: 2em;
  38. }
  39. </style>
  40. </head>
  41. <body>
  42. <div class="container">
  43. <h3>用户登录</h3>
  44. <form action="check.php" method="post">
  45. <label for="email">用户名:</label>
  46. <input type="text" name="username" id="email" placeholder="输入用户名" required autofocus>
  47. <label for="password">密码:</label>
  48. <input type="password" name="password" id="password" placeholder="密码不少于6位" required>
  49. <label for="autoLogin">自动登录</label>
  50. <input type="checkbox" name="autoLogin" id="autoLogin">
  51. <button>提交</button>
  52. </form>
  53. </div>
  54. </body>
  55. </html>
  1. //check.php
  2. <?php
  3. session_start();
  4. extract($_POST);
  5. // 1、检查是否有用户信息
  6. if (empty($username) || empty($password)) {
  7. exit("
  8. <script>
  9. alert('非法登录');
  10. location.href='login.php';
  11. </script>
  12. ");
  13. }
  14. $password = md5($password);
  15. $salt = 'woxiaoyao';
  16. // 2、查询数据库,看用户名和密码是否正确
  17. $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'root');
  18. $stmt = $pdo->prepare('SELECT uname,pwd,id FROM user where uname = ? and pwd = ?;');
  19. $stmt->execute(array($username, $password));
  20. $res = $stmt->fetch(PDO::FETCH_ASSOC);
  21. if ($stmt->rowCount() == 1) {
  22. // 3、若勾选了自动登录则记录用户信息
  23. if ($autoLogin == 'on') {
  24. $token = md5($res['id'] . $res['pwd'] . $salt) . time();
  25. setcookie('token', $token, time() + 60 * 60 * 24 * 7);
  26. $_SESSION['token'] = $token;
  27. $_SESSION['id'] = $res['id'];
  28. $_SESSION['pwd'] = $res['pwd'];
  29. } else {
  30. // 4、否则清除cookie和session
  31. setcookie('token');
  32. session_unset();
  33. session_destroy();
  34. }
  35. exit("
  36. <script>
  37. location.href='index.php';
  38. </script>
  39. ");
  40. } else {
  41. exit("
  42. <script>
  43. alert('用户名和密码不正确');
  44. location.href='login.php';
  45. </script>
  46. ");
  47. }

第三题 请在前后端分离的情况下完成用户信息展示的省略分页功能

答:按老师演示MVC自己搭建了框架,模型继承了Medoo,视图继承了Plates,并通过Composer自动加载类,支持嵌套加载,下面截图是目录结构,参考了TP框架的做法

1

  1. // 核心模型类
  2. <?php
  3. namespace core;
  4. use Medoo\Medoo;
  5. class Model extends Medoo
  6. {
  7. function __construct()
  8. {
  9. $config = [
  10. 'database_type' => 'mysql',
  11. 'database_name' => 'test',
  12. 'server' => 'localhost',
  13. 'username' => 'root',
  14. 'password' => 'root'
  15. ];
  16. parent::__construct($config);
  17. }
  18. }
  19. // 核心视图类
  20. <?php
  21. namespace core;
  22. use League\Plates\Engine;
  23. class View extends Engine{
  24. function __construct($path=null,$fileExtension = 'php')
  25. {
  26. parent::__construct($path,$fileExtension);
  27. }
  28. }
  1. // 用户控制器类
  2. <?php
  3. namespace app\controller;
  4. use PDO;
  5. class User
  6. {
  7. private $model;
  8. private $view;
  9. function __construct($model, $view)
  10. {
  11. $this->model = $model;
  12. $this->view = $view;
  13. }
  14. function index()
  15. {
  16. //分页获取数据
  17. $num = 10;
  18. $sql="select count(id) as total from user";
  19. $res=$this->model->pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
  20. $total = intval($res[0]['total']);
  21. $pages = ceil($total / $num);
  22. $page = $_GET['p'] ?? 1;
  23. $offset = ($page - 1) * $num;
  24. $sql="select * from user where true limit {$offset},{$num}";
  25. $users = $this->model->pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
  26. // 改进的导航栏
  27. $startPage = 1;
  28. // 显示页码数最好为奇数
  29. $showPage = 5;
  30. if (($page - ceil(($showPage - 1) / 2)) > $startPage)
  31. $startPage = $page - ceil(($showPage - 1) / 2);
  32. return $this->view->render('user/list',["users"=>$users,"pages"=>$pages,"startPage"=>$startPage,"showPage"=>$showPage]);
  33. }
  34. }
  35. // 用户模型类
  36. <?php
  37. namespace app\model;
  38. use core\Model;
  39. class User extends Model
  40. {
  41. }
  1. // 分页模板
  2. <style>
  3. * {
  4. margin: 0;
  5. padding: 0;
  6. box-sizing: border-box;
  7. }
  8. a {
  9. text-decoration: none;
  10. display: inline-block;
  11. /* width: 2em; */
  12. height: 2em;
  13. line-height: 2em;
  14. }
  15. .container {
  16. width: 60vw;
  17. margin: 1em auto;
  18. }
  19. td {
  20. text-align: center;
  21. }
  22. .page {
  23. margin-top: 1em;
  24. text-align: center;
  25. }
  26. td a:first-child {
  27. margin-right: 5px;
  28. }
  29. td a:last-child {
  30. margin-left: 5px;
  31. }
  32. .page a {
  33. padding: 0 0.5em;
  34. margin: 0 5px;
  35. }
  36. .page a.cur {
  37. background-color: #007d20;
  38. color: white;
  39. }
  40. </style>
  41. <div class="container">
  42. <table border='1' cellspacing="0" width="100%">
  43. <caption>用户信息表</caption>
  44. <thead>
  45. <tr bgColor="lightgray">
  46. <th>ID</th>
  47. <th>name</th>
  48. <th>password</th>
  49. <th>操作</th>
  50. </tr>
  51. </thead>
  52. <tbody>
  53. <?php
  54. foreach ($users as $user) {
  55. $trdata = "<tr>";
  56. foreach ($user as $item) {
  57. $trdata .= "<td>{$item}</td>";
  58. }
  59. $trdata .= "<td><a href='#'>编辑</a><a href='#'>删除</a></td>";
  60. $trdata .= "</tr>";
  61. echo $trdata;
  62. }
  63. ?>
  64. </tbody>
  65. </table>
  66. <div class="page">
  67. <?php
  68. echo "<a href='{$_SERVER["PHP_SELF"]}?p=1'>首页</a>";
  69. $prev = ($page - 1 > 1) ? ($page - 1) : 1;
  70. if ($startPage > 1)
  71. echo "<a href='{$_SERVER["PHP_SELF"]}?p={$prev}'>...</a>";
  72. // 加入pages验证,可避免记录数少时出现的错误
  73. for ($i = $startPage; $i < $startPage + $showPage, $i < $pages; $i++) :
  74. if ($i == $page)
  75. echo "<a class='cur' href='{$_SERVER["PHP_SELF"]}?p={$i}'>{$i}</a>";
  76. else
  77. echo "<a href='{$_SERVER["PHP_SELF"]}?p={$i}'>{$i}</a>";
  78. endfor;
  79. $next = ($page + 1) < $pages ? ($page + 1) : $pages;
  80. if ($startPage + $showPage <= $pages + 1)
  81. echo "<a href='{$_SERVER["PHP_SELF"]}?p={$next}'>...</a>";
  82. echo "<a href='{$_SERVER["PHP_SELF"]}?p={$pages}'>未页</a>";
  83. ?>
  84. </div>
  85. </div>
  1. // 首页index.php在public目录下
  2. <?php
  3. require_once '../vendor/autoload.php';
  4. use core\Model;
  5. use core\View;
  6. use app\controller\User;
  7. $obj=new User(new Model(),new View('..\app\view'));
  8. echo ($obj->index());
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议