時(shí)間:2023-05-27 20:57:02 | 來(lái)源:網(wǎng)站運(yùn)營(yíng)
時(shí)間:2023-05-27 20:57:02 來(lái)源:網(wǎng)站運(yùn)營(yíng)
小白7天入門(mén)PHP Web開(kāi)發(fā) - Day 7(綜合)個(gè)人博客實(shí)例講解用戶數(shù)據(jù)的存儲(chǔ):《小白7天入門(mén)PHP Web開(kāi)發(fā)》系列文章,面向單純善良的完全不懂Web開(kāi)發(fā)編程的入門(mén)速成課程,小白們?nèi)绻信d趣可以研讀此系列文章,也可以連線提問(wèn)。各路大神有何指教還請(qǐng)指點(diǎn)一二。希望各路大神手下留情,注意維護(hù)自己的身份和形象。拜謝各位。上一篇文章 我們已經(jīng)實(shí)現(xiàn)了博客文章功能的前端三個(gè)主要頁(yè)面的設(shè)計(jì)和編碼,并且了解了一些新的知識(shí)點(diǎn),包括元素定位等。這篇文章將作為我們整個(gè)入門(mén)系列文章的終章,完全實(shí)現(xiàn)個(gè)人博客文章功能模塊的實(shí)現(xiàn)。包括前后端交互、后端數(shù)據(jù)交互、php簡(jiǎn)單類封裝等。開(kāi)始之前,我們需要注意幾點(diǎn),第一,我們的前端頁(yè)面跟上一節(jié)課的基本相同,有細(xì)微調(diào)整,我們不再表,大家可以自行優(yōu)化和補(bǔ)充,都不是很大的變動(dòng),我也盡力在文中提到。第二,我們所有的代碼定位入門(mén)僅為說(shuō)明相關(guān)功能和實(shí)現(xiàn),不做或少做安全校驗(yàn)。第三,文章中只提供核心代碼,希望大家思考完善,有助于學(xué)習(xí)和提高。
// 保存文章的函數(shù)// isSending用于標(biāo)識(shí)用戶是否正在提交數(shù)據(jù),初步防止用戶連續(xù)點(diǎn)擊重復(fù)提交的問(wèn)題var isSending = falsefunction saveArticle(){ // 如果為true,我們判定為用戶已經(jīng)正在提交數(shù)據(jù),并且后端還沒(méi)有返回響應(yīng),return false防止再次提交 if (isSending === true) { return false } // 用戶開(kāi)始提交數(shù)據(jù),我們改變按鈕的文字來(lái)提示用戶文章在發(fā)布過(guò)程中 isSending = true $('.submit>button').text('發(fā)布中...') // 這個(gè)東西是jquery里面的,我們?cè)谇懊娴恼n中有講過(guò)的哦 $.post( '../controllers/addarticle.php', $('form').serialize(), function(ret){ // notify是我們?cè)陧?yè)面上加的一個(gè)div用于提示信息的展示 $('.notify').text(ret.msg) $('.submit>button').text('立即發(fā)布') setTimeout(function(){ $('.notify').text('') window.location.href = 'detail.html?id=' + ret.data.article.id isSending = false }, 2000) }, 'json' )}
然后,我們需要綁定一個(gè)事件到提交按鈕上來(lái)觸發(fā)調(diào)用這個(gè)函數(shù),才能最終將數(shù)據(jù)提交到后端。可以直接像下面這樣綁定<button onclick="saveArticle()">立即發(fā)布</button>
2、后端接收數(shù)據(jù)$post_data = $_POST;
3、所有模型都應(yīng)該自動(dòng)連接數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)連接的基本類封裝<?php/** * Description : * Db.php */namespace php/common;use PDO;/** * Class Db * 數(shù)據(jù)庫(kù)管理類 * * @package php/common */class Db{ // 鏈接數(shù)據(jù)庫(kù)必須的參數(shù) protected $host = ''; # 數(shù)據(jù)庫(kù)地址 protected $user = ''; # 用戶名 protected $pass = ''; # 密碼 protected $select_db = ''; # 數(shù)據(jù)庫(kù)名 // 數(shù)據(jù)庫(kù)連接實(shí)例 public static $pdo_con = null; /** * Db constructor. * 構(gòu)造方法,類實(shí)例化首先會(huì)執(zhí)行的方法,進(jìn)來(lái)就執(zhí)行的 * 我們定義成private私有,是為了實(shí)現(xiàn)單例模式,拒絕類外部的代碼直接實(shí)例化本類 * @param $host 數(shù)據(jù)庫(kù)地址 * @param $user 用戶名 * @param $pass 密碼 * @param $select_db 數(shù)據(jù)庫(kù)名 */ 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實(shí)例 * @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) { // 如果連接實(shí)例已經(jīng)存在直接返回 if (static::$pdo_con) { return self::$pdo_con; } // 如果連接實(shí)例不存在,我們就去實(shí)例化一下 // 參數(shù)的基礎(chǔ)校驗(yàn) if ( !($host && $user && $pass && $select_db) ) { throw new /Exception('數(shù)據(jù)庫(kù)鏈接參數(shù)有誤'); } // 實(shí)例化,調(diào)用構(gòu)造方法,設(shè)置相關(guān)參數(shù) $db = new self($host, $user, $pass, $select_db); // 連接數(shù)據(jù)庫(kù) $db->_connect(); // 返回?cái)?shù)據(jù)庫(kù)連接 return self::$pdo_con; } /** * pdo連接mysql數(shù)據(jù)庫(kù)并返回pdo實(shí)例,長(zhǎng)連接 * * @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()); } }}
然后我們要所有模型去調(diào)用Db::getInstance(),并傳進(jìn)去參數(shù)就可以連接數(shù)據(jù)庫(kù)了,但是我們不想每一個(gè)模型(畢竟我們會(huì)有多個(gè)模型,比如這里的文章模型和評(píng)論模型)都要去連接一次,那怎么辦呢?讓他們都繼承一個(gè)父類,在父類里面完成數(shù)據(jù)庫(kù)的連接。<?php/** * Description : * Base.php */namespace php/models;require_once dirname(__FILE__).'/../common/Db.php';use php/common/Db;/** * Class Base * 基類,主要處理了數(shù)據(jù)庫(kù)連接 * * 請(qǐng)注意,我們本次實(shí)例所有內(nèi)容講解為主,并未考慮相關(guān)數(shù)據(jù)安全 * 比如包括但不僅限于xss注入、sql注入等 * 請(qǐng)勿用作正式用途 * 一般用戶傳遞過(guò)來(lái)的數(shù)據(jù),我們需要進(jìn)行相對(duì)應(yīng)的過(guò)濾后才放入數(shù)據(jù)庫(kù) * * @package php/controllers */class Base{ // 默認(rèn)的數(shù)據(jù)庫(kù)連接參數(shù),我們?cè)趍ysql命令行連接的時(shí)候也需要這些參數(shù) protected $config = [ 'host' => '127.0.0.1', // 數(shù)據(jù)庫(kù)地址,本地一般就是這個(gè)了 'user' => 'root', // 數(shù)據(jù)庫(kù)用戶名 'pass' => 'root', // 數(shù)據(jù)庫(kù)密碼 'dbname'=> 'blog' // 數(shù)據(jù)庫(kù)名 ]; // 數(shù)據(jù)庫(kù)連接實(shí)例 public $db = null; // 類的構(gòu)造方法,每個(gè)類進(jìn)來(lái)就會(huì)先執(zhí)行這個(gè)方法 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、在模型中實(shí)現(xiàn)數(shù)據(jù)的插入<?php/** * Description : * Article.php */namespace php/models;// 引入模型基礎(chǔ)類require_once 'Base.php';// 使用類必須聲明使用,并使用正確的命名空間use php/models/Base;/** * Class Article * 文章類,處理文章的相關(guān)操作 * * @package php/controllers */class Article extends Base{}
實(shí)現(xiàn)文章的保存到數(shù)據(jù)庫(kù),主要是我們?cè)谥暗奈恼乱仓v到過(guò)的,數(shù)據(jù)插入到數(shù)據(jù)庫(kù)的sql。 // 這里我們用類屬性的方式來(lái)接收數(shù)據(jù) 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) { // 獲取參數(shù),文章標(biāo)題、摘要、內(nèi)容、作者 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']; // 判斷是否為空,我們要求每一個(gè)參數(shù)都不能為空,這是基本校驗(yàn) if ( !($this->title && $this->abstract && $this->content && $this->author) ) { throw new /Exception('表單數(shù)據(jù)不正確,請(qǐng)確認(rèn)后重試'); } try { // 獲取當(dāng)前時(shí)間 $created_at = time(); // 開(kāi)始寫(xiě)入數(shù)據(jù),使用sql語(yǔ)句 $sql = " INSERT INTO articles (title, abstract, content, author, created_at) VALUES ('{$this->title}', '{$this->abstract}', '{$this->content}', '{$this->author}', {$created_at}) "; // 執(zhí)行sql語(yǔ)句 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、第二步中的后端接收數(shù)據(jù)完善<?php/** * Description : * addarticle.php */require_once '../models/Article.php';use php/models/Article;// 獲取前端提交過(guò)來(lái)的post參數(shù),并實(shí)例化一個(gè)文章對(duì)象,把數(shù)據(jù)傳進(jìn)去$article = new Article();try { $id = $article->save($_POST); echo json_encode([ 'status'=> 'success', 'msg' => '文章發(fā)布成功', 'data' => ['article' => ['id' => $id]] ]); die;} catch (/Exception $e) { echo json_encode([ 'status'=> 'fail', 'msg' => $e->getMessage() ]); die;}
此時(shí)我們已經(jīng)完成了整個(gè)文章的發(fā)布過(guò)程了。你清楚了嗎?你可以試試你能正常運(yùn)行嗎?// 獲取文章詳情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、后端控制器處理,并請(qǐng)求模型查詢數(shù)據(jù)返回<?php/** * Description : * addarticle.php */require_once '../models/Article.php';use php/models/Article;// 獲取前端提交過(guò)來(lái)的post參數(shù),并實(shí)例化一個(gè)文章對(duì)象,把數(shù)據(jù)傳進(jìn)去$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參數(shù)都不能為空或0,這是基本校驗(yàn) if (!$this->article_id) { throw new /Exception('參數(shù)錯(cuò)誤,請(qǐng)確認(rèn)后重試'); } try { // 開(kāi)始獲取數(shù)據(jù) $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()); } }
就這樣,我們就完成了獲取文章詳情的內(nèi)容。文章寫(xiě)到這里,我們已經(jīng)進(jìn)行了文章的發(fā)布、文章的查詢了,那如果需要編輯文章的話,怎么辦呢? /** * 保存文章,新增或編輯更新 * * @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) { // 獲取參數(shù),文章標(biāo)題、摘要、內(nèi)容、作者 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']; // 判斷是否為空,我們要求每一個(gè)參數(shù)都不能為空,這是基本校驗(yàn) if ( !($this->title && $this->abstract && $this->content && $this->author) ) { throw new /Exception('表單數(shù)據(jù)不正確,請(qǐng)確認(rèn)后重試'); } try { // 獲取當(dāng)前時(shí)間 $created_at = time(); // 開(kāi)始寫(xiě)入數(shù)據(jù),使用sql語(yǔ)句 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}) "; } // 執(zhí)行sql語(yǔ)句 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()); } }
當(dāng)我們需要更新文章的時(shí)候需要給后端傳一個(gè)id值,跟獲取文章詳情一個(gè)樣子的。請(qǐng)學(xué)會(huì)舉一反三。// 多條$this->db->query($sql)->fetchAll(/PDO::FETCH_ASSOC);// 單條$this->db->query($sql)->fetch(/PDO::FETCH_ASSOC);
2、數(shù)據(jù)過(guò)多時(shí)我們需要使用分頁(yè),分頁(yè)的本質(zhì)就是sql中的limit和offset,參數(shù)就是需要當(dāng)前頁(yè)碼和每頁(yè)的數(shù)量// 其中 offset表示數(shù)據(jù)庫(kù)查詢從第幾條數(shù)據(jù)開(kāi)始拿數(shù)據(jù),limit表示從offset條開(kāi)始拿limit跳數(shù)據(jù)// 假設(shè),獲取第一頁(yè)的數(shù)據(jù),每頁(yè)是10條,此時(shí)// offset = page - 1 也就是 1-1=0開(kāi)始// limit = pageSize = 10,每頁(yè)十條// 最后sql中表示就是 LIMIT 0,10 表示從第0條開(kāi)始,取十條數(shù)據(jù)。$sql = "SELECT article_id, content, username, created_at FROM comments WHERE article_id={$article_id} ORDER BY created_at DESC LIMIT {$offset}, {$limit}";
鑒于這個(gè)簡(jiǎn)單的功能,已經(jīng)沒(méi)有什么別的東西了。我把 代碼 也統(tǒng)一放出來(lái)了。大家先看完上面再去看看代碼對(duì)比一下吧。有什么問(wèn)題可以留言或者私信我哦。關(guān)鍵詞:講解,實(shí)例,用戶,數(shù)據(jù),入門(mén),綜合
客戶&案例
營(yíng)銷資訊
關(guān)于我們
客戶&案例
營(yíng)銷資訊
關(guān)于我們
微信公眾號(hào)
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。