15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 小白7天入门PHP Web开发 - Day 7(综合)个人博客实例讲解用户数据的存储

小白7天入门PHP Web开发 - Day 7(综合)个人博客实例讲解用户数据的存储

时间:2023-05-27 20:57:02 | 来源:网站运营

时间:2023-05-27 20:57:02 来源:网站运营

小白7天入门PHP Web开发 - Day 7(综合)个人博客实例讲解用户数据的存储:
《小白7天入门PHP Web开发》系列文章,面向单纯善良的完全不懂Web开发编程的入门速成课程,小白们如果感兴趣可以研读此系列文章,也可以连线提问。各路大神有何指教还请指点一二。希望各路大神手下留情,注意维护自己的身份和形象。拜谢各位。
上一篇文章 我们已经实现了博客文章功能的前端三个主要页面的设计和编码,并且了解了一些新的知识点,包括元素定位等。这篇文章将作为我们整个入门系列文章的终章,完全实现个人博客文章功能模块的实现。包括前后端交互、后端数据交互、php简单类封装等。开始之前,我们需要注意几点,第一,我们的前端页面上一节课的基本相同,有细微调整我们不再表,大家可以自行优化和补充,都不是很大的变动,我也尽力在文中提到。第二,我们所有的代码定位入门仅为说明相关功能和实现不做或少做安全校验。第三,文章中只提供核心代码,希望大家思考完善,有助于学习和提高。

一、分析一下我们要做哪些事情

万事开头难,思考第一步~!(PHP开头不难)

我们知道(我当你们都知道的,毕竟前面这么多课过来了),个人博客文章功能,主要就是涉及了文章的管理,文章要进行发布(增)、删除(删)、查找(查)、修改(改)等操作,才叫管理。那我们就得做到能在前端(页面)去操作文章,提供操作的入口,然后后端接受前端的数据进行相关业务逻辑的处理,处理完把数据存储到数据库中并进行管理,所以我们要做的就是这么几件事情。

第一件事情,前端提供入口,我们上一篇文章已经把页面基本实现了

第二件事情,前后端交互,这篇文章我们去实现,但其实我们早在 Day6上 就已经做过示例了,这节课我们不细讲

第三件事情,后端php和数据库mysql的交互和数据操作,基础的内容我们在 Day5 就已经有过讲解了。

那么,现在我们要?干!

二、万丈高楼平地起,代码生前要先简单“架构”管理一下

首先,我们的整个功能有几个东西,前端页面、后端php业务逻辑、数据库操作,所以我们需要先简单的做一个目录来“架构”管理这些代码。我们需要一个前端页面的目录,暂且叫 views ,届时我们把所有前端的页面移到这里面;然后后端php代码,我们需要一个叫 controllers 的目录来管理一下我们跟前端交互的代码,以及,我们需要php和数据交互的地方,代码放在一个叫 models 的目录里吧;最后我们需要跟数据库进行交互操作,就得连接数据库并单独对此进行管理方便各处都能方便用到,所以放在一个叫 common 的目录下。

以上就是我们简单的目录结构,你可以发现我们有四个东西,一个common,我们可以称作我们的公共类所在的地方,或者叫类库,你也可以取名叫lib,剩下的三个东西就是大家万年都提的 MVC 结构的简易雏形,也就是模型、视图、控制器。最简单的模型就是操作数据,处理数据的,控制器是处理业务逻辑和空值输入输出和前端交互的,视图就是我们的页面了。我们虽然这么进行代码的管理,但并不能称为严格意义上的MVC模式,因为我们采用了ajax前后端完全分离的做法,但是也不能称为非常严格意义上的前后端分离,我做的一切都是为了帮助你们理解这些东西并快速入门。更多相关的东西,大家可以去,嗯,那就百度一下吧。

图 2-1 目录结构图(仅供参考)

三、先拿到文章数据再说

我们先完成添加文章的功能。首先是一个表单页面,通过ajax交互,将表单提交到后端php进行存储。

页面如下,相比较上一篇文章,我们给每一个表单都新增了placeholder属性,用于提示用户输入的内容应该是什么

图 3-1 添加文章页面
我们直接新建一个js文件,用来写前后端交互以及用户交互的相关功能代码。叫 main.js 吧。

1、首先,我们需要一个ajax请求来提交数据到后端

我们把js代码封装成一个函数,方便调用和用户交互事件绑定,我们定义一个函数名叫 saveArticle

// 保存文章的函数// 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、后端接收数据

在controllers目录下新建一个addarticle.php 的文件,用户直接和前端交互,同时在models 下新建一个Article的类文件(还记得类吗?我们的 Day4 讲过的。)Article.php。之后我们的前端会提交数据到控制器,控制器会讲数据处理后转交给模型来处理,拿到结果后返回给前端使用。

当前端点击按钮,触发数据提交后,我们可以在控制器addarticle.php里面通过全局变量 $_POST 来获取所有的post方式提交上来的数据。

$post_data = $_POST;3、所有模型都应该自动连接数据库,数据库连接的基本类封装

为了方便数据库的连接和相关数据库的操作,我们新建一个数据库类,叫Db吧,新建Db.php,因为是公共的类,我们放到common目录下。这个类主要处理了数据库的pdo连接和数据库连接单例模式。要注意我们的文件路径和命名空间

<?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(),并传进去参数就可以连接数据库了,但是我们不想每一个模型(毕竟我们会有多个模型,比如这里的文章模型和评论模型)都要去连接一次,那怎么办呢?让他们都继承一个父类,在父类里面完成数据库的连接

我们在 models 目录下建一个父类文件 Base.php ,然后文章模型继承他就可以了。

<?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、在模型中实现数据的插入

在 models 下新建文章模型 Article.php,并且实现文章的保存,我们需要继承 基础模型类 Base,所以我们的代码如下

<?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。

INSERT INTO table_name (column1, column2) VALUES (value1, value2);

所以我们定义一个用来写入数据的方法,save

// 这里我们用类属性的方式来接收数据 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、第二步中的后端接收数据完善

接收数据我们用$_POST即可,这时我们要把数据交给模型处理,并获得处理结果,然后响应给前端。

<?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;}此时我们已经完成了整个文章的发布过程了。你清楚了吗?你可以试试你能正常运行吗?

接下来为了能够看到我们写入的文章是否成功了,除了看响应结果,那么我们需要写一个详情的功能来获取文章详情。

四、既已写入,是时候取出来了,获取文章详情

基本过程和上面的文章保存发布是一样的。

1、ajax提交请求说我要拿文章详情

拿文章详情就像在超市到储物柜拿自己的东西一样,需要知道柜子的号码,不然路都找不到~!所以我们要拿文章详情,也就需要知道文章id是多少,文章id在上一步中我们其实已经有返回了。所以我们的js很简单,如下。

// 获取文章详情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、模型查询文章详情

这里使用的是查询的sql语句,也是当然的我们之前的文章讲过的。

SELECT * FROM table_name WHERE column=val LIMIT 1

因为我们只取一篇文章也就是一条数据,所以可以使用 limit 1 来提高查询效率,模型方法同样写在模型Article.php文件中

/** * 获取文章详详情 * * @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()); } }就这样,我们就完成了获取文章详情的内容。文章写到这里,我们已经进行了文章的发布、文章的查询了,那如果需要编辑文章的话,怎么办呢?

我们想一下,我们要编辑文章,是不是得先拿到文章呢。没错,这就是查询的过程,跟上面的获取文章详情一毛一样。然后呢?保存到数据库,交互过程跟发布文章几乎一样,唯一的不同就是,sql语句不太一样。插入用 INSERT INTO,而更新用的是 UPDATE

UPDATE table_name SET column1=value1, column2=value2 WHERE column=value

那么我们更新文章和新增文章差不多,区别的sql语句,所以我们的模型方法 save 就改成了这样

/** * 保存文章,新增或编辑更新 * * @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值,跟获取文章详情一个样子的。请学会举一反三。

咳咳,说了这么多,其实也不多,都是大同小异的,这里有几个地方需要大家注意一下

关于PDO数据库连接和查询我一直没提,大家可以直接在官方文档查看一下具体用法。我们这里主要理解sql语句的使用。

五、我们现在还差什么?

文章发布有了、详情有了、编辑更新有了,从页面来看,我们是不是还差首页文章列表和文章评论了?对不起,我要留给你们作业来实现这一部分的功能了。给几个重要的方向提示。

1、多条数据查询,pdo使用的是 fetchAll,相对的单条数据的话,使用的是fetch

// 多条$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}";鉴于这个简单的功能,已经没有什么别的东西了。我把 代码 也统一放出来了。大家先看完上面再去看看代码对比一下吧。有什么问题可以留言或者私信我哦。

六、作业和任务

经过上面和前面文章的所有东西,我觉得你们已经完全有能力独立实现一个个人简单的博客了。恭喜你读到这里的时候,已经完成了PHP web开发的全部入门学习。这篇文章我们留了两个东西,一个文章列表、一个文章评论,希望你们能去搞一搞试一试。我提供的代码已经完成了文章评论列表和分页。希望你们能够学习临摹或者创新,完成文章列表首页的数据交互和处理。



关键词:讲解,实例,用户,数据,入门,综合

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭