منبع اصلی نوشتار زیر در این لینک قرار دارد

Ajax – jQuery – PHP ترکیب دوست داشتنی

یه چند وقتی هست میخوام یه مطلبی درباره آژاکس بنویسم البته با کمک jQuery . قبل از اینکه اینکارو انجام بدم، چند تا مساله هست که میخوام توضیح بدم قبل از شروع.

اول اینکه تو این مطلب میخوام از خود هسته jQuery استفاده کنم نه از افزونه ها
دوم اینکه میخوام طوری این کد رو بنویسم که حتی اگه شخصی جاوا اسکریپت رو هم غیر فعال کرد بدون مشکل کار کنه، و فقط دیگه آژاکس نباشه.

دلیل اولی معلومه، نمیخوام کد بیخودی شلوغ بشه، ولی در حالت عادی افزونه ها خیلی مفیدن. اما دومی وسواس منه. اینکه بدون آژاکس همه چی درست باشه. اما چرا؟ علتش اینه که مهمترین مشتری های یک سایت! معمولا روباتهای موتورهای جستجوگر هستن، و اونا کاری با جاوا اسکریپت ندارن. اگه راستشو بخواید این راهنمای کوچک که من تو این پست و دو سه تا پست بعدی مینویسم، بیشتر از اینکه در مورد آژاکس باشه درباره اینه که چطور میشه همزمان یه صفحه با آژاکس و بی آژاکس کار کنه. البته این مثال به خصوص هیچ نیازی نداره به این قابلیت ولی میتونه راهنمای خوبی باشه برای افرادی که دوست دارن این رو امتحان کنن.

0- پیشنیازها!

آشنایی با jQuery و سیستم انتخاب عناصر اون ( Selector ) و اصولا آشنایی با روش زنجیری فراخوانی توابع، آشنایی با مدیریت رویدادها با jQuery

آشنایی با PHP در حدی که بتونید کد رو دنبال کنید.

1- هدف

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

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

2-طرف سرور

در حالت عادی یه فرم انتهای صفحه هست به این صورت :

<?php if ($mode=='add') : ?>
<form action="<?=$_SERVER['PHP_SELF'];?>" method="post" id="addform">
	<label for "data">Your new data :<input type="text" name="data"/></label>
	<input type="hidden" name="oper" value="add" />
	<input type="submit" name="submit" value="Add" />
</form>
<?php else : ?>

این همون فرم مورد نظر منه. قسمت پردازش این فرم هم بالاتر، تو ابتدای کد هست :

	//Check for add request :
	if (isset($_POST['oper']) && $_POST['oper']=='add'){
		$data=$_POST['data'];
		//Check point : Check user input here! its so important, but not for this example!
		//We just check for reject empty value
		if (!empty($data))
			if ($affected=add($data)) {
				$msg="OK, Done";
				$class="message";
			}else{
				$msg="OOps! more than 100 row! just for fun!";
				$class="errmessage";
			}
		else{
			$msg="Data is invalid (empty).";
			$class="errmessage";
		}
	}
	}

البته من یه کم لقمه رو دور سرم چرخوندم، مثلا در حالت عادی نیازی به افزودن یه فیلد اضافه به فرم (در این مثال فیلد oper ) ، نیست. ولی چون می خوام بعدا دچار مشکل نشم این کارو از همین الان انجام میدم. تابع add توی شبیه ساز دیتابیس خیلی ساده شبیه INSERT عمل میکنه، موفق بشه آخرین id اضافه شده رو برمیگردونه، نشه هم false (البته نشدن که نداره، من عمدا یه شرط الکی گذاشتم که مثلا بعد از 100 دیگه هیچی اضافه نشه) کلا همین. توی کد هم فقط بررسی شده که مبادا کاربر اطلاعات خال بفرستد، وگرنه در مثال واقعی باید بررسی های بیشتری بشه که بسته به نیاز میتونه متفاوت باشه مثلا اینکه اگه قراره که اطلاعات توی دیتابیس قرارداده بشه حتما عمل escape انجام بشه و ….

اینجا یه پیغام هست که به کاربر نشون داده میشه، موفقیت آمیز بوده نبوده و … یه کلاس هست که واسه نشون دادن پیغام به کاربر از اون کلاس توی CSS استفاده میشه (در مورد مثال من دو تا کلاس هست message برای پیغامهای موفقیت آمیز و errmessage برای پیغامهای خطا) و در نهایت یه متغیر affected که در حالتی که آژاکس نباشه اصلا به کار نمیاد و بود و نبودش بی معنیه. فقط تو این کد از این متغیر برای زمانی استفاده میشه که آژاکس باشه . این متغیر آخرین id رو نشون میده که در آخرین عمل تحت تاثیر قرار گرفته، مقدارش یه عدد صحیح مثبت یا -1 یا false خواهد بود که دو تای آخری نشانگر خطاست.

خوب اولین کار اینه که کد مورد نیاز رو اضافه کنیم. اول طرف PHP . باید یه جوری بفهمیم که این درخواست (Request ) فعلی به صورت معمولی بوده یا اینکه نه، این درخواست از طریق Ajax انجام شده.

jQuery و تقریبا تمام FrameWork های دیگه مثل mootools وقتی یه درخواست آژاکس میفرستن، یه سرآمد به درخواست اضافه میکنن به صورت X-Requested-With که مقدارش حاوی فرستنده آژاکس هست، البته مقدارش برای ما مهم نیست، فقط اینکه باشه کافیه که بفهمیم این درخواست با آژاکس فرستاده شده. تو PHP کلیه این متغییر ها که با یه درخواست فرستاده میشن تو $_SERVER قرار میگیرن، با یه HTTP_ اولشون و به صورت تماما حروف بزرگ، پس کافیه اینطوری این رو بررسی کنیم :

$isAjax=isset($_SERVER['HTTP_X_REQUESTED_WITH']);

الان متغیر isAjax نشون میده که درخواست از طریق آژاکس بوده یا نه. چرا این مهمه؟ جواب یه درخواست آژاکس باید ساده باشه نه کل صفحه. در حقیقت به جای اینکه دوباره کل صفحه دوباره ایجاد بشه و پس فرستاده بشه، کافیه که اطلاعات مورد نیاز برای به روز رسانی صفحه فرستاده بشه. برای فرستادن این اطلاعات میشه از هر روشی استفاده کرد، ولی من بدون هیچ شکی از json استفاده میکنم، چون jQuery خیلی ساده اونو پردازش میکنه، از طرفی توی PHP دو تا تابع هست که از PHP 5.2 به بعد دیگه جزیی از هسته PHP هستن، این توابع ، عبارتند از json_encode و json_decode خیلی ساده، اولی یه آرایه میگیره اونو به فرمت json برمیگردونه، و دومی برعکس رشته مربوط به json رو میگیره، و آرایه معادلشو میده. توی درخواستهای آژاکسی، جواب یه چیزی هست شبیه به این :

{"class":"message","msg":"OK, Done","affected":4}

هر فیلد دقیقا همون متغیرهایی هستن که بالاتر توضیح دادم. برای اینکار آخر بلوک کد، قبل از هر خروجی دیگه ای، این کد رو اضافه کردم :

	if ($isAjax) {
		
		$data=array('class'=>$class,'msg'=>$msg,'affected'=>$affected);
		echo json_encode($data); //Send data in json format
		exit();		//Finish the script, in ajax mode it's critical, just result data in 
					//proper format, not anything else
	}

3- طرف کلاینت

همین و کل تغییری که باید توی کد PHP بدید تمومه. باقیش همونه که بود. فقط به کد HTML خروجی یه کم باید کد جاوا اسکریپت اضافه کنید. اول از همه یادتون نره که jQuery رو اضافه کنید :

<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>

بعد هم کافیه کد مورد نظرتونو تو یه بلوک script بنویسید، کد کلا اینه :

<script type="text/javascript">
//<![CDATA[
	$(function() {
		//1- Change add form 
		$('#addform').submit(function(){
			//1-1 :Get add form target
			var target=$(this).attr('action');
			//1-2 : collect data, in very simple way, you can use plugins or better way to do this, 
			// But I want this to be simple.
			var postData=new Object();
			postData.oper='add';
			postData.data=$('#addform input[name=data]').attr('value');
			//1-3 : Post data to server using post method
			$.post(
				target, // The form target (action)
				postData, //The form data 
				function(data){ // callback function , fired on success, with data recived from server
					//Since we use json, data is an object with json data as field => data
					//The data format for this example is very simple, class and message and code, (the id 
					//when insert done and -1 when fail) . no more
					//1-4 : show message
					$("#msg").removeClass('message')  //Remove any old class, just in case
							 .removeClass('errmessage')
							 .addClass(data.class) //Add new class
							 .html(data.msg);	//change message(innerHTML)
					//1-5 : add new data to list (html table) if insert was a success.
					if(data.affected>-1){
						var id=data.affected;
						var delLink="<a href='<?=$_SERVER['PHP_SELF'];?>?del="+id+"' class='dellink' rel='row_"+id+"'>Del</a>";
						var editLink="<a href='<?=$_SERVER['PHP_SELF'];?>?edit="+id+"' class='editlink' rel='row_"+id+"'>Edit</a>";
						//Create new table row with new data, see the table rows, this is just a duplicate of that.
						$("<tr id='row_"+id+"'><td>"+id+"</td><td>"+postData.data+"</td><td>"+delLink+"</td><td>"+
							editLink+"</td></tr>")
							.appendTo('#dataList tbody'); //Append it to end of table
					}
				},
				"json" //Data type, json is simplest , since json extension in php is very simple and good :),
					   // But you can use other format like xml (then you should pass data in php in xml format) or
					   // simply use text, then data is a string not object
			);
			//make sure to return false to override default send.
			return false;
		})
	});
//]]>
</script>

حالا توضیح تکه به تکه، اگه با jQuery آشنایی ندارید، چگونگی انتخاب عناصر رو نمیدونید بالاتر هم گفتم قبلش برید و در این مورد مطالعه کنید :)

اولین کار اینه که به جای اینکه فرم از طریق روش عادی، ارسال بشه ما عمل submit رو مدیریت کنیم و اجازه این کارو به مرورگر ندیم. برای اینکار تابع submit باید حتما false برگردونه و گرنه اطلاعات باز هم از طریق متد عادی فرستاده میشه، چیزی که ما نمیخوایم. پس یه return false به انتهای این تابع که خروجی تابع هم هست اضافه میکنیم.

خیلی ها میان و action فرم رو مثلا میدن # ، در این صورت فرم اگه جاوا اسکریپت نباشه اصلا ارسال نمیشه، چیزی که من میخوام اینطور نباشه.

گام اول اینه که action فرم رو بگیریم، چون میخوایم ما هم اطلاعات رو به همون جا پست کنیم. (1-1 )

var target=$(this).attr('action');

حالا وقتشه که اطلاعات فرم رو جمع و جور کنیم. اینجا شما میتونید از افزونه هایی که هست استفاده کنید و یا اینکه یه سری روتین های تعیین اعتبار رو هم اضافه کنید مثلا اینکه مطمئن شید فرم کاملا پر شده و از این حرفا، ولی روش من یعنی ساده ترین روش :)

تک تک اطلاعات رو میگیریم و به یه شی جاوا اسکریپت اضافه میکنیم :

//1-2 : collect data, in very simple way, you can use plugins or better way to do this, 
// But I want this to be simple.
var postData=new Object();
postData.oper='add';
postData.data=$('#addform input[name=data]').attr('value');

همون oper که بالا هم در موردش توضیح دادیم، اینبار add هست (معلومه دیگه! ما میخوایم فرم add رو شبیه سازی کنیم) حالا متن داخل فیلد data رو هم میخونیم و به شی اضافه میکنیم.

گام بعدی هم، ارسال اطلاعاته، از طریق متد post کلاس jQuery .

			$.post(
				target, // The form target (action)
				postData, //The form data 
				function(data){ // callback function , fired on success, with data recived from server
					//Since we use json, data is an object with json data as field => data
					//The data format for this example is very simple, class and message and code, (the id 
					//when insert done and -1 when fail) . no more
					//1-4 : show message
					$("#msg").removeClass('message')  //Remove any old class, just in case
							 .removeClass('errmessage')
							 .addClass(data.class) //Add new class
							 .html(data.msg);	//change message(innerHTML)
					//1-5 : add new data to list (html table) if insert was a success.
					if(data.affected>-1){
						var id=data.affected;
						var delLink="<a href='<?=$_SERVER['PHP_SELF'];?>?del="+id+"' class='dellink' rel='row_"+id+"'>Del</a>";
						var editLink="<a href='<?=$_SERVER['PHP_SELF'];?>?edit="+id+"' class='editlink' rel='row_"+id+"'>Edit</a>";
						//Create new table row with new data, see the table rows, this is just a duplicate of that.
						$("<tr id='row_"+id+"'><td>"+id+"</td><td>"+postData.data+"</td><td>"+delLink+"</td><td>"+
							editLink+"</td></tr>")
							.appendTo('#dataList tbody'); //Append it to end of table
					}
				},
				"json" //Data type, json is simplest , since json extension in php is very simple and good :),
					   // But you can use other format like xml (then you should pass data in php in xml format) or
					   // simply use text, then data is a string not object
			);

آرگومان اول صفحه مقصده، همون action فرم، آرگومان دوم اطلاعات فرمه که ما گذاشتیمش توی شی postData سومی هم تابعی هست که وقتی عمل موفقیت آمیز باشه فراخوانی میشه، (توضیح بیشتر چند خط پایینتر :D ) و در نهایت آرگومان آخر مشخص میکنه فرمت اطلاعات پاسخ چی باشه. همونطور که گفتم تو این مثال (و من تنبل تقریبا همیشه ) از json استفاده میکنیم.

اما تابعی که تو لیست آرگومانها هست، آرگومان سوم. این تابع وقتی فراخوانی میشه که اطلاعات با موفقیت پست شده باشن، و جواب هم توی متغییر data گذاشته میشه و به عنوان آرگومان این تابع در دسترس هست. اینجا، اطلاعات بازگشتی به صورت json بود، خود jQuery این اطلاعات رو پردازش میکنه و به صورت فیلد به شی data اضافه میکنه، در بعضی موارد (مثلا اگه اطلاعات بازگشتی متنی باشه ) این data به صورت string هست نه object تو این مثال و کلا همیشه برای این فرمت json آرگومان object هست.

function(data){ // callback function , fired on success, with data recived from server
	//Since we use json, data is an object with json data as field => data
	//The data format for this example is very simple, class and message and code, (the id 
	//when insert done and -1 when fail) . no more
	//1-4 : show message
	$("#msg").removeClass('message')  //Remove any old class, just in case
			 .removeClass('errmessage')
			 .addClass(data.class) //Add new class
			 .html(data.msg);	//change message(innerHTML)
	//1-5 : add new data to list (html table) if insert was a success.
	if(data.affected>-1){
		var id=data.affected;
		var delLink="<a href='<?=$_SERVER['PHP_SELF'];?>?del="+id+"' class='dellink' rel='row_"+id+"'>Del</a>";
		var editLink="<a href='<?=$_SERVER['PHP_SELF'];?>?edit="+id+"' class='editlink' rel='row_"+id+"'>Edit</a>";
		//Create new table row with new data, see the table rows, this is just a duplicate of that.
		$("<tr id='row_"+id+"'><td>"+id+"</td><td>"+postData.data+"</td><td>"+delLink+"</td><td>"+
			editLink+"</td></tr>")
			.appendTo('#dataList tbody'); //Append it to end of table
	}
}

اول پیغام رو بدون کم و کاست نشون میدیم. قبلا یه div واسش توی کد در نظر گرفته بودیم، با ID=msg . اونو انتخاب میکنیم، هم کلاس message و هم errmessage رو ازش حذف میکنیم، (که میتونه از آخرین پیغام قبلی باقی مونده باشه) حالا کلاس جدید رو از متغییر data میخونیم و به این div اضافه میکنیم، بعد هم متن داخل این div رو با متن جواب عوض میکنیم.

گام دوم اینه که تغییر داده شده رو اضافه کنیم به انتهای لیست. میتونید اطلاعات اضافه شده رو هم از سرور به این پاسخ اضافه کنید ولی ما فقط id اضافه شده رو میخوایم، و متن رو هم میتونیم از داخل همون فیلد بخونیم (البته این چندان جالب نیست، مثلا اگه طرف بعد از ارسال ولی قبل از رسیدن جواب متنو عوض کرده باشه که اونم کلی راه حل داره :) ) حالا اگه جواب مثبت باشه (مبارکه) این متنو به انتهای لیست اضافه میکنیم.

اول دو تا لینک حذف و ویرایش رو بدون کم و کاست ایجاد میکنیم (دقیقا شبیه همین لینک ها توی PHP ) دست آخر هم یه سطر جدول رو ایجاد میکنیم و با متد appendTo به انتهای جدول اضافه میکنیم (قسمت tbody ) همین! حالا شما یک صفحه آژاکس دارید که هم بدون آژاکس کار میکنه هم با آژاکس. میتونید نتیجه رو اینجا ببینید.

قسمتهای بعدی (که فکر میکنم دست کم 3 قسمت دیگه باشه) به زودی اضافه میکنم، سعی میکنم دست کم هر هفته یه قسمت رو آماده کنم، ولی خدا رو چه دیدی ! شاید زودتر شد یا شاید دیرتر!

اینم لینک دانلود



برچسب ها : , , , , ,

به سیاره لینوکس امتیاز دهید

به اين صفحه امتياز دهيد