PDA

View Full Version : کمک کمک! insert میکنه ولی میگه نکردم!!



memoli
شنبه 26 اردیبهشت 1388, 20:26 عصر
<?php

$nam=$_POST['nam'];
$pas=$_POST['pas'];
$year=$_POST['year'];
$month=$_POST['month'];
$day=$_POST['day'];
$sex=$_POST['sex'];
$mar=$_POST['mar'];
$tel=$_POST['tel'];
$mob=$_POST['mob'];
$mail=$_POST['mail'];
$zip=$_POST['zip'];
$adrs=$_POST['adrs'];


$dt=($year=='0' || $month=='00' || $day=='00')? 'null' : ("'".$year.'-'.$month.'-'.$day."'");
$sx=($sex=='') ? 'null' : "'$sex'";
$mr=($mar=='') ? 'null' : "'$mar'";
$ad=($adrs=='') ? 'null' : "'$adrs'";
$zp=($zip=='') ? 'null' : "'$zip'";
$tl=($tel=='') ? 'null' : "'$tel'";
$mb=($mob=='') ? 'null' : "'$mob'";
$query2= "insert into member set id='$nam' , pas='$pas' , age=$dt , sex=$sx , married=$mr , membership='".date('Y-m-d')."' , email='$mail' , address=$ad , zipcode=$zp , phone=$tl , mobile=$mb , inventory=0";
echo "$query2<br>";


$db=mysql_connect('localhost','root','');
if(!$db)
{
echo " خطا: ارتباط با پایگاه داده برقرار نشد ";
exit();
}
if( !mysql_select_db("travel_agency",$db) )
{
echo " خطا: بانک مورد نظر انتخاب نشد ";
exit();
}

mysql_query("SET NAMES 'utf8'", $db);
//$query0="insert into member set id='yyyoo9osss' , pas='555555' , age=null , sex=null , married=null , membership='2009-05-16' , email='u@g' , address='Ù†' , zipcode=null , phone=null , mobile=null , inventory=0";

$result2=mysql_query($query2,$db);
if($result2)
{
echo "ok";
echo mysql_affected_rows();
}
else
{
echo "fail";
//mysql_affected_rows();
}
mysql_close($db);

?>



وقتی اجرا میشه پیغام میده "fail" یعنی باید عمل insert نکرده باشه ولی میرم می بینم تو جدول رکورد مرد نظر اضاف شده!! در هیچ حالتی پیغام مربوط به بلوک if را چاپ نمیکنه ولی همیشه هم insert میکنه! و در ضمن چک کردم mysql_affected_rows را برابر -1 میده در حالی که insert شده!

حالا اگه به query2 یه رشته ساده بذارم مثل :

$query0="insert into member set id='yyyoo9osss' , pas='555555' , age=null , sex=null , married=null , membership='2009-05-16' , email='u@g' , address='Ù†' , zipcode=null , phone=null , mobile=null , inventory=0";همه چیز درس میشه!!! عجب!! پس query اشکال داره!

امیـرحسین
شنبه 26 اردیبهشت 1388, 21:25 عصر
بعد از این خط:

$result2=mysql_query($query2,$db);
این کد رو اضافه کنید:

echo "<b>mysql_info:</b>";
echo "<pre>";
var_dump(mysql_info());
echo "</pre>";

echo "<b>result2 value:</b>";
echo "<pre>";
var_dump($result2);
echo "</pre>";

die(mysql_error());

خروجی رو کامل تو تاپیک بذارید.

درضمن این تابع رو فراموش نکنید: mysql_real_escape_string (http://ir.php.net/manual/en/function.mysql-real-escape-string.php)

memoli
شنبه 26 اردیبهشت 1388, 22:36 عصر
اینم خروجی!

insert into member set id='maryam' , pas='123456' , age='1990-01-03' , sex='m' , married='s' , membership='2009-05-16' , email='ssss@sss' , address='jgkjfdhgkdf' , zipcode=null , phone=null , mobile=null , inventory=0
mysql_info:bool(false)
result2 value:bool(false)
Duplicate entry 'maryam' for key 1

memoli
شنبه 26 اردیبهشت 1388, 22:39 عصر
درضمن این تابع رو فراموش نکنید: mysql_real_escape_string (http://ir.php.net/manual/en/function.mysql-real-escape-string.php)

چی کار میکنه؟

امیـرحسین
یک شنبه 27 اردیبهشت 1388, 00:40 صبح
توابع escape برای جلوگیری از حملات sql injection (https://www.ircert.cc/articles/show.mno?id=655&lang=fa&subsite=37&product=-1) هستند.



ستون id ظاهرا بصورت unique ایندکس شده و مقداری با نام maryam داره و کوئری که در پیغام خطا نمایش دادید، بخاطر تکراری بودن این مقدار هست.
حدس می زنم که شما ستونی برای اسامی ندارید و (یا دارید و اشتباها) اسامی رو در ستون id میریزید.

به نظر میاد دارید یه اسکریپت ثبت نام می نویسید، پیشنهاد می کنم:

یک ستون مجزا برای نام (username) اختصاص بدید و ستون id رو بصورت auto increment داشته باشید (می تونه مفید باشه).
پسورد رو کد کنید. مثلا با تابع md5 (http://ir.php.net/manual/en/function.md5.php) (اگر کسی به اطلاعات دیتابیس دسترسی پیدا کرد نتونه پسورد کاربران رو استفاده کنه).
تاریخ رو بهتره که بصورت برچسب زمان (timestamp) ذخیره کنید. (اینجوری می تونید روی تاریخ مانور خیلی بهتری بدید) و هر زمان نیاز داشتید توسط تابع date (http://ir.php.net/manual/en/function.date.php)، این مقدار رو تبدیل کنید. می تونید از مبدلهای تاریخ برای تبدیل اون به شمسی هم استفاده کنید.
همه مقادیری که از کاربر میگیرید و میخواید در SQL وارد کنید رو escape کنید. همیشه همیشه!

yaqubian
یک شنبه 27 اردیبهشت 1388, 08:31 صبح
دوست عزیز امیرحسین
دستور mysql_real_escape_string مشکل امنیتی داره. قبلا در موردش بحث کردم.
موفق باشید

memoli
یک شنبه 27 اردیبهشت 1388, 09:08 صبح
ستون id ظاهرا بصورت unique ایندکس شده و مقداری با نام maryam داره

من قبل از اجرای این صفحه چک کردم همچین مقداری نداشت . اصلن همه رکوردها را قبلش پاک کرده بودم و فقط دو تا رکورد بود.... مطمئنم که مقدار تکراری نبوده.


یک ستون مجزا برای نام (username) اختصاص بدید و ستون id رو بصورت auto increment داشته باشید (می تونه مفید باشه).

اینم از تعریف ساختار db:

CREATE TABLE member (
id VARCHAR(20) NOT NULL,
pas VARCHAR(30) NOT NULL,
age DATE NULL,
sex CHAR(1) NULL,
married CHAR(1) NULL,
membership DATE NULL,
email VARCHAR(50) NOT NULL,
address VARCHAR(200) NULL,
zipcode VARCHAR(10) NULL,
phone VARCHAR(15) NULL,
mobile CHAR(11) NULL,
inventory INT NOT NULL,
type CHAR(1) NULL,
PRIMARY KEY (id)) TYPE=INNODB;

اصولی که شما گفتین کاملا صحیح و حرفه ای!
ولی دیدید انگار داره قبلش insert میکنه و وقتی میرسه به insert میگه تکراریه! در حالی که من به طرق مختلف چک کردم مقدار جدیده!

memoli
یک شنبه 27 اردیبهشت 1388, 09:12 صبح
همه مقادیری که از کاربر میگیرید و میخواید در SQL وارد کنید رو escape کنید. همیشه همیشه!

این کار را توابع addslashes() , stripslashes در یک مقیاسی انجام می دن؟!نه؟

memoli
یک شنبه 27 اردیبهشت 1388, 09:17 صبح
با تشکر فراوان از اینکه دارید وقت می ذارید برا این برنامه حالا اگه شما جای من بودید چی کار می کردید؟
پیگیری می کردید تا بفهمید مشکل insert از کجاس؟
یا ساختار db را تغییر می دادین؟ ستون id در 7 -8 تا جدول دیگه کلید خارجیه!!!

امیـرحسین
یک شنبه 27 اردیبهشت 1388, 13:35 عصر
ستون id در 7 -8 تا جدول دیگه کلید خارجیه!!!خودتون گفتید مشکلش رو....





دوست عزیز امیرحسین
دستور mysql_real_escape_string مشکل امنیتی داره. قبلا در موردش بحث کردم.
موفق باشید
من گفتم توابع escape رو فراموش نکنید. دوستمون پرسیدند چی هست. من چی جواب بدم؟ بگم هیس، مشکل امنیتی داره؟! :چشمک:


این دو تا تابعی هست که من با سر هم کردن چند تا تابع از چند جا، واسه یه جایی، یه کلاسی آماده کرده بودم:

/**
* Escape strings to use in SQL commands.
*
* @param string $str String to escape.
* @param resource $connection Connection resource.
* @return string Escaped string.
*/
function str_escape($str, $connection=null)
{
if(get_magic_quotes_gpc())
$str = stripslashes($str);

if(function_exists('mysql_real_escape_string') && $connection)
return mysql_real_escape_string($str, $connection);
else
return mysql_escape_string($str);
}


/**
* Escape array values for SQL commands.
*
* @desc Useful for escaping $_GET and $_POST vars.
* @param array $array Array to escape.
* @param boolean $escapeKeys Escape array KEYs.
* @param resource $connection Connection resource.
* @return array Escaped array.
*/
function arr_escape($array, $escapeKeys=false, $connection=null)
{
$output = array();
foreach($array as $key => $val)
{
$key = (is_string($key) && $escapeKeys) ? str_escape($key) : $key;
$val= is_string($val) ? str_escape($val) : $val;

if(is_array($val))
$val = arr_escape($val, $escapeKeys, $connection);

$output[$key] = $val;
}
return $output;
}

memoli
سه شنبه 29 اردیبهشت 1388, 00:35 صبح
سلام.
با تشکر


نقل قول:
نوشته شده توسط memoli http://barnamenevis.org/forum/images/buttons/viewpost.gif (http://barnamenevis.org/forum/showthread.php?p=723722#post723722)
ستون id در 7 -8 تا جدول دیگه کلید خارجیه!!!

خودتون گفتید مشکلش رو....


یعنی میگید چون تو برخی جداول دیگه کلید خارجی هستش مشکل درست می کنه؟
خوب کلید خارجی که می تونه null باشه!

memoli
سه شنبه 29 اردیبهشت 1388, 00:54 صبح
فکر نکنم مشکل از کلید خارجی باشه !
چون اگه دستور insert را با یه رشته ساده بنویسیم راحت insert میکنه!


$query0="insert into member set id='yyyoo9osss' , pas='555555' , age=null , sex=null , married=null , membership='2009-05-16' , email='u@g' , address='Ù†' , zipcode=null , phone=null , mobile=null , inventory=0";