时间:2023-05-27 20:57:02 | 来源:网站运营
时间:2023-05-27 20:57:02 来源:网站运营
小白7天入门PHP Web开发 - Day 7(综合)个人博客实例讲解用户数据的存储:《小白7天入门PHP Web开发》系列文章,面向单纯善良的完全不懂Web开发编程的入门速成课程,小白们如果感兴趣可以研读此系列文章,也可以连线提问。各路大神有何指教还请指点一二。希望各路大神手下留情,注意维护自己的身份和形象。拜谢各位。上一篇文章 我们已经实现了博客文章功能的前端三个主要页面的设计和编码,并且了解了一些新的知识点,包括元素定位等。这篇文章将作为我们整个入门系列文章的终章,完全实现个人博客文章功能模块的实现。包括前后端交互、后端数据交互、php简单类封装等。开始之前,我们需要注意几点,第一,我们的前端页面跟上一节课的基本相同,有细微调整,我们不再表,大家可以自行优化和补充,都不是很大的变动,我也尽力在文中提到。第二,我们所有的代码定位入门仅为说明相关功能和实现,不做或少做安全校验。第三,文章中只提供核心代码,希望大家思考完善,有助于学习和提高。
// 保存文章的函数// isSending用于标识用户是否正在提交数据,初步防止用户连续点击重复提交的问题var isSending = falsefunction saveArticle(){ // 如果为true,我们判定为用户已经正在提交数据,并且后端还没有返回响应,return false防止再次提交 if (isSending === true) { return false } // 用户开始提交数据,我们改变按钮的文字来提示用户文章在发布过程中 isSending = true $('.submit>button').text('发布中...') // 这个东西是jquery里面的,我们在前面的课中有讲过的哦 $.post( '../controllers/addarticle.php', $('form').serialize(), function(ret){ // notify是我们在页面上加的一个div用于提示信息的展示 $('.notify').text(ret.msg) $('.submit>button').text('立即发布') setTimeout(function(){ $('.notify').text('') window.location.href = 'detail.html?id=' + ret.data.article.id isSending = false }, 2000) }, 'json' )}
然后,我们需要绑定一个事件到提交按钮上来触发调用这个函数,才能最终将数据提交到后端。可以直接像下面这样绑定<button onclick="saveArticle()">立即发布</button>
2、后端接收数据$post_data = $_POST;
3、所有模型都应该自动连接数据库,数据库连接的基本类封装<?php/** * Description : * Db.php */namespace php/common;use PDO;/** * Class Db * 数据库管理类 * * @package php/common */class Db{ // 链接数据库必须的参数 protected $host = ''; # 数据库地址 protected $user = ''; # 用户名 protected $pass = ''; # 密码 protected $select_db = ''; # 数据库名 // 数据库连接实例 public static $pdo_con = null; /** * Db constructor. * 构造方法,类实例化首先会执行的方法,进来就执行的 * 我们定义成private私有,是为了实现单例模式,拒绝类外部的代码直接实例化本类 * @param $host 数据库地址 * @param $user 用户名 * @param $pass 密码 * @param $select_db 数据库名 */ private function __construct($host, $user, $pass, $select_db) { $host && $this->host = $host; $user && $this->user = $user; $pass && $this->pass = $pass; $select_db && $this->select_db = $select_db; } private function __clone() { return self::getInstance($this->host, $this->user, $this->pass, $this->select_db); } /** * 获取pdo连接db实例 * @param $host * @param $user * @param $pass * @param $select_db * * @return PDO * @throws /Exception * @author Shuixiang * @Last Modified content : * @Last Modified at 2019/12/2 1:05 */ public static function getInstance($host, $user, $pass, $select_db) { // 如果连接实例已经存在直接返回 if (static::$pdo_con) { return self::$pdo_con; } // 如果连接实例不存在,我们就去实例化一下 // 参数的基础校验 if ( !($host && $user && $pass && $select_db) ) { throw new /Exception('数据库链接参数有误'); } // 实例化,调用构造方法,设置相关参数 $db = new self($host, $user, $pass, $select_db); // 连接数据库 $db->_connect(); // 返回数据库连接 return self::$pdo_con; } /** * pdo连接mysql数据库并返回pdo实例,长连接 * * @return void * @throws /Exception * @author Shuixiang * @Last Modified content : * @Last Modified at 2019/12/2 1:06 */ protected function _connect() { try { self::$pdo_con = new PDO( "mysql:host={$this->host};dbname={$this->select_db}", $this->user, $this->pass, [PDO::ATTR_PERSISTENT => true] ); } catch (/Exception $e) { throw new /Exception($e->getMessage()); } }}
然后我们要所有模型去调用Db::getInstance(),并传进去参数就可以连接数据库了,但是我们不想每一个模型(毕竟我们会有多个模型,比如这里的文章模型和评论模型)都要去连接一次,那怎么办呢?让他们都继承一个父类,在父类里面完成数据库的连接。<?php/** * Description : * Base.php */namespace php/models;require_once dirname(__FILE__).'/../common/Db.php';use php/common/Db;/** * Class Base * 基类,主要处理了数据库连接 * * 请注意,我们本次实例所有内容讲解为主,并未考虑相关数据安全 * 比如包括但不仅限于xss注入、sql注入等 * 请勿用作正式用途 * 一般用户传递过来的数据,我们需要进行相对应的过滤后才放入数据库 * * @package php/controllers */class Base{ // 默认的数据库连接参数,我们在mysql命令行连接的时候也需要这些参数 protected $config = [ 'host' => '127.0.0.1', // 数据库地址,本地一般就是这个了 'user' => 'root', // 数据库用户名 'pass' => 'root', // 数据库密码 'dbname'=> 'blog' // 数据库名 ]; // 数据库连接实例 public $db = null; // 类的构造方法,每个类进来就会先执行这个方法 public function __construct() { try { $this->db = Db::getInstance($this->config['host'], $this->config['user'], $this->config['pass'], $this->config['dbname']); } catch (/Exception $e) { echo $e->getMessage(); die; } }}
4、在模型中实现数据的插入<?php/** * Description : * Article.php */namespace php/models;// 引入模型基础类require_once 'Base.php';// 使用类必须声明使用,并使用正确的命名空间use php/models/Base;/** * Class Article * 文章类,处理文章的相关操作 * * @package php/controllers */class Article extends Base{}
实现文章的保存到数据库,主要是我们在之前的文章也讲到过的,数据插入到数据库的sql。 // 这里我们用类属性的方式来接收数据 protected $title = ''; protected $abstract = ''; protected $content = ''; protected $author = ''; /** * 保存文章,新增或编辑更新 * * @param $post_data * * @return bool * @throws /Exception * @author Shuixiang * @Last Modified content : * @Last Modified at 2019/12/2 20:52 */ public function save($post_data) { // 获取参数,文章标题、摘要、内容、作者 isset($post_data['id']) && $this->article_id = intval($post_data['id']); isset($post_data['title']) && $this->title = $post_data['title']; isset($post_data['abstract']) && $this->abstract = $post_data['abstract']; isset($post_data['content']) && $this->content = $post_data['content']; isset($post_data['author']) && $this->author = $post_data['author']; // 判断是否为空,我们要求每一个参数都不能为空,这是基本校验 if ( !($this->title && $this->abstract && $this->content && $this->author) ) { throw new /Exception('表单数据不正确,请确认后重试'); } try { // 获取当前时间 $created_at = time(); // 开始写入数据,使用sql语句 $sql = " INSERT INTO articles (title, abstract, content, author, created_at) VALUES ('{$this->title}', '{$this->abstract}', '{$this->content}', '{$this->author}', {$created_at}) "; // 执行sql语句 if($this->db->exec($sql) === false) { throw new /Exception($this->db->errorInfo()[2]); } return $this->article_id ?: $this->db->lastInsertId(); } catch(/Exception $e) { throw new /Exception($e->getMessage()); } }
5、第二步中的后端接收数据完善<?php/** * Description : * addarticle.php */require_once '../models/Article.php';use php/models/Article;// 获取前端提交过来的post参数,并实例化一个文章对象,把数据传进去$article = new Article();try { $id = $article->save($_POST); echo json_encode([ 'status'=> 'success', 'msg' => '文章发布成功', 'data' => ['article' => ['id' => $id]] ]); die;} catch (/Exception $e) { echo json_encode([ 'status'=> 'fail', 'msg' => $e->getMessage() ]); die;}
此时我们已经完成了整个文章的发布过程了。你清楚了吗?你可以试试你能正常运行吗?// 获取文章详情function getDetail(id) { $.get( '../controllers/articledetail.php?id=' + id, function(ret) { if (ret.status == 'fail') { $('.load').text(ret.msg) } else if (ret.status == 'success') { var detail = ret.data.detail console.log(detail) } }, 'json' )}
2、后端控制器处理,并请求模型查询数据返回<?php/** * Description : * addarticle.php */require_once '../models/Article.php';use php/models/Article;// 获取前端提交过来的post参数,并实例化一个文章对象,把数据传进去$article = new Article();try { // 获取文章详情 $detail = $article->getDetail($_GET); echo json_encode([ 'status'=> 'success', 'msg' => '文章获取成功', 'data' => ['detail' => $detail] ]); die;} catch (/Exception $e) { echo json_encode([ 'status'=> 'fail', 'msg' => $e->getMessage() ]); die;}
3、模型查询文章详情 /** * 获取文章详详情 * * @param $get_data * * @return mixed * @throws /Exception */ public function getDetail($get_data) { isset($get_data['id']) && $this->article_id = intval($get_data['id']); // 判断是否为空,我们要求id参数都不能为空或0,这是基本校验 if (!$this->article_id) { throw new /Exception('参数错误,请确认后重试'); } try { // 开始获取数据 $sql = " SELECT id,title,abstract,content,author,created_at FROM articles WHERE id={$this->article_id} "; $data = $this->db->query($sql)->fetch(/PDO::FETCH_ASSOC); if (empty($data)) { throw new /Exception('文章不存在或已删除'); } $data['time'] = date('Y-m-d H:i', $data['created_at']); return $data; } catch(/Exception $e) { throw new /Exception($e->getMessage()); } }
就这样,我们就完成了获取文章详情的内容。文章写到这里,我们已经进行了文章的发布、文章的查询了,那如果需要编辑文章的话,怎么办呢? /** * 保存文章,新增或编辑更新 * * @param $post_data * * @return bool * @throws /Exception * @author Shuixiang * @Last Modified content : * @Last Modified at 2019/12/2 20:52 */ public function save($post_data) { // 获取参数,文章标题、摘要、内容、作者 isset($post_data['id']) && $this->article_id = intval($post_data['id']); isset($post_data['title']) && $this->title = $post_data['title']; isset($post_data['abstract']) && $this->abstract = $post_data['abstract']; isset($post_data['content']) && $this->content = $post_data['content']; isset($post_data['author']) && $this->author = $post_data['author']; // 判断是否为空,我们要求每一个参数都不能为空,这是基本校验 if ( !($this->title && $this->abstract && $this->content && $this->author) ) { throw new /Exception('表单数据不正确,请确认后重试'); } try { // 获取当前时间 $created_at = time(); // 开始写入数据,使用sql语句 if ($this->article_id) { $sql = " UPDATE articles SET title='{$this->title}', abstract='{$this->abstract}', content='{$this->content}', author='{$this->author}', updated_at={$created_at} WHERE id={$this->article_id} "; } else { $sql = " INSERT INTO articles (title, abstract, content, author, created_at) VALUES ('{$this->title}', '{$this->abstract}', '{$this->content}', '{$this->author}', {$created_at}) "; } // 执行sql语句 if($this->db->exec($sql) === false) { throw new /Exception($this->db->errorInfo()[2]); } return $this->article_id ?: $this->db->lastInsertId(); } catch(/Exception $e) { throw new /Exception($e->getMessage()); } }
当我们需要更新文章的时候需要给后端传一个id值,跟获取文章详情一个样子的。请学会举一反三。// 多条$this->db->query($sql)->fetchAll(/PDO::FETCH_ASSOC);// 单条$this->db->query($sql)->fetch(/PDO::FETCH_ASSOC);
2、数据过多时我们需要使用分页,分页的本质就是sql中的limit和offset,参数就是需要当前页码和每页的数量// 其中 offset表示数据库查询从第几条数据开始拿数据,limit表示从offset条开始拿limit跳数据// 假设,获取第一页的数据,每页是10条,此时// offset = page - 1 也就是 1-1=0开始// limit = pageSize = 10,每页十条// 最后sql中表示就是 LIMIT 0,10 表示从第0条开始,取十条数据。$sql = "SELECT article_id, content, username, created_at FROM comments WHERE article_id={$article_id} ORDER BY created_at DESC LIMIT {$offset}, {$limit}";
鉴于这个简单的功能,已经没有什么别的东西了。我把 代码 也统一放出来了。大家先看完上面再去看看代码对比一下吧。有什么问题可以留言或者私信我哦。关键词:讲解,实例,用户,数据,入门,综合