Blogger Information
Blog 54
fans 6
comment 31
visits 107456
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP编程结课考试答卷
吾逍遥
Original
1210 people have browsed it

一、选择题

  • 设置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());
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post