چهارشنبه ۰۸ بهمن ۱۴۰۴

Wednesday, January 28, 2026 GMT +3:30

آموزش ساخت فرم تماس با PHP و MySQL

mysql-php-contact-form

از جمله امکاناتی که تقریبا هر سایتی برای داشتن ارتباط دوسویه با مخاطبانش به آن نیاز دارد فرم تماس (Contact Form) است و برای ایجاد این امکان معمولا برنامه نویسان وب از دو شیوه ی ارسال پیام به آدرس ایمیل مدیر یا ارسال پیام به سرور و ذخیره اطلاعات در دیتابیس سایت و گاهی ترکیب هر دو این شیوه ها را استفاده می کنند، از طرفی محافظت از فرم تماس در مقابل ارسال پیام های اسپم (Spam) یا هرزنامه نیز مبحثی است که در این مورد باید به آن توجه جدی داشته باشیم چون عدم استفاده از سیستم تشخیص ربات از انسان (CAPTCHA) در بخش تماس یا ضعف این سیستم می تواند باعث هجوم خزنده های ارسال هرزنامه به سیستم ارتباط با مخاطبان سایتمان شود که نتیجه آن انبوهی از پیام های تبلیغاتی است که توسط ربات ها ارسال شده و در لیست پیام های دریافتی نمایش داده می شود، با این مقدمه و به جهت کاربرد فراوان و اهمیت این موضوع در آموزش پیش رو قصد داریم تا با نحوه ساخت فرم تماسی نسبتا پیشرفته به کمک زبان برنامه نویسی PHP و پایگاه داده MySQL آشنا شویم.

ساخت فرم تماس به صورت html


طبق معمول آموزش های قبلی، نخستین گامی که برای رسیدن به هدفمان به آن نیاز داریم، ساختن یک فرم تماس در قالب کدهای html است تا اطلاعات آن پس از ارسال، به سرور منتقل و در آنجا (در دیتابیس) ذخیره شده یا توسط سیستم ایمیل (که در آموزش های کاربردی php و در مطلب ارسال ایمیل با php و کلاس phpmailer در مورد آن صحبت کرده ایم)، به آدرس مدیر سایت ارسال گردد، البته در اینجا هدف ما صرفا ذخیره یادداشت کاربر در دیتابیس است و مجددا به بحث ایمیل نمی پردازیم؛ لذا بدین منظور ابتدا فرم زیر را نوشته و آن را در یک فایل با نام فرضی index.php ذخیره می کنیم (البته این فرم در ادامه تکمیل خواهد شد و نمونه زیر تنها به عنوان مقدمه کار است).
<!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;
}
label{
    display:inline-block;
    width:100px;
    height:25px;
    vertical-align:top;
}
.code{
    width:50px;
    margin-top:2px;
}
</style>
</head>
<body>
<form action="contact.php" method="post">
<label for="name">نام:</label>
<input name="name" id="name" type="text" maxlength="255" /><br />
<label for="mail">ایمیل:</label>
<input name="mail" id="mail" type="text" maxlength="255" dir="ltr" /><br />
<label for="message">یادداشت:</label>
<textarea name="message" id="message" cols="35" rows="8">
</textarea><br />
<label for="code">کد امنیتی:</label>
<input name="code" id="code" type="text" class="code" /><br />
<input type="hidden" name="check" value="1" />
<input type="submit" value="ارسال" />
</form>
</body>
</html>
توضیح:
- همان طور که ملاحظه می کنید، اطلاعات این فرم جهت پردازش به فایل فرضی contact.php ارسال می شوند.
- فرم تماس در نمونه بالا دارای سه فیلد از نوع text جهت درج نام، ایمیل و کد امنیتی، یک فیلد از نوع textarea برای درج یادداشت کاربر و یک فیلد hidden یا مخفی برای بررسی و اطمینان از ارسال فرم در سرور است.
- برای تنظیمات ظاهری فرم تماس، می توانید از css یا از خاصیت های استاندارد html استفاده کنید.
نکته: این فایل را باید با پسوند php ذخیره کنید، چون در ادامه به دستورات و کدهای php درون آن نیاز خواهیم داشت.

پردازش و ذخیره اطلاعات در سرور با php و mysql


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

ساخت دیتابیس، جدول و ستون برای فرم تماس


برای ساختن دیتابیس، در لوکال هاست یا در سرور از برنامه phpMyAdmin استفاده کرده و یک دیتابیس به صورت دستی با نام فرضی contact بسازید (دقت کنید که یونیکد یا collation پیش فرض دیتابیس بر روی utf8_general_ci باشد)؛ سپس در یک فایل php با نام فرضی install، کد زیر را ذخیره و اجرا کنید تا جدول و ستون ها در دیتابیس contact ایجاد شوند:
<?php
//اطلاعات اتصال به دیتابیس
$con = mysql_connect("localhost","root","")
or die(mysql_error());
//نام پایگاه داده
mysql_select_db("contact", $con)
or die(mysql_error());
//پرس و جوی ساخت جدول
mysql_query("CREATE TABLE form(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
name VARCHAR(255),
mail VARCHAR(255),
message TEXT,
code VARCHAR(255),
date VARCHAR(255),
time VARCHAR(255),
userip VARCHAR(255),
useragent VARCHAR(255),
status VARCHAR(255)) ENGINE=MyISAM "
)
or die(mysql_error());
echo "CREATE TABLE form = ok<br />";
//سازگاری با زبان فارسی
mysql_query("ALTER TABLE form
DEFAULT CHARACTER SET utf8
COLLATE utf8_general_ci;"
)
or die(mysql_error());
echo "ALTER TABLE form = ok<br />";
//پایان ارتباط    
mysql_close($con);
?>
اکنون دیتابیس برای ذخیره اطلاعات آماده است، ضمن اینکه با استفاده از دستور ALTER TABLE و تنظیم یونیکد utf8 برای ستون ها، برای کار با حروف و زبان فارسی نیز مشکلی نخواهیم داشت.
نکته: برای ستون message از data type یا نوع TEXT به جای VARCHAR استفاده کرده ایم؛ این کار به دلیل محدودیت VARCHAR نسبت به TEXT در حداکثر میزان ظرفیت کلمات و کاراکترها است (حداکثر تعداد بایت کاراکتر در نوع VARCHAR در نسخه های ماقبل 5.0.3 از 0 تا 255 و از نسخه های مابعد آن 0 تا 65,535 است، اما برای نوع TEXT در تمام نسخه ها 65,535 بایت معادل 64kb کاراکتر است، البته از مقادیر دیگر مثلTINYTEXT با حداکثر 256 بایت کاراکتر، MEDIUMTEXT با حداکثر 16,777,215 بایت کاراکتر (16MB) و LONGTEXT با حداکثر 4,294,967,295 بایت کاراکتر (4GB) هم می توانید بسته به هدفتان استفاده کنید).

کد php برای پردازش اطلاعات فرم تماس


همان طور که در بالا و در قسمت کد html گفتیم، اطلاعات ارسال شده از فایل index.php به یک فایل دیگر به نام contact.php فرستاده می شود (البته می توانید برنامه خود را طوری بنویسید که اطلاعات به همان فایل ارسال شوند و نیازی به یک فایل دیگر نباشد)، در این فایل کدهای زیر را قرار می دهیم.
<!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;
}
.error{
    display:block;
    padding:10px;
    background-color:#C00;
    border:4px #EAEAEA solid;
    color:#FFF;
}
.sent{
    display:block;
    padding:10px;
    background-color:#090;
    border:4px #EAEAEA solid;
    color:#FFF;
}
</style>
</head>
<body>
<?php
//اطلاعات اتصال به دیتابیس
$con = mysql_connect("localhost","root","")
or die(mysql_error());
//نام پایگاه داده
mysql_select_db("contact", $con)
or die(mysql_error());
//تابعی برای ایمن سازی مقادیر
function clean($str) {
    $str = trim($str);
    if (get_magic_quotes_gpc()){
        $str = stripslashes($str);
    }    
    $str = htmlspecialchars($str);
return mysql_real_escape_string($str);
}
//دریافت و ایمن سازی متغیرها
$check = $_POST['check'];
$name = clean($_POST['name']);
$mail = clean($_POST['mail']);
$message = clean($_POST['message']);
$code = clean($_POST['code']);
//تنظیم تاریخ ، زمان و اختلاف زمانی سرور
$time_zone = 12600;
$date = date("Y-m-d", time()+$time_zone);
$time = date("H:i:s", time()+$time_zone);
//دریافت آی پی کاربر
$ip = $_SERVER['REMOTE_ADDR'];
//دریافت مشخصات مرورگر و سیستم
if (isset($_SERVER['HTTP_USER_AGENT'])){
    $agent = $_SERVER['HTTP_USER_AGENT'];
}
else{
    $agent = 'unknown';
}
//مقادیر پیش فرض برای خطا
$error = 0;
//بررسی معتبر بودن اطلاعات
if ($check == 1 && $name == ''){
    echo "<div class=\"error\">لطفا نام خود را وارد کنید!</div>";
    $error = 1;
}
elseif ($check == 1 && $message == ''){
    echo "<div class=\"error\">لطفا پیام خود را وارد کنید!</div>";
    $error = 1;    
}
elseif ($check == 1 && $code == ''){
    echo "<div class=\"error\">لطفا کد امنیتی را وارد کنید!</div>";
    $error = 1;    
}
//بررسی و ذخیره اطلاعات در دیتابیس
if ($check == 1 && $error != 1){
    //بررسی کد امنیتی
    $result = mysql_query("SELECT * FROM form WHERE userip = '$ip' AND code = '$code' AND status = 'temp' LIMIT 1")
    or die(mysql_error());
    $code_exist = mysql_num_rows($result);
    if ($code_exist > 0){
        //ذخیره اطلاعات در دیتابیس
        mysql_query("INSERT INTO form (name,mail,message,code,date,time,userip,useragent,status) VALUES ('$name','$mail','$message','$code','$date','$time','$ip','$agent','sent')")
        or die(mysql_error());
        echo "<div class=\"sent\">پیام شما با موفقیت ارسال شد!</div>";        
    }
    else{
        echo "<div class=\"error\">کد امنیتی اشتباه است! [<a href=\"javascript: history.go(-1)\">بازگشت</a>]</div>";
    }
}
//پایان ارتباط    
mysql_close($con);
?>
</body>
</html>
اکنون باید دو فایل با نام های index.php که فرم تماس را در آن نوشته ایم و فایلی دیگر با نام contact.php برای پردازش و ذخیره اطلاعات داشته باشیم، اما توضیح موارد مورد نیاز.
توضیح:
- در ابتدا یک اتصال با دیتابیس برقرا می کنیم، چرا که در ادامه کد، اطلاعاتی را از دیتابیس فراخوانی یا در آن ذخیره خواهیم کرد؛ دقت کنید که در این قسمت باید از نام کاربری و کلمه عبور دیتابیس خود استفاده کنید (در حالت پیش فرض این کار برای لوکال هاست انجام شده است).
- سپس متغیرهایی را که برای بررسی و کارکرد صحیح برنامه به آنها نیاز خواهیم داشت، تعریف می کنیم، همان طور که ملاحظه می کنید، از تابعی با نام clean برای جلوگیری از نفوذ به دیتابیس یا همان mysql injection استفاده کرده ایم، این تابع در واقع در درون خود چند کار را انجام می دهد، ابتدا فضای خالی احتمالی ابتدا و انتهای مقدار ارسال شده با trim حذف می شود، سپس وضعیت فعال بودن get_magic_quotes_gpc در سرور بررسی می شود، اگر این قابلیت در سرور فعال باشد (به طور پیش فرض معمولا این امکان غیر فعال است، ولی در برخی نسخه های قدیمی php ممکن است این طور نباشد)، مفسر php به صورت خودکار بک اسلش هایی (\) به مقادیر ارسال شده اضافه می کند (هر جا که علامت " یا ' باشد)، برای جلوگیری از ایجاد این بک اسلش های تکراری و ناخواسته، از stripslashes استفاده می کنیم؛ در قسمت بعدی تابع، htmlspecialchars کاراکترهای مربوط به تگ های html را غیر فعال می کند، این کار باعث می شود تگ ها به صورت متن دریافت شوند نه به صورت کدهای html، در نهایت نیز mysql_real_escape_string مقادیر را به جهت جلوگیری از نفوذ به دیتابیس ایمن سازی می کند و متغیر نهایی با return از تابع برگردانده می شود.
- تاریخ و زمان ارسال پیام را با تابع date در php بدست می آوریم، در اینجا علاوه بر این کار، اختلاف زمانی سرور از وقت محلی (ایران) را هم حساب می کنیم، برای سرورهایی که بر روی GMT تنظیم شده اند، اختلاف 3:30 معادل 12600 ثانیه و 4:30 معادل 16200 ثانیه خواهد بود؛ لذا این مقادیر را به زمان فعلی سرور اضافه می کنیم (دقت کنید که برخی سرور ها بر روی زمان دیگری ممکن است تنظیم شده باشند).
- برای اینکه سیستم کد امنیتی به طور صحیح کار کند، ما نیاز به شناسایی کاربران متفاوت از هم داریم، بدین منظور تقریبا دو راه وجود دارد؛ استفاده از سشن (session) و مقادیر id آن، یا استفاده از IP کاربر، به جهت جلوگیری از پیچیده شدن مبحث، در اینجا تنها از IP استفاده کرده و بحث سشن ها و کدهای امنیتی را به مطلب دیگری موکول می کنیم.
- برای بدست آوردن IP کاربر، ساده ترین راه استفاده از دستور SERVER و REMOTE_ADDR است که در کد بالا ملاحظه می کنید.
- علاوه بر این، اگر تمایل دارید اطلاعاتی در مورد مرورگر و سیستم عامل کاربر داشته باشید، می توانید از HTTP_USER_AGENT نیز استفاده کنید، در مثال بالا این کار انجام شده است.
- مرحله بعدی، مرحله اعتبار سنجی و اطمینان از خالی نبودن فیلد های مورد نیاز است (روش و نوع اعتبار سنجی به خودتان و هدفی که دارید، بستگی دارد و از این لحاظ محدودیتی نیست).
- و در گام نهایی نیز، پس از ارسال صحیح مقادیر از فرم تماس، ابتدا بررسی می شود که کد ذخیره شده برای IP کاربر در دیتابیس با آنچه که کاربر در فیلد مربوط به کد امنیتی وارد کرده است، یکی باشد، اگر این کدها مطابق هم بودند (در این صورت mysql_num_rows مقادیر 1 را برمی گرداند)، اطلاعات او در پایگاه داده ذخیره می شود و در غیر این صورت قسمت else اجرا شده و پیغام خطا نشان داده می شود.
اما اگر دقت کرده باشید، گفتیم IP و کد امنیتی با آنچه در دیتابیس ذخیره شده مقایسه می شود، لذا باید از قبل و در فرم تماس، IP و کد را علاوه بر ذخیره کردن، به کاربر نیز نشان دهیم (تا او مقادیر کد امنیتی را در فیلد مربوط وارد کند)؛ لذا در فایل index.php مقادیر زیر را برای سیستم کد امنیتی یا captcha اضافه می کنیم.

ساخت سیستم کد امنیتی یا captcha


همان طور که می دانیم، کد امنیتی یا captcha، به سیستمی برای شناسایی کاربران حقیقی (انسان ها) از کاربران ماشینی (ربات های خزنده، برنامه های مخرب و...) گفته می شود، اینکه چگونه این قابلیت را به فرم خود اضافه کنیم، تا حدود زیادی بستگی به خودتان دارد، برنامه هایی نیز بدین منظور نوشته شده و در وب وجود دارد که هر کدام دارای معایب و مزایایی هستند، اما اگر می خواهید خودتان این کار را انجام دهید، یک روش ساده را در زیر توضیح می دهیم و توسعه آن را به عهده شما می گذاریم.
گام اول برای ساخت سیستم کد امنیتی، ذخیره اطلاعات منحصر به فرد هر کاربر در دیتابیس است، برای این کار معمولا برنامه نویسان وب از دو روش IP یا روش سشن (session) استفاده می کنند، این دو روش در عمل یک کارکرد دارند ولی از نظر جزئیات کمی با هم فرق می کنند؛ گام بعدی ما ایجاد یک کد امنیتی (با استفاده از توابع و روش های مختلف در php) است، این کد همراه با اطلاعات کاربر علاوه بر اینکه در دیتابیس ذخیره شده، در یک بلاک مشخص به صورت یک معادله ساده، به کاربر نشان داده می شود (تا او بتواند مقادیر را وارد فیلد مورد نظر کند)؛ حال بعد از ارسال فرم، مقادیر موجود در دیتابیس با کد ارسال شده کاربر تطبیق داده می شود، اگر اطلاعات همسان و درست بود، پیام کاربر ذخیره می شود و در غیر این صورت، پیغام خطای کد امنیتی نشان داده می شود.
توجه داشته باشید، برنامه نویسانی که ربات های خزنده و اسپمرها را طراحی می کنند، هم زمان با به کارگیری روش های نوین ساخت کد امنیتی، برنامه های مخرب خود را نیز هوشمندتر می کنند، به طور مثال حتی برخی ربات ها قادر به تجزیه تحلیل و خواندن اعداد و حروف داخل تصاویر captcha هستند، پس مهم است از روشی استفاده نمائید که قابل شناسایی برای ربات نباشد و تا می توانید آن را پیچیده کنید، یکی از این روش ها که بازدهی بالاتری نسبت به موارد مشابه دارد، ترکیب اعداد به صورت حاصل جمع، ضرب و... است، معمولا این برنامه ها آنقدر هم هوشمند نیستند که منظور حقیقی شما را تشخیص دهند و احتمالا هر آنچه را در فرم می بینند در فیلد وارد می کنند! (سعی کنید از علامت های دیگر مانند فاصله، ()، [] و ... نیز در زمان نمایش کد امنیتی استفاده کنید)؛ در مثال زیر ما از حاصل جمع دو عدد استفاده کرده ایم.
فایل index.php که پیش از این ساختیم را ویرایش کرده و به صورت زیر تغییر دهید.
<!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;
}
label{
    display:inline-block;
    width:100px;
    height:25px;
    vertical-align:top;
}
.code{
    width:50px;
    margin-top:2px;
}
.code-box{
    display:inline-block;
    font-weight:bold;
}
</style>
</head>
<body>
<?php
//اطلاعات اتصال به دیتابیس
$con = mysql_connect("localhost","root","")
or die(mysql_error());
//نام پایگاه داده
mysql_select_db("contact", $con)
or die(mysql_error());
//ساخت کد امنیتی
$code_1 = rand(1,9);
$code_2 = rand(1,9);
$code = $code_1 + $code_2;
//دریافت آی پی کاربر
$ip = $_SERVER['REMOTE_ADDR'];
//بررسی وضعیت کاربر در سرور
$result = mysql_query("SELECT * FROM form WHERE userip = '$ip' AND status = 'temp' LIMIT 1")
or die(mysql_error());
$user_exist = mysql_num_rows($result);
if ($user_exist > 0){
    //به روز رسانی کد برای آی پی کاربر در دیتابیس
    mysql_query("UPDATE form SET code='$code' WHERE userip = '$ip' AND status = 'temp'" )
    or die(mysql_error());    
}
else{
    //ذخیره کد و آی پی کاربر در دیتابیس
    mysql_query("INSERT INTO form (code,userip,status) VALUES ('$code','$ip','temp')")
    or die(mysql_error());
}
?>
<form action="contact.php" method="post">
<label for="name">نام:</label>
<input name="name" id="name" type="text" maxlength="255" /><br />
<label for="mail">ایمیل:</label>
<input name="mail" id="mail" type="text" maxlength="255" dir="ltr" /><br />
<label for="message">یادداشت:</label>
<textarea name="message" id="message" cols="35" rows="8">
</textarea><br />
<label for="code">کد امنیتی:</label>
<input name="code" id="code" type="text" class="code" />
<div class="code-box"><?php echo $code_1.' + '.$code_2 ?></div><br />
<input type="hidden" name="check" value="1" />
<input type="submit" value="ارسال" />
</form>
</body>
</html>
توضیح:
- از آنجایی که به حاصل جمع دو عدد تصادفی نیاز داریم، برای ساخت کد امنیتی از تابع rand در php استفاده کرده ایم، کد نهایی ما، در واقع حاصل جمع دو مقدار اتفاقی بین اعدا 1 تا 9 خواهد بود (روش تولید کدهای اتفاقی به این شیوه محدود نمی شود و می توان توابع پیشرفته تری برای آن به کار برد).
- برای تفکیک کاربرانی که نظر آنها ارسال و در دیتابیس ذخیره شده با آنهایی که هنوز نظری ارسال نکرده اند، از یک ستون با نام status یا وضعیت استفاده کرده ایم (نامی دلخواه است)، بدین ترتیب کاربرانی که نظر آنها ارسال نشده است یا قصد ندارند نظری ارسال کنند، تنها به عنوان temp یا موقتی در دیتابیس ذخیره می شوند و مقادیر این ستون برای آنهایی که پیامی ارسال می کنند، sent در نظر گرفته می شود (در فایل contact.php این مقادیر بعد از بررسی صحیح بودن کد امنیتی، در ستون status ذخیره می شود).
- همان طور که ملاحظه می کنید، ابتدا بررسی می کنیم که آیا چنین کاربری (IP) در دیتابیس از قبل موجود است (ممکن است کاربر صفحات سایت را قبلا دیده باشد)، اگر این طور بود، مقادیر مربوط به ستون کد امنیتی را با مقدار جدید به روز رسانی می کنیم (و با این کار از ایجاد یک ردیف جدید تکراری برای کاربر در دیتابیس، جلوگیری می کنیم).
- اما اگر کاربری با این IP در دیتابیس از قبل وجود نداشت، یعنی او اولین بار است که از صفحات سایت دیدن می کند، برای او یک ردیف جدید ایجاد کرده و به این صورت به نحوی تقریبا هوشمندانه وضعیت کاربر را شناسایی می کنیم، علاوه بر این شما می توانید با درک نحوه کارکرد این شیوه، روش های منحصر به فرد و هوشمندانه تری نیز ابداع کنید، به طور مثال در حالت فعلی حتی اگر کاربر نظری ارسال نکند، یک ردیف در دیتابیس برای IP او در نظر گرفته می شود و واضح است که پس از مدتی ممکن است تعداد این ردیف های temp زیاد شوند، البته این اتفاق به طور کلی مشکل خاصی ایجاد نمی کند، ولی می توان از ایجاد ردیف های اضافه در mysql با تعریف یک سیستم هوشمندتر جلوگیری کرد، به فرض ردیف های temp را پس از چند روز به حالت غیر فعال درآورد (به فرض در ستون status برای ردیف هایی که تاریخ آنها مربوط به چند روز پیش است، مقادیر فرضی trash را در نظر گرفت!) و برنامه را طوری تنظیم کرد که ابتدا از ردیف های غیر فعال استفاده کند و اگر دیگر ردیف غیر فعالی باقی نبود، ردیف های جدید برای کاربران temp بسازد (چیزی شبیه به یک سیستم بازیافت!)، به هر صورت انجام این موضوع تا حدود زیادی به میزان آشنایی شما با برنامه نویسی و به طور خاص برنامه نویسی وب برمی گردد.
- برای نمایش کد امنیتی از یک بلاک با کلاس css فرضی code-box استفاده کرده ایم، با دقت در نحوه عملکرد کد، به راحتی می توانید تغییرات سفارشی و دلخواه خود را در آن ایجاد کنید.

نمایش پیام های ذخیره شده در دیتابیس


پس از ذخیره اطلاعات در دیتابیس، نوبت به فراخوانی و نمایش آنها است، برای این کار نیز به راحتی می توانید از دستور SELECT * FROM در mysql استفاده کنید، به طور مثال:
<?php
//اطلاعات اتصال به دیتابیس
$con = mysql_connect("localhost","root","")
or die(mysql_error());
//نام پایگاه داده
mysql_select_db("contact", $con)
or die(mysql_error());
//نمایش پیام ها
$result = mysql_query("SELECT * FROM form WHERE status != 'temp' LIMIT 15")
or die(mysql_error());
$message_exist = mysql_num_rows($result);
if ($message_exist > 0){
    $loop = 1;
    while ($row = mysql_fetch_array($result)){
        $name = $row['name'];
        $mail = $row['mail'];
        $message = nl2br($row['message']);
        $date = $row['date'];
        $time = $row['time'];
        $ip = $row['userip'];
        $agent = $row['useragent'];
        echo "شماره: $loop - نام: $name - ایمیل: $mail <br /> پیام: $message <br /> تاریخ: $date - زمان: $time آی پی: $ip - سیستم: $agent  <hr />";
        $loop++;
    }
}
else{
    echo "<div class=\"error\">هنوز هیچ پیامی ارسال نشده است!</div>";
}
//پایان ارتباط    
mysql_close($con);
?>
توضیح:
- در کد بالا، ابتدا بررسی می کنیم تا ببینیم آیا پیام ارسال شده ای در دیتابیس موجود است یا خیر، اگر پیامی موجود باشد mysql_num_rows عددی بزرگتر از صفر خواهد بود و با mysql_fetch_array و حلقه while اطلاعات ردیف ها را استخراج کرده و نمایش می دهیم.
- برای جلوگیری از مشکل نمایش خطوط جدید در پیام به صورت یک خطی(یا همان مشکل حذف خطوط  جدید یا line break پیام در textarea)، از تابع nl2br استفاده می کنیم، این کار به این دلیل است که در php برای خطوط و سطرهای جدید، به جای تگ <br> از n\r\ استفاده می شود و لذا هنگام نمایش پیام در صفحات html باید از تابع nl2br استفاده کنیم تا خطوط php به خطوط html تبدیل شوند، در غیر این صورت پیام شما در یک سطر نشان داده می شود و فاصله بین خطوط حذف می شود!
در پایان این مطلب، یک بار دیگر یادآوری می کنیم که این فرم صرفا یک نمونه و الگو است، با آشنایی و تسلط نسبی بر php و mysql، به راحتی می توانید مواردی پیشرفته تر و به صورت سفارشی تعریف نمائید؛ در آموزش های بعدی، به شیوه های ساختن کدهای captcha و تعویض آنها به صورت آژاکسی (ajax) خواهیم پرداخت.
دسته بندی: آموزش کاربردی » MySQL
related مطالب بیشتر:
نحوه رسم چارت و نمودار آماری با PHP و MySQL
صفحه بندی مطالب و محتوا با PHP و MySQL
آموزش ساخت پنل ورود و خروج سایت با PHP و MySQL
ایجاد لینک دانلود مدت دار با PHP و MySQL
آموزش ساخت فرم عضویت در سایت با PHP و MySQL
دیدگاه
more ۸۷ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
زینب
۲۲:۱۸ ۱۳۹۴/۰۶/۱۱
سلام من کدها رو دقیق امتحان کردم دیتابیس و جدول هم ساخته شد اما همش ارور کد امنیتی اشتباه است می دهد لطفا راهنماییم کنید ممنون .
سلام
پی بردن به علت مشکل تنها با بررسی ساختار دیتابیس و نحوه تعریف و استفاده از کدها امکانپذیر است، در صورت تمایل ساختار دیتابیس را به صورت فایل sql به همراه فایل های PHP به آدرس ایمیل ما (موجود در بخش تماس) ارسال کنید تا بررسی گردد.
محسن
۲۲:۴۴ ۱۳۹۴/۰۳/۰۶
سلام دوباره.
توضیحات: من میخوام تو سایت فروشگاهیم قسمت نظرات بذارم واسه هر کالا. از طرفی هر کالا ای دی منحصر بفرد داره.
من دو تا جدول دارم یکی که مربوط به کالاهاست و دیگری مریوط به دریافت و ارسال نظرات. میخوام بین این دو تا جدول ارتباط یک به چند برقرار کنم یعنی هر کالا از طریق یک ای دی یونیک به جدول نظرات متصل بشه. اومدم تو جدول نظرات یک ستون اضافه کردم به نام ای دی. کاربر با کلیک بر روی هر محصول وارد صفحه اون محصول میشه. که همزمان با این کلیک، ای دی محصول به صورت اتوماتیک و هیدن از طریق متد پست می بایست به صفحه محصول ارسال و اونجا دریافت بشه (دلیل استفاده از متغیر گلوبال همینه تا تو همه صفحات و همه جا قابل دریافت باشه) و از طریق دستورات سلکت و ... دقیقا نظرات همون کالا چاپ بشه.
این هدف من بود ولی تا الان موفق نشدم این کارو انجام بدم. به دلیل همون دو تا مشکلی که تو کامنت قبلی نوشتم..
استاد خواهشا راهنمایی کنین شما چه راه حلی دارین واسه این موضوع.
سلام
متغیر گلوبال برای این هدف کاربردی ندارد، گلوبال تنها در هنگام اجرای کدها، scope یا حوزه دسترسی به یک متغیر را تغییر می دهد، برای هدف شما روش متداول در وب انتقال ID به عنوان پارامتر در آدرس URL است، در غیر اینصورت باید نام کالا یا هر چیز منحصر بفرد دیگری را از طریق URL و متد GET انتقال دهید تا منظور کاربر برای کدها قابل تشخیص باشد، اگر بخواهید به صورت مخفی (متد POST) این کار را انجام دهید، باید از یک دکمه submit در فرم و فیلد hidden برای ID استفاده کنید، روش دیگر استفاده از AJAX است که البته در این مورد خیلی مناسب به نظر نمی رسد.
محسن
۲۳:۵۸ ۱۳۹۴/۰۳/۰۴
سلام استاد. حالتون خوبه؟؟
یه سوال:
چرا بعد از ارسال اطلاعات از صفحه ایندکس ، با اینکه متغیر name$ در صفحه contact.php تعریف شده ولی وقتی دستور
echo $name;
یا دستور
echo $_POST['name']
رو میزنم چیزی چاپ نمیشه؟؟؟
سوال دوم:
آیا من میتونم یه متغیر مثلا ای دی رو از یه جدول دیگه بگیرم و در متغیر گلوبال
$GLOBALS[id]
ذخیره کنم و این متغیر گلوبالو توسط فرم و متد پست بفرستم و در صفحات دیگه استفاده کنم؟؟؟
سلام
- چاپ نشدن مقدار متغیر حتما دلیل خاصی دارد، ممکن است نام فیلد input با نام استفاده شده در هنگام دریافت متغیر یکی نباشد، یا متد استفاده شده POST نباشد و یا علت های دیگری که تنها با بررسی فایل ها قابل تشخیص است!
- هرچند مشخص نیست هدفتان از این کار چیست، اما چنین کاری شدنی است، می توانید به صورت داینامیک ID را در یک فیلد input (معمولا به صورت hidden) به عنوان value چاپ کنید و این مقدار را با متد POST یا GET به سرور ارسال و استفاده کنید، البته اشاره نکرده اید که لزوم استفاده از GLOBALS چیست، در حالت معمول نیز این کار شدنی است!
ranjer
۰۰:۵۵ ۱۳۹۳/۱۰/۲۹
با سلام
میخواستم برای کاربران فرم هایی حاوی دکمه های افزاییش و یا کاهش فرم (+ و – ) برای سفارشات درست کنم لطفا من راهنمایی کنید خیلی گشتم ولی به جایی نرسیدم . از دوستان خواهش میکنم اگر کتاب یا نرم افزار و سیستم مدیریت محتوا خاصی که بتونم این فرم ها رو راه اندازی کنم معرفی کنند
سایت زیر نمونه ای از این فرم هست
http://www.samanpl.ir/search/professionalsearch/Index
سلام
تقریبا می توان گفت هیچ آموزشی وجود ندارد که تمام جزئیات مربوط به فرم مد نظر شما را در یک مطلب توضیح داده باشد! در واقع روش یادگیری این موارد به این صورت اصولی نیست! بلکه باید اسکریپت نویسی با JavaScript را از مقدمات فرابگیرید تا بتوانید به کمک قابلیت های آن هر طور که می خواهید امکانات صفحه وب خود را شکل دهید.
حمید
۱۵:۵۵ ۱۳۹۳/۱۰/۲۲
خیلی سایت مشتی ای دارید دمتون گرم
بهاره
۱۸:۳۳ ۱۳۹۳/۱۰/۱۹
سلام
ممنون از آموزش های بسیار عالی شما
من مراحلی که گفتید رو اجرا کردم ولی وقتی فایل index رو اجرا میکنم پیغام
No database selected
را دریافت میکنم
میشه راهنماییم کنید؟
سلام
این به دلیل تفاوت نسخه PHP زمان تهیه آموزش و نسخه PHP ای است که شما استفاده می کنید! در هر صورت قسمت مربوط به انتخاب دیتابیس را به صورت زیر تغییر دهید:
//نام پایگاه داده
mysql_select_db("contact", $con)
محمدعلی وارسته
۱۴:۲۷ ۱۳۹۳/۰۸/۱۳
در بخشی از برنامه خود از یک textarea استفاده کرده ام که قرار است متنی را از پایگاه داده نمایش دهد این کار انجام می گردد لیکن متن به طور کامل نمایش داده نمی شود و بخشی از متن به نمایش در می اید لطفا راهنمایی کنید
پاسخ دقیق به این مشکل تنها با بررسی برنامه ممکن است، اما بر اساس احتمالات موارد زیر را امتحان کنید:
- Type ستون مورد نظر در دیتابیس را بررسی کنید که مطابق با تعداد کاراکترهای مورد نیاز باشد (به فرض از نوع TEXT یا MEDIUMTEXT و... باشد نه VARCHAR)، همچنین از طریق برنامه phpMyAdmin ستون مورد نظر را بررسی و دقت کنید که اطلاعات در دیتابیس به طور کامل وجود داشته باشند.
- سورس HTML خروجی را بررسی کنید و از وجود مشکلات ناخواسته مانند نقص در کدنویسی HTML مطمئن شوید (به فرض ممکن است تگی به درستی بسته نشده باشد).
امین
۲۲:۳۳ ۱۳۹۳/۰۷/۰۲
سلام و با تشکر از پاسختون
مشکل علامت های " و ' برطرف شد ولی منظور تون رو از جواب دوم متوجه نشدم
ولی کد عمل میکنه اما تا وقتی که روی رادیو کلیک نشه عملکردی نداره بخاطر
onclick="kod1();"
تابع مشابه onclick وجود نداره که با نمایش دادن عمل کنه؟
منظور از بخش دوم پاسخ این است که ارجاع به یک تگ در کدهای جاوا اسکریپت باید زمانی رخ دهد که آن تگ در مرورگر پردازش شده باشد، کدهای صفحات وب از ابتدا به انتها پردازش می شوند، لذا زمانی که ابتدا به یک تگ ارجاع می دهید، چون هنوز بارگذاری نشده، خطای null دریافت می کنید، باید ارجاع به تگ بعد از بارگذاری آن باشد، لذا در هنگام استفاده مستقیم از متد document.getElementById باید تگ هدف بارگذاری شده باشد.
برای بخش آخر سوالتان می توانید از window.onload استفاده کنید، مثال:
<script type="text/javascript">
window.onload = function(){
alert('test');
}
</script>
امین
۱۵:۱۹ ۱۳۹۳/۰۷/۰۲
با سلام دوباره
در صفحه html بالای فرم کد زیر رو قرار دادم
<script type="text/javascript">
if(document.getElementById('z').checked==true) {document.getElementById('ps1').style.display='none';}
</script>
و فرم رو درون کد زیر قرار دادم
<div id="ps1" style="display:block">
فرم
</div>
و در صفحه php جهت تست کار در قسمت ایمن سازی فیلد name کد زیر رو قرار دادم تا اگه فیلد نام خالی بود فرم مخفی بشه جهت تست
if ( $name == ''){
echo "<div class='message-error'>لطفا نام خود را وارد کنید ! <input id="z" name="z" onkeydown="kod1();" onclick="kod1();" type="radio" checked="checked" ><label for="tab1">عنوان تب 1</label> </div>";
}
ولی هیچ چیزی نشان نمیده حتی متن هشدار رو
مشکل از کجاست؟
با تشکر
سلام
هر چند بررسی دقیق مشکلتان نیاز به دسترسی به کل برنامه یا حداقل فایل های مربوطه دارد، اما دو اشکال در کدهایی که درج کردید دیده می شود که ممکن است مسئله ناشی از آنها باشد:
- Syntax کدنویسی PHP شما دچار ایراد است، علامت های " و ' در قسمت echo به درستی استفاده نشده و با هم تداخل دارند، برای رفع مشکل توصیه می کنیم از یک ویرایشگر حرفه ای مانند برنامه Adobe Dreamweaver استفاده کنید تا خطاهای Syntax نمایش داده شوند.
- در قسمت جاوا اسکریپت قبل از ارجاع به یک عنصر با document.getElementById، آن تگ باید در HTML DOM بارگذرای شده باشد، لذا قبل از اینکه قسمت مربوط به تگ بارگذاری شود، بررسی checked بودن آن خطای null برمی گرداند، راه حل این است که تکه کد جاوا اسکریپت را بعد از تگ هدف قرار دهید نه قبل از آن.
امین
۲۳:۴۵ ۱۳۹۳/۰۶/۳۰
خیلی ممنون از راهنماییتون
با استفاده از مطلب بخش اجاکس در وبگو سوال دومم برطرف شد
و سوال اول هم با استفاده از فیلد مخفی
فقط یه مشکل که پیش اومده بعد از موفقیت آمیز بودن ارسال ایمیل چون از اجاکس استفاده شده و به صفحه php منتقل نمیشه کاربر هر چقدر روی ارسال کلیک کنید (بعد از بررسی معتبر بودن داده های ارسالی) ایمیل ارسال میشه! باید چکار کرد که بعد از ارسال ایمیل فیلدها پاک بشن؟
با تشکر از وقتی که میگذارید جهت پاسخگویی
می توانید در پاسخ درخواست Ajax به طور مثال یک عبارت مانند Yes یا No برگردانید، سپس در ادامه کدها، پاسخ سرور را بررسی کنید، اگر به فرض Yes بود، با دستورات جاوا اسکریپت و از جمله متد document.getElementById پارامتر value فیلدهای مورد نظر را برابر خالی قرار دهید!
امین
۰۳:۵۰ ۱۳۹۳/۰۶/۲۸
با عرض سلام و خسته نباشید
ببخشید یه سوال
بعد از ساخت فرم تماس به صورت html
مقادیر نظیر نام و اطلاعات دیگه که در فرم html وارد شده بودن بعد از کلیک روی گزینه ارسال به صفحه php منتقل میشه
در صفحه php که به اون منتقل میشه مقادیر به روش مثلا
$mail= $_POST['mail'];
فراخانی میشه
اگه بخوایم بدون دیتابیس این فرم تماس ساخته بشه کد امنیتی که در صفحه html ساخته شده رو چجوری باید به صفحه php منتقل کنیم؟
و یه سوال دیگه اگه نخوایم کاربر بعد از کلیک روی ارسال به صفحه php منتقل بشه یعنی کاربر در همان صفحه html بماند و نتیجه پردازش php درهمان صفحه نمایش داده شود باید چه روشی استفاده کرد؟
با تشکر
سلام
سوال اولتان واضح نیست! انتقال مقادیر فرم از صفحه HTML به PHP ارتباطی به استفاده از دیتابیس ندارد، در واقع تا این مرحله دیتابیس نقشی در کار ندارد و بعد از انتقال پارامترها در PHP است که به دیتابیس متصل می شویم، اگر منظورتان ساخت کد امنیتی بدون دیتابیس است که قاعدتا کار ساده ای نیست و باید موارد زیادی را در نظر بگیرید، مانند کار با سشن یا ذخیره مقادیر در فایل و مدیریت آنها.
در پاسخ به سوال دوم باید از Ajax استفاده کنید که آموزش های جداگانه ای دارد.
ماه بیگم
۱۶:۳۶ ۱۳۹۳/۰۶/۰۲
سلام
خدا قوت
من میخوام سایتم رو به گونه ای طراحی کنم که کاربر۱ بتونه از پنل خودش به کاربر۲ مسیج بفرسته.
کاربر ۲ وقتی وارد صفحه اش شد ببینه که مسیج جدید داره و بتونه از همون قسمتی که مسیج رو باز میکنه ، پاسخ بده.
و همین اتفاق برای همه کاربران سایت بیفته.
ممکنه بفرمایید مراحل این کار چی هست.
و من حتی میخوام به انگلیسی گوگل کنم ، نمیدونم چی بنویسم برای سرچ.
ممنون میشم اگر توضیح بفرمایید.
سلام
توضیح چنین موضوعی در اینترنت وجود ندارد!
باید از قبل با نحوه تعریف ساختار برنامه های وب آشنا باشید، به عبارتی قبلا چند برنامه کوچکتر نوشته باشید تا دقیقا چند و چون طراحی این ساختار دستتان باشد، نمی توانیم بیش از این در این رابطه توضیح دهیم چون بحث مختصری نیست، صرفا در حد راهنمایی جهت شروع کار باید جدول کاربرانی با ID یکتا داشته باشید، جدول پیام ها، ستون ارسال کننده پیام، گیرنده پیام، ستون پیام، ستون پاسخ و...
علی
۲۳:۰۱ ۱۳۹۳/۰۵/۲۹
میشه سوال دوم رو دوباره توضیح بدیدن متوجه نشدم گفتید یه فیلد از نوع hidden قرار بدم واسش ایدی و نام انتخاب نکنم؟ اگه انتخاب کنم به چه اسمی باشند و دستور شرطی را چه بنویسم؟ و در کجای کدها قرار بدم؟
یک input از نوع hidden با name دلخواه قرار دهید، در قسمت value به فرض مقدار 1 را تنظیم کنید، سپس در سرور با متد POST مقدار input را به یک متغیر اختصاص دهید، در این حالت هر زمان که مقدار متغیر برابر 1 باشد، یعنی کاربر فرم را ارسال کرده و لذا متناسب با آن باید کدهای خاصی اجرا شوند، دستور شرطی می تواند به صورت زیر باشد:
<?php
if(isset($hidden_input) && $hidden_input == 1){
//کدهایی که باید بعد از ارسال فرم اجرا شوند
}
?>
محل درج کد بستگی به هدف شما دارد، در واقع باید درک درستی از برنامه ای که طراحی می کنید داشته باشید، در غیر این صورت لازم است که مباحث مقدماتی را مرور نمایید!
علی
۰۲:۳۷ ۱۳۹۳/۰۵/۲۹
سلام سه تا سوال داشتم یکی اینکه در این کد
if ($check == 1 && $name == ''){
echo "<div class=\"error\">لطفا نام خود را وارد کنید!</div>";
$error = 1;
}
کارایی کد
$error = 1; 
چیه
سوال دوم : من هر دو فرم را در یک فرم ترکیب کردم که یه مشکل دارد هنگامی که فرم را پر میکنم و ارسال را میزنم در حالی که جواب کد امنتی را صحیح وارد کردم میگوید جواب کد امنیتی اشتباست کدها را به این صورت گذاشتم بررسی کنید
حذف شد!
سوال سوم: اگه بخوایم کد اعتبار سنجی کد امنیتی رو در کنار فیلد کد امنیتی قرار بدیم تا ارورش در کنار فیلدش نشان داده شود , موقعی که فرم رو باز میکنیم از قبل پیغام اینکه کد امنیتی اشتباه است را نشان می دهد در حالی که فرم را هنوز ارسال نکردیم .
سوال چهارم : میشه یه مثال در مورد اعتبار سنجی البته به همین شیوه ای که در اینجا به کار بردید و قبل از ذخیره شدن در دیتابیس قبلش کل فرم چک می شود بزنید مثلا در مورد فیلد ایمیل که قبلش پیغام بده اولا فیلد الزامیه بعد اگه فیلد رو پر کرد و اگر اشتباه پر کرد پیغام ایمیل رو به صورت صحیح بنویسد بدهد
سلام
- همان طور که مشخص است، این متغیر صرفا برای بررسی بروز خطا در دستورات شرطی تعیین شده کاربرد دارد، یعنی زمانی که یک شرط برقرار باشد، مقدار متغیر 1 می شود و در ادامه کدها می توان پی برد که پیش از این خطایی رخ داده!
- با قرار دادن دستور به روزرسانی کد امنیتی در ابتدای صفحه، هر بار که فرم را ارسال می کنید ابتدا یک بار فیلد کد امنیتی با مقدار جدید به روز می شود، سپس مقدار ارسال شده با مقدار جدید تطبیق داده می شود! در نتیجه جواب همواره اشتباه است، مگر در شرایطی که آی پی برای اولین بار در دیتابیس ثبت شود.
- می توانید یک فیلد از توع hidden در فرم داشته باشید و از آن برای پی بردن به ارسال شدن یا نشدن فرم استفاده کنید (زمانی که مقدار فیلد در دسترس باشد، فرم ارسال شده است)، در این شرایط یک دستور شرطی if داشته باشید که اگر فرم ارسال شده بود، خروجی مربوط به خطا اجرا شود.
- برای ایمیل می توانید از تابع آماده زیر استفاده کنید:
if (filter_var($adresse, FILTER_VALIDATE_EMAIL)) {
// valid
} else {
// not valid
}
۲۳:۵۴ ۱۳۹۳/۰۵/۰۴
استاد سلام میخواستم بدونم که برای هر صفحه از سایتم بخوام جدا نظرات نشون داده بشه باید چیکار کنم برای مثال کل نظرات داده شده در سایت شما به کنار اما برای مثال در این صفحه فقط نظرات مربوط به همان صفحه نمایش داده میشود آیا باید در تشکیل دیتابیس کاری کرد و یا در صفحه نمایش و یا ارسال به دیتابیس کاری کرد معذرت میخوام از توضیحات زیاد یه چیزی مثل سایت شما
لازم به ذکر است سایت شما عالی است و این کد خیلی خوب کار می کند.
با تشکر اوس
سلام
در واقع در همه موارد باید چنین حالتی لحاظ شود! یک برنامه کاربردی مجموعه ای از توابع و دستورات به هم پیوسته و مرتبط در راستای یک هدف مشخص است، به عبارت ساده تر به فرض باید هر مطلب یک شماره ID یکتا داشته باشد، هر نظری که ارسال می شود، ستونی برای مشخص شدن ارتباط نظر با مطلب مورد نظر (از طریق ID) داشته باشد، در هنگام نمایش یک مطلب، نظرات از جدول مربوط به نظرات، با توجه به ستون ID مطلب SELECT شوند و... در کل باید یک ساختار منسجم تعریف کنید که این به داشتن حداقل آشنایی با برنامه نویسی PHP، کار با MySQL و تجربه نوشتن برنامه های کوچک نیاز دارد.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
7 × 4
20 × 20
=