article

ساخت قابلیت امتیازدهی با PHP و Ajax

ajax-php-voting

از جمله قابلیت ها و امکانات مورد نیاز در برخی صفحات وب مانند شبکه های اجتماعی، پایگاه های خبری، سایت های پرسش و پاسخ، انجمن ها و... قابلیت امتیازدهی به مطالب و نظرات کاربران است که امروزه کاربرد فراوان دارد، ویژگی خاص این قابلیت، یعنی نیاز به ارسال و دریافت درخواست در پس زمینه و بدون رفرش شدن صفحه باعث می شود که ناگزیر دست به دامن آژاکس (Ajax) یا فریم ورک های آن شویم، از طرفی بعد از ارسال درخواست آژاکسی، در سمت سرور نیز باید با php و mysql آن را پردازش کرده و متناسب با اتفاقاتی که روی می دهد، خروجی ارسال کنیم، البته مبحث اصلی یادگیری ایجاد و مدیریت این امکان است و جزئیات آن به برنامه نویس بستگی دارد، لذا در این آموزش تنها به قسمت آژاکس و php آن خواهیم پرداخت و قسمت mysql را خودتان می توانید با توجه به نیازتان اضافه کنید.

کد جاوا اسکریپت سیستم امتیازدهی


قبل از هر چیز ما به واسطه ای نیاز داریم که بتواند بدون رفرش شدن صفحه، درخواست کاربر را به سرور منتقل کرده و پاسخ سرور را دریافت، پردازش و در صورت نیاز خروجی دهد، این واسطه در اکثر موارد چیزی نیست به جزء آژاکس و جاوا اسکریپت (یا فریم ورک های مبتنی بر آن مانند جی کئوری) که در زیر یک نمونه از آن را ملاحظه می کنید.
<script type="text/javascript">
//<![CDATA[
function voting(action,id){
    var up_point_id = "up_point_" + id;
    var down_point_id = "down_point_" + id;    
    var loading_id = "loading_img_" + id;        
    var loading = '<img src="loading.gif" alt="loading" height="16" width="16" border="0" />';
    if (action == 'up'){
        var user_point = document.getElementById(up_point_id).innerHTML;
    }
    else if (action == 'down'){
        var user_point = document.getElementById(down_point_id).innerHTML;
    }
    var xmlhttp;
    if (window.XMLHttpRequest){
        xmlhttp=new XMLHttpRequest();
    }
    else{
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange=function(){
    if (xmlhttp.readyState > 0 && xmlhttp.readyState < 4){
        document.getElementById(loading_id).innerHTML=loading;
    }
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
        document.getElementById(loading_id).innerHTML='';
        var response = xmlhttp.responseText;
        var splited_response = response.split("||");
        var status = splited_response[0];        
        var new_point = splited_response[1];
        if (action == 'up' && status == 'ok'){
            document.getElementById(up_point_id).innerHTML=new_point;
        }
        else if (action == 'down' && status == 'ok'){
            document.getElementById(down_point_id).innerHTML=new_point;
        }
    }
  }
  var req = "vote.php?do=" + action + "&user=" + id + "&point=" + user_point;
  xmlhttp.open("GET",req,true);
  xmlhttp.send();
}
//]]>
</script>
توضیح:
- در کد بالا ما صرفا از برنامه نویسی ساده جاوا اسکریپت و آژاکس استفاده کرده ایم که این کار موجب کاهش چشمگیر حجم نهایی صفحات وب می شود.
- تابعی که از آن استفاده کرده ایم، voting نام دارد که البته یک نام دلخواه و فرضی است، این تابع از دو آرگومان استفاده می کند، آرگومان اول (action) مشخص می کند که آیا کاربر قصد دادن امتیاز منفی را دارد یا اینکه می خواهد امتیاز مثبت بدهد، مقادیر آرگومان در هنگام فراخوانی تابع با عبارات up یا down مشخص می شوند.
- آرگومان دوم برای این است که کاربران مختلف را در صفحه از هم متمایز کنیم، در اینجا می توان از تکنیک های زیادی بسته به سلیقه استفاده کرد، به طور مثال ما از نام کاربران برای آرگومان دوم استفاده کرده ایم و برای هر کاربر نیز، نام او را به انتهای عنوان آی دی بلاک ها اضافه نموده ایم، به این ترتیب سیستم ما قادر خواهد بود که هر کاربر را به طور مجزا شناسایی کند، البته در عمل برای ایجاد چنین مواردی می توان در هنگام خروجی گرفتن، لیست کاربران را از دیتابیس استخراج و در حلقه foreach یا for به صورت داینامیک چاپ کرد.
- در قسمت اول تابع  voting چند متغیر تعریف می کنیم که در ادامه به آنها نیاز خواهیم داشت، به فرض متغیر up_point_id از پیوستن پیش عبارت _up_point به آرگومان id برای هر کاربر به صورت داینامیک، آی دی اختصاصی بلاک او را برای امتیازات مثبت تعریف می کند، یا متغیر loading_id به همین ترتیب مشخص می کند که تصویر کوچک نمایش در حال بارگذاری باید برای کدام کاربر به نمایش درآید.
- در گام بعدی چون در اینجا ما از دیتابیس استفاده نمی کنیم، ناچاریم امتیازات فعلی را از صفحه حاضر دریافت کنیم، لذا یک متغیر با نام user_point تعریف می کنیم که وظیفه اش گرفتن محتوای درون بلاک up_point_id یا down_point_id است، این مقدار به سرور ارسال شده و (در این مثال) با عدد 1 جمع می شود، نهایتا نیز حاصل با xmlhttp.responseText بازگشت داده می شود.
- همان طور که در آموزش های مقدماتی آژاکس (Ajax) گفته ایم، پس از ارسال درخواست آژاکسی، xmlhttp.readyState در چند وضعیت قرار می گیرد که با اعداد 0 تا 4 دریافت می شوند، بدین شرح:
عدد 0 به معنی حالت عادی و عدم درخواست آژاکس است.
عدد 1 به معنی شروع درخواست آژاکس است.
عدد 2 به معنی دریافت درخواست آژاکس توسط سرور است.
عدد 3 به معنی در حال پردازش بودن درخواست آژاکس است.
عدد 4 به معنی تکمیل درخواست و آماده بودن پاسخ آن است.
لذا بین عدد 0 تا 4 می توان یک تصویر کوچک به عنوان در حال بارگذاری نمایش داد.
- برای اینکه بتوانیم پاسخ سرور را به درستی مدیریت کنیم، آن را با split به آرایه هایی تجزیه می کنیم، در اینجا از علامت || به عنوان جدا کننده، برای قسمت کردن پاسخ و تجزیه آن در چند متغیر مجزا استفاده کرده ایم، حال متغیر status بخش اول پاسخ سرور و متغیر new_point قسمت دوم آن را در خود دارد.
- ملاحظه می کنید که از متد GET برای ارسال و دریافت متغیرها و مقادیر آنها به سرور استفاده شده است.

فراخوانی تابع voting


برای فراخوانی تابع کافی است آن را به صورت a و href به همراه رویداد onclick تعریف کنید، این کار را در نمونه زیر برای دو کاربر انجام داده ایم.
<div class="user">
<a href="#" onclick="voting('up','user1');"><img src="plus.png" height="16" width="16" alt="up" title="امتیاز مثبت" border="0" /></a>
<span id="up_point_user1">0</span>
<a href="#" onclick="voting('down','user1');"><img src="minus.png" height="16" width="16" alt="down" title="امتیاز منفی" border="0" /></a>
<span id="down_point_user1" dir="ltr">0</span>
<span id="loading_img_user1"></span>
</div>
<div class="user">
<a href="#" onclick="voting('up','user2');"><img src="plus.png" height="16" width="16" alt="up" title="امتیاز مثبت" border="0" /></a>
<span id="up_point_user2">0</span>
<a href="#" onclick="voting('down','user2');"><img src="minus.png" height="16" width="16" alt="down" title="امتیاز منفی" border="0" /></a>
<span id="down_point_user2" dir="ltr">0</span>
<span id="loading_img_user2"></span>
</div>
توضیح:
- در مثال بالا برای هر کاربر یک بلاک با کلاس فرضی user در نظر گرفته ایم.
- اگر به آی دی به کار رفته شده برای تگ های span دقت کنید، ملاحظه می کنید که نام هر کاربر برای تفکیک، به انتهای آنها اضافه شده است.

کد php برای سیستم امتیازدهی


برنامه هنوز تکمیل نشده است، گذشته از سمت کاربر و اسکریپت نویسی آن، بخش عمده کار مربوط می شود به سمت سرور و پردازش های آن، به طور مثال پس از ارسال درخواست، ابتدا باید ببینیم کاربر به چه کسی قصد امتیاز دادن دارد  و امتیاز فعلی آن فرد چقدر است، اگر قصد کاربر امتیاز مثبت بود، امتیازات فعلی را به اضافه مقادیر جدید کنیم، یا برعکس اگر کاربر امتیاز منفی داد، امتیازات فرد را از مقادیر جدید کم و سپس نتایج جدید را هم در دیتابیس به روز کرده و هم به صفحه مرورگر ارسال کنیم، لذا بخش اصلی کار ما در کنار کدها و برنامه نویسی php کار با دیتابیس و پرس و جوهای mysql خواهد بود، اما به جهت اینکه آموزش حاضر صرفا برای این است که یک نمونه باشد، از مباحث مربوط به mysql آن می گذریم و برای درک مطلب با یک تکه کد php ساده کار را ادامه می دهیم.
<?php
$do = $_GET['do'];
$point = $_GET['point'];
if ($do == 'up'){
    $new_point = $point + 1;
}
elseif($do == 'down'){
    $new_point = $point - 1;    
}
echo 'ok'.'||'.$new_point;
?>
توضیح:
- این کد را با نام vote.php در یک فایل ذخیره کنید، فایل حاضر و صفحه html که کد آژاکس را در آن قرار داده ایم باید در یک فولدر قرار گیرند یا اینکه آدرس قسمت var req به درستی تنظیم شود.
- در کد بالا تنها با یک دستور شرطی ساده امتیاز فعلی کاربر را یک واحد افزایش یا کاهش می دهیم.
- خروجی ما با علامت || از هم تفکیک شده است، همان طور که پیش تر گفتیم، در سمت کاربر و در کد آژاکس، پاسخ سرور را با این علامت و دستور split تجزیه می کنیم.

کد نهایی و پیش نمایش آنلاین


برای ملاحظه یک نمونه آزمایشی و اولیه از سیستم امتیازدهی می توانید از کد و پیش نمایش آنلاین زیر استفاده کنید.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>وبگو | ایجاد امکان امتیازدهی در سایت</title>
<!-- https://webgoo.ir -->
<style type="text/css">
body{
    font-family:Tahoma, Geneva, sans-serif;
    font-size:12px;
    direction:rtl;
}
.user{
    display:block;
    border:#666 1px dashed;
    height:30px;
    width:120px;
    padding:4px;
    margin:4px;
}
</style>
<script type="text/javascript">
//<![CDATA[
function voting(action,id){
    var up_point_id = "up_point_" + id;
    var down_point_id = "down_point_" + id;    
    var loading_id = "loading_img_" + id;        
    var loading = '<img src="loading.gif" alt="loading" height="16" width="16" border="0" />';
    if (action == 'up'){
        var user_point = document.getElementById(up_point_id).innerHTML;
    }
    else if (action == 'down'){
        var user_point = document.getElementById(down_point_id).innerHTML;
    }
    var xmlhttp;
    if (window.XMLHttpRequest){
        xmlhttp=new XMLHttpRequest();
    }
    else{
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    xmlhttp.onreadystatechange=function(){
    if (xmlhttp.readyState > 0 && xmlhttp.readyState < 4){
        document.getElementById(loading_id).innerHTML=loading;
    }
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
        document.getElementById(loading_id).innerHTML='';
        var response = xmlhttp.responseText;
        var splited_response = response.split("||");
        var status = splited_response[0];        
        var new_point = splited_response[1];
        if (action == 'up' && status == 'ok'){
            document.getElementById(up_point_id).innerHTML=new_point;
        }
        else if (action == 'down' && status == 'ok'){
            document.getElementById(down_point_id).innerHTML=new_point;
        }
    }
  }
  var req = "vote.php?do=" + action + "&user=" + id + "&point=" + user_point;
  xmlhttp.open("GET",req,true);
  xmlhttp.send();
}
//]]>
</script>
</head>
<body>
<noscript>
جاوا اسکریپت در مرورگر شما غیر فعال است یا پشتیبانی نمی شود! <br />
</noscript>
<div class="user">
<a href="#" onclick="voting('up','user1');"><img src="plus.png" height="16" width="16" alt="up" title="امتیاز مثبت" border="0" /></a>
<span id="up_point_user1">0</span>
<a href="#" onclick="voting('down','user1');"><img src="minus.png" height="16" width="16" alt="down" title="امتیاز منفی" border="0" /></a>
<span id="down_point_user1" dir="ltr">0</span>
<span id="loading_img_user1"></span>
</div>
<div class="user">
<a href="#" onclick="voting('up','user2');"><img src="plus.png" height="16" width="16" alt="up" title="امتیاز مثبت" border="0" /></a>
<span id="up_point_user2">0</span>
<a href="#" onclick="voting('down','user2');"><img src="minus.png" height="16" width="16" alt="down" title="امتیاز منفی" border="0" /></a>
<span id="down_point_user2" dir="ltr">0</span>
<span id="loading_img_user2"></span>
</div>
<hr />
سیستم امتیازدهی بالا جهت تست و بدون استفاده از دیتابیس کار می کند؛ لذا امتیازات بعد از بستن یا رفرش صفحه به حالت پیش فرض بر می گردند، برای ساخت یک سیستم امتیازدهی کامل باید علاوه بر آژاکس و php از mysql نیز استفاده کنید.
</body>
</html>
پیش نمایش
sectionدسته بندی: آموزش کاربردی » Ajax
related مطالب بیشتر:
» لیست داینامیک پیشنهاد کلمات، مبتنی بر ای جکس، PHP و MySQL
» نمایش داینامیک و صفحه به صفحه مطالب با ای جکس (Ajax)
» نمایش زنده آمار و اطلاعات با ای جکس (Ajax)
» ارسال اطلاعات فرم با ای جکس (Ajax) و نمایش پیام در حال پردازش
» آموزش نحوه آپلود فایل با PHP و آژاکس (Ajax)
commentنظرات (۱۷ یادداشت برای این مطلب ارسال شده است)
more یادداشت های جدید بر اساس تاریخ ارسال در انتهای یادداشت های موجود نمایش داده می شوند.
نویسنده: mehrdad
زمان: ۱۳:۵۱:۴۴ - تاریخ: ۱۳۹۴/۰۱/۳۱
سلام
ایا اموزش مربوطه (یعنی کسب امتیاز با فعالیت کاربران) را در سایت قرار می دهید؟
با سپاس
پاسخ: 
سلام
به دنبال این نوع آموزش ها در وب نباشید! چون اصولا چنین مواردی به دلیل گسترده و پیوسته بودن موضوع قابل طرح در یک مطلب نیست (به عبارتی شما باید برنامه نویس باشید و متناسب با برنامه و نیاز خودتان کدهای سفارشی تعریف کنید!).
نویسنده: بهرنگ
زمان: ۱۰:۱۹:۴۶ - تاریخ: ۱۳۹۵/۰۳/۱۵
سلام خیلی عالی بود
paged صفحه 2 از 2
more لطفا پیش از ارسال یادداشت نکات زیر را مد نظر داشته باشید:
- مواردی که به کلی خارج از موضوع این مطلب هستند را در فرم منوی "تماس با ما" مطرح و پاسخ را از طریق ایمیل دریافت کنید.
- به سوالات کلی، مبهم، غیرضروری و مشکلاتی که تلاشی برای رفع آن نکرده باشید پاسخ خاصی داده نخواهد شد.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین قرار دهید تا امکان تست و بررسی وجود داشته باشد.
- تمام یادداشت ها بررسی و برای هر کاربر زمان مشخصی جهت پاسخگویی در نظر گرفته می شود، لذا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.




4 × 6
 refresh
نکته:
با توجه به تاریخ نگارش آموزش های سایت و پیشرفت تکنولوژی های مرتبط با وب در سالیان اخیر، محتوای برخی از مطالب قدیمی ممکن است نیاز به ویرایش و به روزرسانی داشته باشند که این کار هم زمان با تهیه نسخه جدید «وبگو» به مرور در حال انجام است، لطفا در استفاده از مطالب سایت به این نکته دقت داشته و حتی المقدور از چند منبع مختلف استفاده نمائید.
آخرین دیدگاه ها
form مهسا
در:
سلام وقت بخیر من یک فرم طراحی کردم input ها به صورت دو ستونه گذاشتم. میخواستم با زدن تب از input اولی در...
۱۳:۰۱:۴۶ ۱۳۹۸/۰۶/۰۲

form behzad
در:
مرسی خوب بود
۱۲:۱۵:۱۴ ۱۳۹۸/۰۶/۰۲

form zeynab
در:
سلام یه سوال دارم برای اینکه بتونم رنگ رو ذخیره کنم تو جدولم در قسمت پایگاه داده چیکار باید کنم ؟؟ من...
۱۷:۰۶:۳۵ ۱۳۹۸/۰۵/۲۸

form علی
در:
سلام من میخوام تو صفحه html همچین طرحی رو بندازم میشه راهنماییم کنید (به صورت جداگانه یعنی هر کدوم توی یه صفحه) ***** ...
۱۶:۴۶:۳۶ ۱۳۹۸/۰۵/۲۷

form Zeynab
در:
سلام . وقت بخیر . من از کدهای htaccess برای سایت استفاده کردم . روی لوکال هاست مشکلی ندارم اجرا میشن . ...
۲۲:۴۲:۵۴ ۱۳۹۸/۰۵/۲۳

form bahman
در:
عالی
۲۲:۱۵:۵۰ ۱۳۹۸/۰۵/۲۳

form Abbas rahmati
در:
سلام همه چی توی قسمت اینکه اس اس ال چطور کار میکنه درست بود فقط اخرشو درست نگفتید
۱۴:۱۶:۴۰ ۱۳۹۸/۰۵/۲۳

form مهدی فراهانی
در:
در آکولاد if، می خواهم پس از صحت پرداخت کاربر، کاربر به یک صفحه html برای دانلود فایل لینک شود. چه دستوری در حلقه if...
۱۲:۰۸:۳۲ ۱۳۹۸/۰۵/۲۳

form احسایدر
در:
شما از چه روشی برای لینک دادن به قسمت‌های نوشته استفاده کردید که با کلیک کردن چیزی به آدرس نوشته اضافه نمیشه؟
۱۸:۵۷:۰۵ ۱۳۹۸/۰۵/۲۲

form Mahyar
در:
سلام خسته نباشید اگه بخواهیم که یک pop up با کلیک به خارج از کادر pop up یا کلیک به روی دکمه esc...
۱۱:۴۸:۵۶ ۱۳۹۸/۰۵/۱۹

form بینهایت
در:
سلام. میخواستم بپرسم اگر به اینترنت جایی وصل باشیم کسی که ادرس IP رو میدونه ایا امکان داره از طریق همین اتصال به سیستم ما...
۱۰:۲۶:۱۵ ۱۳۹۸/۰۵/۱۵

form کیهان
در:
سلام دوستان من یک صفحه درست کردم که از طریق یک فرم اطلاعات رو میفرسته به این صفحه برای ذخیره در دیتابیس ولی...
۱۱:۰۰:۲۳ ۱۳۹۸/۰۵/۱۴

form مجتبی
در:
هر وقت این سایت رو می بینم سریع ازش رد میشم حالم از این سایت بهم میخوره هیچ طراحی جذابی نداره مطالبش هم بدرد نخوره
۰۹:۵۳:۴۹ ۱۳۹۸/۰۵/۱۴

form بهزاد
در:
سلام من وبلاگ درست کردم عمل هم کرده ولی الان اخطار میده که وبلاگ شما در وضعیت عدم نمایش قرار دارد. برای فعال سازیش چکار...
۱۷:۲۰:۳۷ ۱۳۹۸/۰۵/۱۳

form امیر
در:
مرسی مقاله بسیار عالی بود . فوق العاده این.
۱۰:۵۰:۳۵ ۱۳۹۸/۰۵/۰۹
49 . 1 %
در حال برنامه نویسی و آماده سازی نسخه جدید «وبگو» هستیم، در این نسخه قابلیت ها و ظاهر سایت متفاوت و کاملتر خواهد بود، این فرآیند زمانبر است و روند پیشرفت پروژه در این قسمت به صورت درصدی نمایش و به تناوب به روزرسانی می شود. Webgoo.ir