JavaScript >> Javascript 文檔 >  >> Tags >> CSS

簡單的 AJAX 評論系統

這一次,我們正在製作一個簡單的 AJAX 評論系統。它將以 gravatar 集成為特色,並演示如何在 JSON 的幫助下實現 jQuery 和 PHP/MySQL 之間的有效通信。

第 1 步 - XHTML

首先,讓我們看一下評論的標記。這段代碼是 PHP 在 Comment 類中生成的,稍後我們會看一下。

demo.php

<div class="comment">
    <div class="avatar">
        <a href="https://tutorialzine.com/">
        <img src="http://www.gravatar.com/avatar/112fdf7a8fe3609e7af2cd3873b5c6bd?size=50&default=http%3A%2F%2Fdemo.tutorialzine.com%2F2010%2F06%2Fsimple-ajax-commenting-system%2Fimg%2Fdefault_avatar.gif">
        </a>
    </div>

    <div class="name"><a href="https://tutorialzine.com/">Person's Name</a></div>
    <div title="Added at 06:40 on 30 Jun 2010" class="date">30 Jun 2010</div>
    <p>Comment Body</p>
</div>

頭像 div 包含一個超鏈接(如果用戶在提交評論時輸入了一個有效的 URL)和一個頭像圖像,該圖像是從 gravatar.com 獲取的。我們將在 tut 的 PHP 步驟中回到這一點。最後,我們有名稱和時間 div,以及評論正文。

XHTML 部分中的另一個重要元素是註釋表單。它通過 POST 發送 .除了 URL 字段之外的所有字段都是必需的。

demo.php

<div id="addCommentContainer">
    <p>Add a Comment</p>
    <form id="addCommentForm" method="post" action="">
        <div>
            <label for="name">Your Name</label>
            <input type="text" name="name" id="name" />

            <label for="email">Your Email</label>
            <input type="text" name="email" id="email" />

            <label for="url">Website (not required)</label>
            <input type="text" name="url" id="url" />

            <label for="body">Comment Body</label>
            <textarea name="body" id="body" cols="20" rows="5"></textarea>

            <input type="submit" id="submit" value="Submit" />
        </div>
    </form>
</div>

表單是通過 AJAX 提交的。驗證完全由 submit.php 在後端執行 ,正如您將在本教程的 jQuery 步驟中看到的那樣。每個字段都有一個對應的標籤元素,帶有適當的 for 屬性。

第 2 步 - PHP

PHP 處理與 MySQL 數據庫的通信並生成註釋標記。它也在 AJAX 請求的接收端,並將評論數據插入到 comments 桌子。您可以看到將評論打印到下面頁面的代碼。

demo.php

/*
/   Select all the comments and populate the $comments array with objects
*/

$comments = array();
$result = mysql_query("SELECT * FROM comments ORDER BY id ASC");

while($row = mysql_fetch_assoc($result))
{
    $comments[] = new Comment($row);
}

MySQL 查詢從數據庫中選擇所有條目並填充 $comments 包含評論類對象的數組,您將在下面看到。這個數組在腳本執行的後期輸出。

demo.php

/*
/   Output the comments one by one:
*/

foreach($comments as $c){
    echo $c->markup();
}

每條評論都有一個 markup() 方法,它生成準備好打印到頁面的有效 HTML 代碼。可以看下這個方法和類的定義。

該類從數據庫中獲取一行(使用 mysql_fetch_assoc() 獲取 ) 並將其存儲在私有變量 $data .它只對類的方法可用,不能從外部訪問。

comment.class.php - 第 1 部分

class Comment
{
    private $data = array();

    public function __construct($row)
    {
        /*
        /   The constructor
        */

        $this->data = $row;
    }

    public function markup()
    {
        /*
        /   This method outputs the XHTML markup of the comment
        */

        // Setting up an alias, so we don't have to write $this->data every time:
        $d = &$this->data;

        $link_open = '';
        $link_close = '';

        if($d['url']){

            // If the person has entered a URL when adding a comment,
            // define opening and closing hyperlink tags

            $link_open = '<a href="'.$d['url'].'">';
            $link_close =  '</a>';
        }

        // Converting the time to a UNIX timestamp:
        $d['dt'] = strtotime($d['dt']);

        // Needed for the default gravatar image:
        $url = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]).
                '/img/default_avatar.gif';

        return '

            <div class="comment">
                <div class="avatar">
                    '.$link_open.'
                    <img src="http://www.gravatar.com/avatar/'.
                md5($d['email']).'?size=50&default='.
                urlencode($url).'" />
                    '.$link_close.'
                </div>

                <div class="name">'.$link_open.$d['name'].$link_close.'</div>
                <div class="date" title="Added at '.
                date('H:i \o\n d M Y',$d['dt']).'">'.
                date('d M Y',$d['dt']).'</div>
                <p>'.$d['body'].'</p>
            </div>
        ';
    }

該腳本使用 gravatar 在評論中顯示頭像。對於那些沒有使用過 gravatar 的人來說,這是一項非常有用的服務,它可以讓您將頭像與您的電子郵件地址相關聯。通過傳遞 md5() 可以輕鬆獲取頭像圖像 您的電子郵件地址的編碼哈希到 gravatar.com。這正是我們在第 48 行所做的 .

注意第 39 行 在它上面 - 腳本試圖找出它所在的 URL,並確定 default_avatar.gif 的確切地址 圖片。此 gif 將沿 md5 哈希傳遞給 gravatar,因此如果未找到此特定電子郵件的頭像,則會顯示備用圖像。

comment.class.php - 第 2 部分

 public static function validate(&$arr)
    {
        /*
        /   This method is used to validate the data sent via AJAX.
        /
        /   It return true/false depending on whether the data is valid, and populates
        /   the $arr array passed as a paremter (notice the ampersand above) with
        /   either the valid input data, or the error messages.
        */

        $errors = array();
        $data   = array();

        // Using the filter_input function introduced in PHP 5.2.0

        if(!($data['email'] = filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL)))
        {
            $errors['email'] = 'Please enter a valid Email.';
        }

        if(!($data['url'] = filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL)))
        {
            // If the URL field was not populated with a valid URL,
            // act as if no URL was entered at all:

            $url = '';
        }

        // Using the filter with a custom callback function:

        if(!($data['body'] = filter_input(INPUT_POST,'body',FILTER_CALLBACK,
                        array('options'=>'Comment::validate_text'))))
        {
            $errors['body'] = 'Please enter a comment body.';
        }

        if(!($data['name'] = filter_input(INPUT_POST,'name',FILTER_CALLBACK,
                        array('options'=>'Comment::validate_text'))))
        {
            $errors['name'] = 'Please enter a name.';
        }

        if(!empty($errors)){

            // If there are errors, copy the $errors array to $arr:

            $arr = $errors;
            return false;
        }

        // If the data is valid, sanitize all the data and copy it to $arr:

        foreach($data as $k=>$v){
            $arr[$k] = mysql_real_escape_string($v);
        }

        // Ensure that the email is in lower case (for a correct gravatar hash):
        $arr['email'] = strtolower(trim($arr['email']));

        return true;

    }

驗證() 上面的方法(也是類的一部分)被定義為 static .這意味著它可以像 Comment::validate() 一樣被直接喚起 ,而不需要創建類的對象。該方法的作用是驗證通過 AJAX 提交的輸入數據。

此方法使用新的過濾器函數,從 PHP 5.2.0 開始可用 .這些使我們能夠輕鬆地驗證和過濾傳遞給腳本的任何輸入數據。例如 filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL) 表示我們正在檢查 $_POST['url'] 是一個有效的 URL 地址。如果是,則函數返回變量的值,否則返回false .

這真的很有用,因為到目前為止,我們必須使用自定義正則表達式來驗證數據(並且有一系列 if 語句)。此外,另一個優點是在應用任何特定於配置的轉換(如魔術引號)之前獲取此數據。

我們還可以選擇指定一個自定義函數,該函數將對數據進行一些更高級的修改,如第 31 和 37 行所示。

comment.class.php - 第 3 部分

 private static function validate_text($str)
    {
        /*
        /   This method is used internally as a FILTER_CALLBACK
        */

        if(mb_strlen($str,'utf8')<1)
            return false;

        // Encode all html special characters (<, >, ", & .. etc) and convert
        // the new line characters to <br> tags:

        $str = nl2br(htmlspecialchars($str));

        // Remove the new line characters that are left
        $str = str_replace(array(chr(10),chr(13)),'',$str);

        return $str;
    }

}

最後一個方法是validate_text, 我們在上面的兩個 filter_input 調用中將其作為回調函數傳遞。它對所有特殊的 HTML 字符進行編碼,有效地阻止 XSS 攻擊。它還將換行符替換為
換行符。

提交.php

/*
/   This array is going to be populated with either
/   the data that was sent to the script, or the
/   error messages:
/*/

$arr = array();

$validates = Comment::validate($arr);

if($validates)
{
    /* Everything is OK, insert to database: */

    mysql_query("   INSERT INTO comments(name,url,email,body)
                    VALUES (
                        '".$arr['name']."',
                        '".$arr['url']."',
                        '".$arr['email']."',
                        '".$arr['body']."'
                    )");

    $arr['dt'] = date('r',time());
    $arr['id'] = mysql_insert_id();

    /*
    /   The data in $arr is escaped for the mysql insert query,
    /   but we need the unescaped text, so we apply,
    /   stripslashes to all the elements in the array:
    /*/

    $arr = array_map('stripslashes',$arr);

    $insertedComment = new Comment($arr);

    /* Outputting the markup of the just-inserted comment: */

    echo json_encode(array('status'=>1,'html'=>$insertedComment->markup()));

}
else
{
    /* Outputting the error messages */
    echo '{"status":0,"errors":'.json_encode($arr).'}';
}

提交.php 通過 AJAX 請求接收評論表單數據。它驗證它並輸出帶有成功插入註釋的 XHTML 標記或錯誤消息列表的 JSON 對象。 jQuery 使用 status 屬性來決定是顯示錯誤消息還是在頁面中添加註釋標記。

您可以在下面看到兩個示例響應。

成功響應

{
    "status": 1,
    "html": "Html Code Of The Comment Comes Here..."
}

html 屬性包含註釋的代碼,類似於第一步中的標記。

失敗響應

{
    "status": 0,
    "errors": {
        "email": "Please enter a valid Email.",
        "body": "Please enter a comment body.",
        "name": "Please enter a name."
    }
}

失敗時,jQuery 循環遍歷錯誤對象,並在導致錯誤的字段旁邊輸出錯誤。

第 3 步 - CSS

現在我們已經正確生成並顯示在頁面上的所有標記,我們可以繼續對其進行樣式設置。

styles.css - 第 1 部分

.comment,
#addCommentContainer{

    /* Syling the comments and the comment form container */

    padding:12px;
    width:400px;
    position:relative;
    background-color:#fcfcfc;
    border:1px solid white;
    color:#888;
    margin-bottom:25px;

    /* CSS3 rounded corners and drop shadows */

    -moz-border-radius:10px;
    -webkit-border-radius:10px;
    border-radius:10px;

    -moz-box-shadow:2px 2px 0 #c2c2c2;
    -webkit-box-shadow:2px 2px 0 #c2c2c2;
    box-shadow:2px 2px 0 #c2c2c2;
}

.comment .avatar{

    /*
    /   The avatar is positioned absolutely,
    /   and offset outside the comment div
    /*/

    height:50px;
    left:-70px;
    position:absolute;
    width:50px;
    background:url('img/default_avatar.gif') no-repeat #fcfcfc;

    /* Centering it vertically: */

    margin-top:-25px;
    top:50%;

    -moz-box-shadow:1px 1px 0 #c2c2c2;
    -webkit-box-shadow:1px 1px 0 #c2c2c2;
    box-shadow:1px 1px 0 #c2c2c2;
}

.comment div 和 #addCommentContainer 會同時設置樣式,因為它們共享大部分樣式。應用了許多 CSS3 規則,包括圓角和框陰影。不用說,這些在舊版瀏覽器中不起作用,但由於它們純粹是展示性的,因此腳本在沒有它們的情況下仍然可以工作。

styles.css - 第 2 部分

.comment .avatar img{
    display:block;
}

.comment .name{
    font-size:20px;
    padding-bottom:10px;
    color:#ccc;
}

.comment .date{
    font-size:10px;
    padding:6px 0;
    position:absolute;
    right:15px;
    top:10px;
    color:#bbb;
}

.comment p,
#addCommentContainer p{
    font-size:18px;
    line-height:1.5;
}

#addCommentContainer input[type=text],
#addCommentContainer textarea{

    /* Styling the inputs */

    display:block;
    border:1px solid #ccc;
    margin:5px 0 5px;
    padding:3px;
    font-size:12px;
    color:#555;
    font-family:Arial, Helvetica, sans-serif;
}

#addCommentContainer textarea{
    width:300px;
}

label{
    font-size:10px;
}

label span.error{
    color:red;
    position:relative;
    right:-10px;
}

#submit{

    /* The submit button */

    background-color:#58B9EB;
    border:1px solid #40A2D4;
    color:#FFFFFF;
    cursor:pointer;
    font-family:'Myriad Pro',Arial,Helvetica,sans-serif;
    font-size:14px;
    font-weight:bold;
    padding:4px;
    margin-top:5px;

    -moz-border-radius:4px;
    -webkit-border-radius:4px;
    border-radius:4px;
}

#submit:hover{
    background-color:#80cdf5;
    border-color:#52b1e2;
}

在樣式表的第二部分,我們設置註釋和表單元素的樣式。注意 input[type=text] 選擇器,根據type屬性選擇元素。

第 4 步 - jQuery

現在讓我們繼續使用 jQuery,這是本教程的最後一步。將庫包含到頁面底部(最適合頁面的感知性能)後,我們可以開始編寫腳本文件了。

script.js

$(document).ready(function(){
    /* The following code is executed once the DOM is loaded */

    /* This flag will prevent multiple comment submits: */
    var working = false;

    /* Listening for the submit event of the form: */
    $('#addCommentForm').submit(function(e){

        e.preventDefault();
        if(working) return false;

        working = true;
        $('#submit').val('Working..');
        $('span.error').remove();

        /* Sending the form fileds to submit.php: */
        $.post('submit.php',$(this).serialize(),function(msg){

            working = false;
            $('#submit').val('Submit');

            if(msg.status){

                /*
                /   If the insert was successful, add the comment
                /   below the last one on the page with a slideDown effect
                /*/

                $(msg.html).hide().insertBefore('#addCommentContainer').slideDown();
                $('#body').val('');
            }
            else {

                /*
                /   If there were errors, loop through the
                /   msg.errors object and display them on the page
                /*/

                $.each(msg.errors,function(k,v){
                    $('label[for='+k+']').append('<span class="error">'+
                        v+'</span>');
                });
            }
        },'json');

    });

});

從頂部開始,我們有 $(document).ready() 調用,將函數綁定到加載的 DOM 內容 事件。工作變量充當一個標誌,告訴腳本是否正在進行 AJAX 請求(從而防止重複發布)。

在 POST AJAX 請求的回調函數中,我們檢查 status 屬性以確定評論是否插入成功。如果是,我們將收到的標記添加到最後一條評論之後的頁面,並使用 slideDown 動畫。

如果有問題,我們會通過將錯誤範圍附加到適當的標籤元素來顯示錯誤消息(標籤的 for 屬性包含導致錯誤的輸入的 id)。

有了這個,我們的簡單 AJAX 評論系統就完成了!

結論

為了能夠在您的服務器上運行此腳本,您需要創建 comments MySQL 數據庫中的表。您可以通過執行 table.sql 中的 SQL 代碼來完成此操作 從 phpMyAdmin 的 SQL 選項卡。在此之後,您需要在 connect.php 中輸入您的 MySQL 連接詳細信息 .

您可以隨意修改和使用此代碼。

你怎麼看?您將如何改進此腳本?


Tutorial JavaScript 教程
  1. 我的第一個開源項目:使用 2 行代碼最小化和自動化 ExpressJs REST API 設置

  2. 使用 React 開發一個成熟的組件庫,就像 Material UI

  3. 貢獻給 dev.to,你也可以!

  4. (五)非凡的 Javascript 資源聯盟

  5. 對您的代碼進行測試的最大價值可能是......

  6. 帶有 JS 和 HTML 的 Firebase CRUD:讀取、更新和刪除

  7. 時刻js中帶有日期數字的工作日

  1. 使用 append() 附加大塊 html

  2. 使用 HTML、CSS 和 JavaScript 構建動畫推薦卡。

  3. 使用異步生成器解耦業務邏輯

  4. 圖像,onload 事件在 chrome 中不起作用

  5. JavaScript 中的方法鍊是什麼,它是如何工作的以及如何使用它

  6. 調試提示:Javascrip2

  7. 了解 JavaScript 裝飾器

  1. 構建零依賴的移動文檔掃描儀:霍夫變換

  2. 如何在您的 Web 應用程序中使用 jQuery Upload UI 組件

  3. 對 Tailwind、Vue 和 Vite 感到好奇?

  4. 重新審視 JavaScript Mixins