الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

النمط المفرد Singleton Pattern وتطبيقة لإنشاء إتصال بقاعدة البيانات

بدأه ahmedsaoud31 في 28 سبتمبر 2012 · 18 رد · 1,897 مشاهدة · في منتدى تطوير المواقع بـ PHP
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاتة

اليوم بإذن الله سنتحدث عن نمط من أنماط التصميم وهو النمط المفرد Singleton Pattern .

- ما هو الـSingleton Pattern ؟

- إن أردت أن تفهم ماذا تعنى هذه الكلمة أكمل معنا الشرح التالى :

أولاً : كنا قد تحدثنا عن ملخص سريع عن البرمجة الكائنية فى هذا الموضوع , الآن نريد عمل دالة تقوم بإنشاء كائن من نفس الفئة كالتالى :

<?php
class singleton {


	// دالة إنشاء كائن من نفس الفئة الحالية
	public function getObj(){
        	echo "make object<br>";
        	return new singleton();
	}

	// دالة إختبار
	public function test(){
    	echo "ahmed<br>";
	}

} // نهاية الفئة

$obj = new singleton();
$obj2 = $obj->getObj();
$obj3 = $obj->getObj();
$obj4 = $obj->getObj();

// test
echo "-------------<br>";
$obj->test();
$obj2->test();
$obj3->test();
$obj4->test();

?>

الآن ستسألنى وما الفائده من هذه الدالة؟ فأنا أستطيع عمل كائن مباشراً بدون إستخدام هذه الدالة , فقط أردت إظهار كلمة make object فى كل مره يتم فيها إنشاء كائن من نفس الفئة ولهذا ظهرت هذه الكلمة 3 مرات لأننا أنشئنا كائن من خلال دالة getObj() ثلاث مرات ولكن جرب الكود التالى :

<?php
class singleton {

 // متغير لحفظ الكائن المشأ من هذه الفئة
	private $classObj = NULL;

	// دالة إنشاء كائن من نفس الفئة الحالية
	public function getObj(){
    	if(!$this->classObj){
        	echo "make object<br>";
        	$this->classObj = new singleton();
    	}
    	return $this->classObj;
	}

	// دالة إختبار
	public function test(){
    	echo "ahmed<br>";
	}

} // نهاية الفئة

$obj = new singleton();
$obj2 = $obj->getObj();
$obj3 = $obj->getObj();
$obj4 = $obj->getObj();

// test
echo "-------------<br>";
$obj->test();
$obj2->test();
$obj3->test();
$obj4->test();

?>

- قمنا بإنشاء متغير $classObj لنخزن به كائن منشأ من نفس الفئة ولذلك وضعنا شرط فى حالة عدم وجود قيمة فى المتغير $classObj يتم إنشاء كائن من الفئة singleton وإسناده لهذا المتغير وإن كان يحتوى على قيمة يعود مباشراً بالقيمة الموجودة به بدون إنشاء كائن جديد من الفئة , وسوف تلاحظ هذا فى أن الكلمة make object لم تكتب إلا مرة واحده دليل على عدم إنشاء كائن من الفئة مرة أخرى ولكن إستخدام الكائن المنشأ مسبقاً من هذه الفئة .

ملاحظة : يمكن الإستغناء عن كتابة اسم الفئة بإستخدام self() كالتالى :

	public function getObj(){
		if(!$this->classObj){
			echo "make object<br>";
			$this->classObj = new self();
		}
		return $this->classObj;
	}

- ولكن يمكن لمستخدم الفئة إنشاء كائن مباشراً دون إستخدام دالة الإنشاء getObj() ولهذا يفضل إلغاء إمكانية إنشاء كائن من هذه الفئة , سيتبادر لذهنك وكيف سيمكننى فى البداية إنشاء كائن من الفئة لأستطيع إستخدام هذه الدالة ؟ أذكرك بالمكونات الساكنة للفئة static ويمكن من خلال تعريف دالة من النوع الساكن الوصول إليها مباشراً بدون إنشاء كائن من الفئة بإستخدام اسم الفئة ثم العلامتين :: ثم اسم الدالة الساكنة , وعند إستخدام دالة ساكنة يجب أيضاً إستخدام متغيرات ساكنة داخل هذه الدالة الساكنة وعلى هذا سيتم تعريف المتغير $classObj على أنه ساكن وسيتم إستخدامه من خلال الكلمة المحجوزة self ثم العلامتين :: ثم اسم المتغير الساكن .

- وهذا الكود لتوضيح ما سبق :

<?php

class singleton {

	// متغير لحفظ الكائن المشأ من هذه الفئة
	private static $classObj = NULL;

	// جعل دالة البناء نهائية لعدم إنشاء كائن مباشراً من خلال اسم الفئة
	final protected function __construct(){}

	// دالة إنشاء كائن من نفس الفئة الحالية
	public static function getObj(){
    	if(!self::$classObj){
        	echo "make object<br>";
        	self::$classObj = new self();
    	}
    	return self::$classObj;
	}

	// دالة إختبار
	public function test(){
    	echo "ahmed<br>";
	}

} // نهاية الفئة

$obj = singleton::getObj();
//$obj = new singleton();
$obj2 = $obj->getObj();
$obj3 = $obj->getObj();
$obj4 = $obj->getObj();

// test
echo "-------------<br>";
$obj->test();
$obj2->test();
$obj3->test();
$obj4->test();

?>

- تم تعريف دالة بناء الفئة __construct() على أنها نهائية final وبالتالى لا نستطيع إنشاء كائن من هذه الفئة إلا من خلال الدالة الساكنة getObj() , لاحظ الكود الموجود فى التعليق وهو محاولة إنشاء كائن من الفئة مباشراً فلو تم تفعيل الكود سيعطى خطأ .

- أيضاً لمنع عملية نسخ كائن من كائن بإستخدام clone سنقوم بتعريف الدالة __clone() على أنها نهائية لنمنع عملية نسخ كائن جديد .

وتصبح الفئة على الصورة التالية :

<?php

class singleton {

	private static $classObj = NULL;

	final protected function __construct(){}

	final private function __clone() {}

	public static function getObj(){
		if(!self::$classObj)
			self::$classObj = new self();
		return self::$classObj;
	}
}

?>

- وبالتالى قصرنا عملية إنشاء الكائن على الدالة getObj() لضمان عدم إنشاء كائن جديد من هذه الفئة فى حالة وجود كائن منشئ من تلك الفئة .

- سنأخذ تطبيق لهذه الطريقة على كيفية الإتصال الأمثل بقاعدة البيانات ليتضح فائدة هذه الطريقة , سيتم إستخدام mysqli للإتصال بقاعدة البيانات وهى فئة مدمجة باللغة يتم إنشاء كائن منها دون الحاجة لتضمين ملف خارجى .

ملاحظة : إستخدام mysql عفا عليه الزمن والأفضل إستخدام mysqli لمعالجتها كثير من مشاكل mysql وأهمها الناحية الأمنية .

<?php

class mySQL {

// مصفوفة لتخزين قيم الإتصال بقاعدة البيانات بها
private $DB = array();
// متغير لحفظ الكائن المشأ من هذه الفئة
private static $classObj = NULL;

	final protected function __construct(){
		// ضبط قيم الإتصال بقاعدة البيانات عند إستدعاء الفئة
		// اسم السرفر لقاعدة البيانات
		$this->DB['Host'] = "localhost";
		// اسم المستخدم لقاعدة البيانات
		$this->DB['UserName'] = "root";
		// الرقم السرى لمستخدم قاعدة البيانات
		$this->DB['UserPass'] = "";
		// اسم قاعدة البيانات
		$this->DB['Name'] = "db";
	}

	// جعل الدالة نهائية حتى لا يتم إستنساخ كائن جديد من الفئة
	final private function __clone() {}

	// دالة إنشاء كائن من نفس الفئة الحالية
	public static function getObj(){
		if(!self::$classObj)
			self::$classObj = new self();
		return self::$classObj;
	}

	// دالة إنشاء كائن من فئة الإتصال بقاعدة البيانات
	public function getConObj(){
		echo "make mysqli object<br>";
		return new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']);
	}


}

$obj = mySQL::getObj();
$obj2 = $obj->getConObj();
$obj3 = $obj->getConObj();
$obj4 = $obj->getConObj();
$obj5 = $obj->getConObj();
$obj6 = $obj->getConObj();
$obj7 = $obj->getConObj();
$obj8 = $obj->getConObj();
$obj9 = $obj->getConObj();
$obj10 = $obj->getConObj();
?>

- يجب وضع قيم الإتصال بقاعدة البيانات فى بانى الفئة حتى يعمل معك الكود بشكل سليم بدون أخطاء الإتصال بقاعدة البيانات , فى الكود أضع القيم الإفتراضية للسرفر المحلى "ربما تختلف من سرفر محلى لأخر" .

- تم إنشاء الدالة getConObj() والتى تعود بكائن فئة الإتصال بقاعدة البيانات .

- تم إنشاء كائن من الفئة mySQL من خلال الدالة getObj() كما تقدم شرحه .

- تم إنشاء عده كائنات من فئة الإتصال بقاعدة البيانات من خلال الدالة getConObj() , وتعمدت وضع عدد كبير من الكائنات المنشأه لتلاحظ الوقت الذى يمر حتى يتم إنشاء تلك الكائنات .

سنقوم الآن بتعديل الكود السابق وتطبيق مبدأ مشاركة الإتصال بقاعدة البيانات وذلك من خلال تعريف متغير لحفظ كائن الإتصال المنشأ كالتالى :

<?php

class mySQL {

// مصفوفة لتخزين قيم الإتصال بقاعدة البيانات بها
private $DB = array();
// متغير لحفظ الكائن المشأ من هذه الفئة
private static $classObj = NULL;
// متغير لحفظ الكائن المنشأ من فئة الإتصال بقاعدة البيانات
private $objCon = NULL;

	final protected function __construct(){
		// ضبط قيم الإتصال بقاعدة البيانات عند إستدعاء الفئة
		// اسم السرفر لقاعدة البيانات
		$this->DB['Host'] = "localhost";
		// اسم المستخدم لقاعدة البيانات
		$this->DB['UserName'] = "root";
		// الرقم السرى لمستخدم قاعدة البيانات
		$this->DB['UserPass'] = "";
		// اسم قاعدة البيانات
		$this->DB['Name'] = "db";
	}

	// جعل الدالة نهائية حتى لا يتم إستنساخ كائن جديد من الفئة
	final private function __clone() {}

	// دالة إنشاء كائن من نفس الفئة الحالية
	public static function getObj(){
		if(!self::$classObj)
			self::$classObj = new self();
		return self::$classObj;
	}

	// دالة إنشاء كائن من فئة الإتصال بقاعدة البيانات
	public function getConObj(){
		if(!$this->objCon){
			echo "make mysqli object<br>";
			$this->objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']);
		}
		return $this->objCon;
	}


}

$obj = mySQL::getObj();
$obj2 = $obj->getConObj();
$obj3 = $obj->getConObj();
$obj4 = $obj->getConObj();
$obj5 = $obj->getConObj();
$obj6 = $obj->getConObj();
$obj7 = $obj->getConObj();
$obj8 = $obj->getConObj();
$obj9 = $obj->getConObj();
$obj10 = $obj->getConObj();
?>

والآن هل لاحظت فرق الوقت بين هذا الكود والكود السابق

ويمكن تعديل دالة إنشاء كائن من فئة الإتصال بحيث يتم إنهاء الفئة وعرض أخطاء الإتصال بقاعدة البيانات كالتالى :

public function getConObj(){
	if(!$this->objCon){
		$this->objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']);
		if($this->objCon->connect_errno) 
			die($this->objCon->connect_error);
	}
	return $this->objCon;
}

- سنضع الآن دالة لعمل إستعلام على قاعدة البيانات وإظهار الأخطاء إن وجدت فى الإستعلام كالتالى :

public function makeQuery($qu){
	$temp = $this->getConObj()->query($qu);
	if(!$temp)
		die($this->getConObj()->error);
	return $temp;
}

- لتصبح الفئة على الشكل التالى:

<?php

class mySQL {

// مصفوفة لتخزين قيم الإتصال بقاعدة البيانات بها
private $DB = array();
// متغير لحفظ الكائن المشأ من هذه الفئة
private static $classObj = NULL;
// متغير لحفظ الكائن المنشأ من فئة الإتصال بقاعدة البيانات
private $objCon = NULL;

	final protected function __construct(){
		// ضبط قيم الإتصال بقاعدة البيانات عند إستدعاء الفئة
		// اسم السرفر لقاعدة البيانات
		$this->DB['Host'] = "localhost";
		// اسم المستخدم لقاعدة البيانات
		$this->DB['UserName'] = "root";
		// الرقم السرى لمستخدم قاعدة البيانات
		$this->DB['UserPass'] = "";
		// اسم قاعدة البيانات
		$this->DB['Name'] = "db";
	}

	// جعل الدالة نهائية حتى لا يتم إستنساخ كائن جديد من الفئة
	final private function __clone() {}

	// دالة إنشاء كائن من نفس الفئة الحالية
	public static function getObj(){
		if(!self::$classObj)
			self::$classObj = new self();
		return self::$classObj;
	}

	// دالة إنشاء كائن من فئة الإتصال بقاعدة البيانات
	public function getConObj(){
		if(!$this->objCon){
			$this->objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']);
			if($this->objCon->connect_errno) 
				die($this->objCon->connect_error);
		}
		return $this->objCon;
	}

	// دالة إنشاء إستعلام على قاعدة البيانات
	public function makeQuery($qu){
		$temp = $this->getConObj()->query($qu);
		if(!$temp)
			die($this->getConObj()->error);
		return $temp;
	}

}

// test
$obj = mySQL::getObj();
if($obj->makeQuery("SELECT * FROM users")->num_rows > 1)
	echo "yes";
else
	echo "no";

?>

وإلى هنا والسلام عليكم وإلا لقاء أخر بإذن الله تعالى

singleton.php

mySQL.php

تم تعديل هذه المشاركة بواسطة ahmedsaoud31 في 28 سبتمبر 2012 في 22:32

2

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#2

السلام عليكم

سنتابع لعمل دالة لتسجيل الدخول تعتمد على الفئة السابقة ولشرح مبدأ والوارثة بشئ من التطبيق سنقوم بوراثة الفئة mySQL .

- ولكن تعريف الدالة __construct() على أنها نهائية يجعلنا لا نستطيع إستخدام بانى الفئة عند الوراثة فلهذا سنجعل الدالة __construct() فى الفئة mySQL محمية فقط , لأننا سنحتاج إستخدام بانى الفئة فيما بعد .

- عند وراثة الفئة mySQL وإنشاء كائن منها وإنشاء كائن أخر من الفئة الوارثة للفئة mySQL فإذا تم مناداه دالة الإتصال بقاعدة البيانات من الكائنين سيتم عمل إتصالين ولهذا نقوم بتعريف المتغير $objCon على أنه ساكن لفتح إتصال واحد لأى كائن منشأ من الفئة mySQL أو أحد الفئات التى ترثها , ويمكنكم ملاحظة هذا بوضع جملة طباعة فى دالة الإتصال بقاعدة البيانات لمعرفة عدد الإتصال التى يتم فتحها كما فعلنا فى الأكواد السابقة .

- الآن تصبح الفئة mySQL كالتالى :

<?php 

class mySQL { 

// مصفوفة لتخزين قيم الإتصال بقاعدة البيانات بها 
private $DB = array(); 
// متغير لحفظ الكائن المشأ من هذه الفئة 
private static $classObj = NULL; 
// متغير لحفظ الكائن المنشأ من فئة الإتصال بقاعدة البيانات 
private static $objCon = NULL; 

	protected function __construct(){ 
    	// ضبط قيم الإتصال بقاعدة البيانات عند إستدعاء الفئة 
    	// اسم السرفر لقاعدة البيانات 
    	$this->DB['Host'] = "localhost"; 
    	// اسم المستخدم لقاعدة البيانات 
    	$this->DB['UserName'] = "root"; 
    	// الرقم السرى لمستخدم قاعدة البيانات 
    	$this->DB['UserPass'] = ""; 
    	// اسم قاعدة البيانات 
    	$this->DB['Name'] = "db"; 
	} 

	// جعل الدالة نهائية حتى لا يتم إستنساخ كائن جديد من الفئة 
	final private function __clone() {} 

	// دالة إنشاء كائن من نفس الفئة الحالية 
	public static function getObj(){ 
    	if(!self::$classObj) 
        	self::$classObj = new self(); 
    	return self::$classObj; 
	} 

	// دالة إنشاء كائن من فئة الإتصال بقاعدة البيانات 
	public function getConObj(){ 
    	if(!self::$objCon){ 
        	self::$objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']); 
        	if(self::$objCon->connect_errno) 
            	die(self::$objCon->connect_error); 
    	} 
    	return self::$objCon; 
	} 

	// دالة إنشاء إستعلام على قاعدة البيانات 
	public function makeQuery($qu){ 
    	$temp = $this->getConObj()->query($qu); 
    	if(!$temp) 
        	die($this->getConObj()->error); 
    	return $temp; 
	} 

} 

?>

والآن سنقوم بعمل فئة جديد باسم myLogin ترث الفئة mySQL :

<?php 
include_once(__DIR__ .'\mySQL.php'); 

class myLogin extends mySQL{ 

	protected function __construct(){ 
		parent::__construct(); 
	} 

}

?>

- تم تضمين الفئة mySQL فى بداية الملف , وإن أردت أن تعرف ما هو الثابت __DIR__ وأخواته أدخل على هذا الرابط .

- الفئة myLogin قامت بوراثة الفئة mySQL .

- قمنا بإنشاء بانى الفئة وإستدعينا بداخلة بانى الفئة للفئة الأب mySQL .

والآن نريد عمل نمط مفرد لإنشاء كائن من الفئة myLogin ولكن لا يعقل عند كل وراثة عمل دالة مختلفة لعمل ذلك ولهذا وجد ما يعرف بالتحميل الزائد للدول أى سيتم تعريف الدالة بنفس التعريف و نفس الاسم ونفس الوسائط , وأيضاً بما أن المتغير $classObj خاص داخل الفئة mySQL سنقوم بتعريفة أيضاً بنفس الاسم مره أخرى فى الفئة myLogin .

- وتصير الفئة على النحو التالى :

<?php 
include_once(__DIR__ .'\mySQL.php'); 

class myLogin extends mySQL{ 

private static $classObj = NULL;

	protected function __construct(){ 
		parent::__construct(); 
	} 

	public static function getObj(){ 
		if(!self::$classObj) 
			self::$classObj = new self(); 
		return self::$classObj; 
	} 
} 

?>

- لاحظ أنها نفس الدالة فى الفئة mySQL تماماً ولكن التعريف $obj = myLogin::getObj(); يعنى إنشاء كائن من الفئة myLogin والتعريف $obj = mySQL::getObj(); يعنى إنشاء كائن من الفئة mySQL .

- وهذه دالة تسجيل الدخول :

public function login($user,$pass){ 
	if($user==NULL or $pass==NULL){ 
		return false; 
	}else{ 
		// هذا كود الفلترة لاسم المستخدم وكلمة المرور يمكنك ضبطه كما تريد بإستخدام التعابير القياسية 
		$user = preg_replace('/[^A-Za-z0-9]/','',$user); 
		$pass = preg_replace('/[^A-Za-z0-9]/','',$pass); 
		// كود الاستعلام من قاعدة البيانات يمكنك تغييره على حسب بيانات جدولك 
		$Tquery = " SELECT * FROM users WHERE userName='$user' AND userPass='$pass'"; 
		if($temp = $this->makeQuery($Tquery)->num_rows == 1) 
			return true; 
		else 
			return false; 
	} 
}

- طبعاً يتم تغيير بيانات قاعدة البيانات إلى بيانات القاعدة لديكم , وأيضاً التعابير القياسية لفلترة الاسم وكلمة المرور على حسب ما تريدون .

وهذه هى الفئة كاملة :

<?php 
include_once(__DIR__ .'\mySQL.php'); 

class myLogin extends mySQL{ 

private static $classObj = NULL;

	protected function __construct(){ 
		parent::__construct(); 
	} 

	public static function getObj(){ 
		if(!self::$classObj) 
			self::$classObj = new self(); 
		return self::$classObj; 
	} 

	// دالة تسجيل الدخول 
	public function login($user,$pass){ 
		if($user==NULL or $pass==NULL){ 
			return false; 
		}else{ 
			// هذا كود الفلترة لاسم المستخدم وكلمة المرور يمكنك ضبطه كما تريد بإستخدام التعابير القياسية 
			$user = preg_replace('/[^A-Za-z0-9]/','',$user); 
			$pass = preg_replace('/[^A-Za-z0-9]/','',$pass); 
			// كود الاستعلام من قاعدة البيانات يمكنك تغييره على حسب بيانات جدولك 
			$Tquery = " SELECT * FROM users WHERE userName='$user' AND userPass='$pass'"; 
			if($temp = $this->makeQuery($Tquery)->num_rows == 1) 
				return true; 
			else 
				return false; 
		} 
	} 
} 

// test
$obj = myLogin::getObj(); 
if($obj->login("ahmed","123")) 
	echo "Login Ok !"; 
else 
	echo "Try Again !"; 

echo "<br>";

$obj2 = mySQL::getObj();
if($obj2->makeQuery("SELECT * FROM users")->num_rows) 
	echo "Found Users !"; 
else 
	echo "No users in the table !"; 

?>

- سنقوم بإضافة تسجيل الدخول من خلال الجلسات session يمكن وضع الدوال مباشراً فى الفئة myLogin ولكن لتوضيح مبدأ الوراثة المتتابعة سنقوم بعمل فئة جديدة mySession ترث الفئة myLogin :

<?php 
include_once(__DIR__ .'\myLogin.php'); 
class mySession extends myLogin { 

	private static $classObj = NULL; 

	protected function __construct(){ 
		if(!isset($_SESSION)) SESSION_START(); 
		parent::__construct(); 
	} 
	public static function getObj(){ 
		if(!self::$classObj) 
			self::$classObj = new self(); 
		return self::$classObj; 
	} 
}  
?>

- تم تضمين ملف الفئة myLogin ثم إنشاء فئة mySession ثرث الفئة myLogin

- تم إنشاء بانى الفئة وتشغيل جلسة فى حال كانت غير مفعلة

- تم إنشاء نمط مفرد لإنشاء كائن من الفئة mySession بإستخدام التحميل الزائد للدالة getObj()

- والآن سنضع الدوال التالية للفئة mySession :

1- دالة تسجيل الدخول من خلال الجلسة .

2- دالة تسجيل الخروج من الجلسة .

3- دالة عمل تحقق من قاعدة البيانات للقيم الموجودة فى الجلسة "وذلك حماية لعدم محاولة التلاعب فى قيم الجلسة" .

ويكون الكود كالتالى :

<?php 
include_once(__DIR__ .'\myLogin.php'); 

class mySession extends myLogin {

	// متغير تخزين الكائن المنشأ من الفئة  
	private static $classObj = NULL; 

	// بانى الفئة 
	protected function __construct(){ 
		if(!isset($_SESSION)) SESSION_START(); 
		parent::__construct(); 
	} 

	// دالة تحميل زائد لتطبيق النمط الفردى لإنشاء كائن من الفئة 
	public static function getObj(){ 
		if(!self::$classObj) 
			self::$classObj = new self(); 
		return self::$classObj; 
	} 

	// دالة تسجيل دخول عبر الجلسة 
	public function sLogin($user,$pass){ 
		if($this->login($user,$pass)){ 
			$_SESSION['username'] = $user; 
			$_SESSION['password'] = $pass; 
			return true; 
		}else return false; 
	} 

	// دالة تسجيل الخروج من الجلسة 
	public function sLogout(){ 
		if(isset($_SESSION['username']) and isset($_SESSION['password'])) 
			unset($_SESSION['username'],$_SESSION['password']); 
	} 

	// دالة إختبار البيانات الموجودة فى الجلسة 
	public function checkSLogin(){ 
		if(isset($_SESSION['username']) and isset($_SESSION['password'])){ 
			if($this->login($_SESSION['username'],$_SESSION['password'])) 
				return true; 
			else 
				return false; 
		}else return false; 
	} 
} // end mySession class  


// test     
$user='ahmed'; 
$pass='123'; 

$obj = mySession::getObj();
if($obj->login($user,$pass)) 
	echo "login ok !<br>"; 
else 
	echo "not login !<br>"; 

if($obj->sLogin($user,$pass)) 
	echo "session login ok !<br>"; 
else 
	echo "not session login !<br>"; 

$obj->sLogout(); 
echo "logout session ok!<br>"; 

if($obj->checkSLogin())
	echo "session login ok !<br>"; 
else 
	echo "not session login !<br>"; 

if($obj->makeQuery("SELECT * FROM users")->num_rows)
	echo "Found Users !"; 
else 
	echo "No users in the table !"; 
?>

- لست بحاجة عند إنشاء تطبيق أو موقع أن تقوم ببرمجة هذا من جديد فقط ستقوم بإستخدام الفئة أو وراثتها وإضافة مزيد من الدوال عليها , فهل وضحت الآن الفكرة من عملية الوراثة ؟

- وفى وقت لاحق إن شاء الله سأشرح وأضع ملف به تطبيق لإستخدام هذه الفئة فى عملية تسجيل الدخول والخروج لمعرفة كيفية الإستخدام بشئ من التطبيق المباشر .

myClasses.zip

2

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#3

كنت قبل قليل اقرأ مقالة لاستاذنا الغالي بن العبد في هذا الرابط

/index.php?showtopic=183931

من ضمن النقاط التي ذكرها هي الاهتمام بالذاكرة وتقليص استخدامها لاكبر درجة ممكنه وموضوع الـ Singleton يندرج تحت هذا المجال لاستخدام الموارد بشكل افضل وإتقان البرمجة .

لفتة جميلة منك استاذنا أحمد الى MySQLi فعلا نحن بحاجه الى الانتقال من MySQL الى MySQLi لأنها لاحدث والافضل لكن بخصوص المثال الذي شرحته في حالة استخدمنا MySQL لاداعي لاستخدام معها Singleton لانه تم حل هذه المشكلة من خلال دالة mysql_pconnect لكن بطبيعة الحال الافضل استخدام MySQLi .

عموما مجهودك هذا تستحق عليه كل الشكر والتقدير ونحن فعلا بحاجه الى مواضيع بهذا المستوى واتمنى ان لا تحبط من قلة التفاعل في الموضوع وغيرها من مواضيعك المميزة واعتقد انت تعرف السبب تماما ثقافة النسخ واللصق لازالت منتشرة بكثرة والمواضيع المتقدمة لا تستهوي الكثيرين :lol:

استمر وواصل ابداعك اتمنى لك التوفيق

M.B.O

Mohamed Bin Othman

إبن المكلا

يابني البشر ماذا فعلتم بالبشر !!

إسـألـنـي

#4

السلام عليكم ورحمة الله وبركاتة

شكراً لك أستاذنا العزيز محمد مرورك هنا على الموضوع يكفينا , أنت تعلم أن قلة التفاعل تسبب نوع من عدم الإجتهاد ولكن والحمد لله نحن نكتب لأننا على قناعه أن هناك شخص ما سيقرأ الموضوع "عاجلاً أم أجلاً" وربما يسفيد منه ويدعوا لنا دعوه بظهر الغيب عسى أن تنفعنا يوم لا ينفع مال ولا بنون .

يبدوا أن موضوع الأستاذ بن العيد موضوع ثرى سأحاول قراءته لاحقاً .

- بالنسبة لتعليقك فهذا من أهم نقاط المشاركة الفعَّاله وهو التفاعل والذى دائماً ما يثرى الموضوع , وأيضاً بالإضافه لما قلت فإن إستخدام نمط الإتصال المفرد بقاعدة البيانات يوفر حتى عملية مخاطبة خادم قاعدة البيانات للتأكد من وجود إتصال مفتوح كما فى mysql_pconnect لأن العملية تتم من خلال كود php دون الحاجة لمخاطبة خادم قاعدة البيانات وأيضاً mysql_close() لا تستطيع غلق هذا النوع من الإتصال , ويمكن تعميم متغير الإتصال بقاعدة البيانات من متغير على مستوى الكائن وهو النوع الساكن static إلى متغير على مستوى المشروع أو الموقع ككل فيتبادر للزهن إستخدام الجلسات ولكن لن نستطيع فعل هذا بإستخدام الجلسات لأن الجلسات لا تدعم حفظ كائن من نوعيه كائن الإتصال بقاعدة البيانات ولمن يريد تعميم متغير الإتصال بقاعدة البيانات يمكن استخدام Memcache أو Memcashed .

- ولا يقتصر تطبيق مبدأ النمط المفرد على الإتصال بقاعدة البيانات أو إنشاء كائن من الفئة ولكن يمكن إستخدام هذا المبدأ فى نواحى عديدة كحفظ إستعلامات تتم بشكل دورى على قاعدة البيانات أو غيرها من الإستخدامات الهامة التى يظهر أثرها عند التعامل مع مواقع ذات ضغط عالى من الزوار .

- بالنسبة لو أردنا تعميم الإتصال بقاعدة البيانات ليصبح إتصال واحد بقاعدة البيانات على مستوى الموقع ككل -أى حتى عند التنقل بين صفحات الموقع - سنقوم بإستخدام Memcashed كالتالى :

أولاً : علينا تهيئة الـMemcashed حتى نستطيع التعامل معها .

- إذا كنت تستخدم نظام لينكس وتوزيعة ubuntu وأيضاً تستخدم السرفر LAMPP فقط يكفيك كتابة الأمر التالى فى نافذه الأوامر "terminal" :

sudo apt-get install php5-memcached

ثم أعد تشغيل السرفر بالأمر :

sudo /etc/init.d/apache2 restart

ثانياً : سوف نتعامل مع الفئة mySQL التى أنشأناها من قبل ويكون حفظ متغير الإتصال فى ذاكرة السرفر كالتالى :

$obj = new Memcached(); 
$obj->addServer("localhost", 11211); 
$obj->set('objCon',self::$objCon,300);

- تم إنشاء كائن من الفئة Memcashed

- الخطوة التالية إعداد السرفر للتخزين .

- لإضافة متغيرات للـMemcashed نستخدم set "الوسيط الأول اسم المتغير والثانى القيمة والثالث وقت الإحتفاظ بالمتغير بالثوان" ولجلب تلك المتغيرات نستخدم get "وتأخذ وسيط اسم المتغير المراد جلب قيمته"

- تم تخزين كائن الإتصال فى متغير باسم objCon داخل الـMemcashed وتم ضبط وقت بقاء هذا المتغير داخل الذاكرة لمدة 300 ثانية تقريباً .

ولتطبيق الكود السابق فى الفئة mySQL سنقو بإنشاء دالة باسم getMCObj() لإنشاء كائن من الفئة Memcashed وطبعاً تعريف متغير ساكن باسم $objMC لحفظ الكائن المنشأ "تطبيق النمط المفرد لإنشاء كائن من الفئة".

- وفى دالة إنشاء كائن الإتصال بقاعدة البيانات getConObj() سيتم الأتى :

1- إن كانت هناك قيمة فى متغير الإتصال $objCon يعود بها مباشراً وإلا يتم الكشف عن وجود المتغير objCon فى الـMemcashed فإن كان موجد يتم حفظ قيمته "كائن الإتصال بقاعدة البيانات" فى المتغير $objCon والعوده بها

وإن لم يوجود المتغير objCon فى الـMemcashed يتم إنشاء كائن الإتصال بقاعدة البيانات وحفظ قيمته فى المتغير objCon فى الـMemcashed وأيضاً حفظ قيمته فى المتغير $objCon الساكن ثم العوده بقيمة كائن الإتصال .

وهذا الكود كامل لما سبق :

<?php 

class mySQL { 

// مصفوفة لتخزين قيم الإتصال بقاعدة البيانات بها 
private $DB = array(); 
// متغير لحفظ الكائن المشأ من هذه الفئة 
private static $classObj = NULL; 
// متغير لحفظ الكائن المنشأ من فئة الإتصال بقاعدة البيانات 
private static $objCon = NULL; 

private static $objMC = NULL; 

	protected function __construct(){ 
    	// ضبط قيم الإتصال بقاعدة البيانات عند إستدعاء الفئة 
    	// اسم السرفر لقاعدة البيانات 
    	$this->DB['Host'] = "localhost"; 
    	// اسم المستخدم لقاعدة البيانات 
    	$this->DB['UserName'] = "root"; 
    	// الرقم السرى لمستخدم قاعدة البيانات 
    	$this->DB['UserPass'] = "123"; 
    	// اسم قاعدة البيانات 
    	$this->DB['Name'] = "db"; 
	} 

	// جعل الدالة نهائية حتى لا يتم إستنساخ كائن جديد من الفئة 
	final private function __clone() {} 

	// دالة إنشاء كائن من نفس الفئة الحالية 
	public static function getObj(){ 
    	if(!self::$classObj) 
        	self::$classObj = new self(); 
    	return self::$classObj; 
	} 

	// دالة إنشاء كائن من فئة الإتصال بقاعدة البيانات 
	public function getConObj(){ 
		if(self::$objCon)  
			return self::$objCon; 
		$obj = $this->getMCObj(); 
		if(!$obj->get('objCon')){ 
			self::$objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']); 
			if(self::$objCon->connect_errno) 
            	die(self::$objCon->connect_error); 
			$obj->set('objCon',self::$objCon,300); 
			return self::$objCon; 
		}else{ 
			self::$objCon = $obj->get('objCon'); 
			return self::$objCon; 
		} 
	} 

	// دالة إنشاء إستعلام على قاعدة البيانات 
	public function makeQuery($qu){ 
    	$temp = $this->getConObj()->query($qu); 
    	if(!$temp) 
        	die($this->getConObj()->error); 
    	return $temp; 
	} 

	public function getMCObj(){ 
		if(!self::$objMC){ 
        	self::$objMC = new Memcached(); 
        	self::$objMC->addServer('localhost', 11211); 
		} 
    	return self::$objMC; 
	} 

} // end mySQL class 

?>

بالنسبة لهذا التطبق السابق فيمكن لنا تسميته بنمط مفرد بصوره أعم وأشمل ولا تقتصر هذه الطريقة على إنشاء الإتصال بقاعدة البيانات ولكن هذا كمثال , فهى لها إستخدامات عديدة .

mySQL.php

تم تعديل هذه المشاركة بواسطة ahmedsaoud31 في 13 أكتوبر 2012 في 12:52

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#5

السلام عليكم

إن شاء الله اليوم هو تطبيق على الفئات السابقة لعملية تسجيل الدخول

- نلاحظ فى الصورة التالية من ملفات ومجلدات التطبيق " المجلد فى المرفقات " :

post-254524-081359900 1350225931_thumb.p

- مجلد myClasses يحتوى على الفئات التى تم تنفيذها فى الأعلى وعلى الملفان indx.php و login.php هما ما يهمانا فى الأمر وباقى المجلدات والملفات فهى ملفات التنسيق والصور .

- سنقوم بتضمين الفئة mySession فى أعلى الملفين لنستطيع إنشاء كائن منها كالتالى :

include_once( __DIR__ .'/myClasses/mySession.php');

* فى ملف indx.php فى حالة كون المستخدم فى حالة عدم تسجيل الدخول تظهر له كلمة " تسجيل الدخول " وإن كان فى حالة تسجيل الدخول تظهر له " تسجيل الخروج " ويكون كالتالى :

$obj = mySession::getObj(); 
if(isset($_GET['login'])) 
	if($_GET['login']==0) 
		$obj->sLogout(); 
if(isset($_SESSION['username']) and isset($_SESSION['password'])) 
	echo '<a href="indx.php?login=0"> تسجيل الخروج </a>'; 
else 
	echo '<a href="login.php?login=1"> تسجيل الدخول </a>';

- تم إنشاء كائن من الفئة mySession ثم التحقق من وجود قيمة فى $_GET['login'] وإن كانت القيمة تساوى 0 يتم تسجيل الخروج من الجلسة بإستخدام .

- فى حالة عدم وجود قيم لاسم الستخدم وكلمة المرور فى الجلسة يتم إظهار " تسجيل الدخول " وإن وجد بهما قيم يتم إظهار " تسجيل الخروج " .

- نأتى لأهم خطوة وهى عملية التحقق من القيم الموجودة فى الجلسة من قاعدة البيانات لإظهار محتوى معين أو إخفائه كالتالى :

if($obj->checkSLogin()) 
	echo '<span class="content1" > مرحباً بك هنا لا يوجد محتوى لعرضه :) </span>'; 
else 
	echo '<span class="content2" > قم بتسجيل الدخول لترى محتوى الصفحة </span>';

- والآن نتجه لملف العم login.php كما فى الصورة التالية :

post-254524-034759800 1350226100_thumb.p

والذى يحوى بطياته هذا الكود :

<?php 
	if(isset($_POST['username']) and isset($_POST['password'])){ 
	$obj = mySession::getObj(); 
	if($obj->sLogin($_POST['username'],$_POST['password'])){ 
?> 
		<h3 align="center"><font color='#33AA33'>تم تسجيل الدخول بنجاح جارى الإنتقال للصفحة الرئيسية</font></h3> 
		<script type="text/javascript"> 
			setTimeout(function() { location.href="indx.php" }, 1000); 
		</script> 
<?php 
		exit(); 
	}else{ 
		echo "<h3 align='center'><font color='#FF0000'>عفواً لم يتم تسجيل الدخول حاول مرة أخرى</font></h3>"; 
	} 
} 
?>

- ففى حالة عدم وجود قيم مرسلة للعم login.php من أبيه الحج indx.php فيتجاهل أبيه ولا يفعل شياً , وإن كان هناك قيم سيتنازل الكود عن كبريائة ويقوم بإنشاء كائن من الفئة mySession وإرسال قيم الحج أبيه للتحقق من صحتها فإن تم الرد علية بالقبول يقوم بتهنئة المستخدم ونقلة بعد ثوان قلية لأبيه مباشراً , ولكن ما بال لو تم الرد عليه بعدم القبول بكل تأكيد سيغضب ويحمر وجهه ويقوم بإظهار رسالة ترهيبية للمستخدم تفيد بعدم مقدرة تسجيل الدخول , laugh.gif اسف على هذا ولكن ملل الكتابة الرتيبة هو الدافع لبعض المزاح معكم smile.gif

أرجوا أن تكونوا قد إستفدتم من هذا الموضوع

دمتم فى رعاية الله والسلام عليكم

lessons.zip

المرفقات
Selection_001.pngSelection_002.png

تم تعديل هذه المشاركة بواسطة ahmedsaoud31 في 14 أكتوبر 2012 في 17:54

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#6

السلام عليكم

اخي الكريم من المعرف انه عند وراثت كلاس يتم وراثة جميع الـ (method) لكنك انت عندما قمت بوراثة كلاس قاعدة البيانات اعدت كتابة التابع التالي:

public static function getObj(){ 
                if(!self::$classObj) 
                        self::$classObj = new self(); 
                return self::$classObj; 
        }

لقد راجعت الكود و الدرس عدة مرات لكني لم افهم هذه النطقة فهل من الممكن توضيحا؟

#7

السلام عليكم

اقتباس
اخي الكريم من المعرف انه عند وراثت كلاس يتم وراثة جميع الـ (method) لكنك انت عندما قمت بوراثة كلاس قاعدة البيانات اعدت كتابة التابع ...
سؤال جميل عزيزى وسأوضح ما أعلم

- من تعريف عمل هذه الدالة وهو " إنشاء كائن من نفس الفئة الموجوده بها بطريقة النمط المفرد "

على سبيل المثال هب أن الفئة myLogin قامت بوراثة الفئة mySQL وأيضاً الفئة mySession قامت بوراثة الفئة myLogin ولم نعيد كتابة الدالة getObj() وقمنا بإنشاء كائنات من الفئات الثلاثة كالتالى :

$obj1 = mySQL::getObj(); 
$obj2 = myLogin::getObj(); 
$obj3 = mySession::getObj();

- فجميعها ستقوم بإنشاء كائن من الفئة mySQL وهذا مالا نريده

- وحتى لانكتب فى كل مرة دالة مختلفة لعملية إنشاء كائن من الفئة الحالية توفر لنا لغة php عملية تعرف بالتحميل الزائد للدوال وهى إعادة تعريف نفس الدالة مرة أخرى فى الفئة الموروثة وبالتالى عند إنشاء كائن من هذه الفئة سيتم إنشاء كائن من الفئة الحالية وليس من الفئة الأب .

وعلى هذا إذا تم إعادة كتابة الدالة getObj() فى الفئتين myLogin و mySession وتم إنشاء كائنات من الفئات الثلاثة كالتالى :

$obj1 = mySQL::getObj(); 
$obj2 = myLogin::getObj(); 
$obj3 = mySession::getObj();

- فالمتغير الأول سيحمل كائن منشأ من الفئة mySQL والثانى سيحمل كائن منشأ من الفئة myLogin والثالث سيحمل كائن منشأ من الفئة mySession

ملاحظة : يتم تعريف المتغير $classObj فى كل مرة تتم فيها عملية الوراثة لإستخدامة من قبل الدالة getObj() الموجودة فى نفس الفئة , وهذا المتغير خاص بالفئة أى ليس له علاقة بالمتغير الذى يحمل نفس الاسم فى الفئة الأب , " لأننا نعلم أن المتغيرات الخاصة لا يتم وراثتها " .

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#8

جميل جداً

مافهمته منك اخي انه عند انشاء تابع في الكلاس a على سبيل المثال ثم توريثة في الكلاس b واستخدامه من الكلاس b فانه يعمل على انه او لصالح الكلاس a. فهل هذه هي الفكرة ؟

#9

السلام عليكم

اقتباس
جميل جداً

مافهمته منك اخي انه عند انشاء تابع في الكلاس a على سبيل المثال ثم توريثة في الكلاس b واستخدامه من الكلاس b فانه يعمل على انه او لصالح الكلاس a. فهل هذه هي الفكرة ؟

كلامك صحيح إن كنت تقصد التالى " التعديل باللون الأحمر " :

... عند انشاء تابع " تقصد متغير أو دالة ؟ " في الكلاس a على سبيل المثال ثم توريثة في الكلاس b وإعادة تعريفه فى الكلاس b فانه يعمل على انه او لصالح الكلاس b ...

تم تعديل هذه المشاركة بواسطة ahmedsaoud31 في 15 أكتوبر 2012 في 22:47

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#10

السلام عليكم

- عذراً فقد أخطأت في المشاركة الرابعة لي في هذا الموضوع عند محاولتي تخزين كائن الإتصال بقاعدة البيانات في الـMemcached , وإتضح حتي أن الـMemcached لايمكنها حفظ متغير كائن الإتصال بقاعدة البيانات وظهر الخطأ عند محاولتي عمل إستعلام من خلال الكائن المخزن في الـMemcashed ولتوضيح ما سبق سنستخدم دالة var_dump() أو print_r() لعرض خصائص الكائن , سنقوم بإنشاء كائن من فئة الإتصال بقاعدة البيانات ونقوم بعرض خصائص الكائن من خلال إحدي الدالتين السابقتين كالتالي :

<?php

	$DB = array(
		'Host' => 'localhost',
		'UserName' => 'root',
		'UserPass' => '123',
		'Name' => 'db');

	$obj = new mysqli($DB['Host'],$DB['UserName'],$DB['UserPass'],$DB['Name']);

	echo print_r($obj);
?>

- والآن سنقوم بحفظ كائن الإتصال في الـMemcached ثم نقوم بإستدعائة لعرض الخصائص مرة أخري كالتالي :

<?php

	$DB = array(
		'Host' => 'localhost',
		'UserName' => 'root',
		'UserPass' => '123',
		'Name' => 'db');

	$obj = new mysqli($DB['Host'],$DB['UserName'],$DB['UserPass'],$DB['Name']);

	$obj2 = new Memcached();
	$obj2->addServer('localhost', 11211);
	$obj2->set('objCon',$obj,20);

	echo print_r($obj2->get('objCon'));
?>

- عند تنفيذ هذا الكود ستظهر لنا أخطاء عدم الوصول لخصائص الكائن المخزن في الـMemcached وعلي هذا لن نستطيع إعادة إستخدام هذا الكائن لأنه يفقد خصائصة بمجرد تخزينة في الـMemcashed .

- إن كان لدي أحد طريقة ما لكيفة جعل متغير كائن الإتصال عام علي مستوي المشروع فليطرحها لنا .

دمتم في رعاية الله والسلام عليكم

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#11

السلام عليكم

اخي لقد اضفت فقط  mysqli_close بستخدام __destruct والكود أصبح كتالي:

<?php 

class mySQL { 
    
// مصفوفة لتخزين قيم الإتصال بقاعدة البيانات بها 
private $DB = array(); 
// متغير لحفظ الكائن المشأ من هذه الفئة 
private static $classObj = NULL; 
// متغير لحفظ الكائن المنشأ من فئة الإتصال بقاعدة البيانات 
private static $objCon = NULL; 

        protected function __construct(){ 
        // ضبط قيم الإتصال بقاعدة البيانات عند إستدعاء الفئة 
        // اسم السرفر لقاعدة البيانات 
        $this->DB['Host'] = "localhost"; 
        // اسم المستخدم لقاعدة البيانات 
        $this->DB['UserName'] = "root"; 
        // الرقم السرى لمستخدم قاعدة البيانات 
        $this->DB['UserPass'] = ""; 
        // اسم قاعدة البيانات 
        $this->DB['Name'] = "test"; 
        } 
		
		protected function __destruct(){
			if(self::$objCon){
				@mysqli_close(self::$objCon);
			}
		}
    
        // جعل الدالة نهائية حتى لا يتم إستنساخ كائن جديد من الفئة 
        final private function __clone() {} 
    
        // دالة إنشاء كائن من نفس الفئة الحالية 
        public static function getObj(){ 
        if(!self::$classObj) 
                self::$classObj = new self(); 
        return self::$classObj; 
        } 
    
        // دالة إنشاء كائن من فئة الإتصال بقاعدة البيانات 
        public function getConObj(){ 
        if(!self::$objCon){ 
				echo "create <br />";
                self::$objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']); 
                if(self::$objCon->connect_errno) 
                die(self::$objCon->connect_error); 
        } 
        return self::$objCon; 
        } 
    
        // دالة إنشاء إستعلام على قاعدة البيانات 
        public function makeQuery($qu){ 
        $temp = $this->getConObj()->query($qu); 
        if(!$temp) 
                die($this->getConObj()->error); 
        return $temp; 
        } 
    
} 

$mysql = mysql::getObj();
$mysql->getConObj();
$mysql->getConObj();

?>

فاعطاني الخطأ Warning: Call to protected mySQL::__destruct() from context '' during shutdown ignored in Unknown on line 0

فما السبب؟

#12

وعليكم السلام ورحمة الله وبركاته

 

الخطأ بسبب تعريف هادم الفئة على أنه محمي وبهذا أن لا تستطيع إنشاء كائنات مباشراً من الفئة , ولا تصلح الفئة إلا للوراثة فقط بما أن هادم الفئة محمي .

 

ولإزالة الخطأ ثم بتعريف هادم الفئة دالة عامة public , ولن تؤثر على النمط المفرد لإنشاء إتصال بقاعدة البيانات .

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#13

اعرف اخي ولكن الهادم لا استدعيه ابدا خارج الكلاس فهو يعمل من الداخل وهاذا اللذي حيرني.

هل وصلت الفكرة؟

#14

الهادم هي دالة كأي دالة تقوم بإنشائها داخل الفئة ولكنها معرفة مسبقاً في اللغة فعند إنشاء كائن من الفئة يتم تنفيذ الفئة وفي النهاية يقوم الكائن المنشأ تلقائياً بإستدعاء هادم الفئة فلهذا أشرت أنه عند جعل هادم الفئة محمي لا يصلح إستخدام الفئة إلا عن طريق الوراثة لأنه عند إنشاء كائن من الفئة يقوم الكائن بإستدعاء هادم الفئة إجبارياً -وتعتبر هذه العملية وصول للهادم من الخارج- , أي كأنك قمت بإستدعاء الكائن ولكن هذه العملية تتم تلقائياً وإيجبارياً عن تعريف الهادم في الفئة .

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#15

لقد وضحت الفكرة

وعندي سؤال هل القريقة اللتي استخدمتها انا الانشاء الهادم صحيح أم هناك طريقة أفضل؟

#16

اخي الكريم عندي سؤال آخر وهو.
في حال كان لدي كلاسان واحد للاتصال بقاعدة البيانات و الآخر لتسجيل الدخول كتالي:
كلاس الاتصال بقاعدة اليانات.
 

class mySQL { 
    
private $DB = array(); 
private static $classObj = NULL; 
private static $objCon = NULL; 

        protected function __construct(){ 
        $this->DB['Host'] = "localhost"; 
        $this->DB['UserName'] = "root"; 
        $this->DB['UserPass'] = ""; 
        $this->DB['Name'] = "db"; 
        } 
    
        final private function __clone() {} 
    
        public static function getObj(){ 
        if(!self::$classObj) 
                self::$classObj = new self(); 
        return self::$classObj; 
        } 
    
        public function getConObj(){ 
        if(!self::$objCon){ 
                self::$objCon = new mysqli($this->DB['Host'],$this->DB['UserName'],$this->DB['UserPass'],$this->DB['Name']); 
                if(self::$objCon->connect_errno) 
                die(self::$objCon->connect_error); 
        } 
        return self::$objCon; 
        } 
    
        public function makeQuery($qu){ 
        $temp = $this->getConObj()->query($qu); 
        if(!$temp) 
                die($this->getConObj()->error); 
        return $temp; 
        } 
    
} 

?>

والآن اردت الاتصال بقاعدة البيانات من داخل كلاس تسجيل الدخول كتالي

$query = "SELECT id, name, mail, pass, power FROM `user` WHERE mail = email@email.com' AND pass = MD5(pass)";
				$obj = self::getSing();
				//$obj->connectDB();
				$query = $obj->query($query);
				if($query != false){
echo 'good';
				}else{
					Echo 'error';
				}

فاستعمال الاسطر التالية صحيح؟

$obj = self::getSing();				$query = $obj->query($query);

مع العلم أنني قمت بتجريب الحول وهو يعمل لكن سؤالي هل هاذا الحل به اخطاء غير واضحة؟

وهل الاتصال بقاعدة بيانات من داخل كلاس يعتبر خطأ في عالم البرمجة؟

#17

مرحباً بك أخي العزيز

 

إستدعاء دالة query من الكائن المنشأ $obj  سليمة وليس بها أخطاء , لأن هذا الكائن هو كائن منشأ من الفئة mysqli وتستطيع إستدعاء أي دالة من دوال mysqli مباشراً من هذا الكائن .

 

ولكن ما هذه الدالة getSing() ؟ فدالة إنشاء الكائن من الفئة mySQL هي getObj()

 

- في الفئة mySQL توجد دالة باسم makeQuery يمكنك إستخدامها بدلاً من إستخدام دالة query مباشراً وتضع بها أي كود لا تريد تنفيذه في كل مرة تقوم بعمل إستعلام على قاعدة البيانات , مثلاً أنت تتعامل مع بيانات باللغة العربية في قاعدة البيانات وتريد ضبط قيمة ترميز قاعدة البيانات قبل كل عملية إستعلام على قاعدة البيانات فالأفضل أن تضع هذا في دالة حتى لا تقوم بهذه العملية في كل إستعلام على قاعدة البيانات وسيكون شكل دالة makeQuery على النحو التالي :

// دالة إنشاء إستعلام على قاعدة البيانات
public function makeQuery($qu)
{
    // هذه الجذئية إن كنت تتعامل مع  اللغة العربية في قاعدة البيانات
    if(!$this->getConObj()->query("SET NAMES 'utf8'"))
    {
        die($this->getConObj()->error);
    }
    
    $temp = $this->getConObj()->query($qu);
    
    if(!$temp)
    {
        die($this->getConObj()->error);
    }
    
    return $temp;
}

 

اقتباس

وهل الاتصال بقاعدة بيانات من داخل كلاس يعتبر خطأ في عالم البرمجة؟

- لا يعتبر خطأ وهذه فائدة الفئة mySQL في أنها إذا وجدت أن هناك كائن منشأ من فئة الإتصال لا تقوم بإنشاء واحد جديد ولكن تستخدم الكائن المنشأ فقط وهذا يوفر وقت وذاكرة .

- بمعنى أنك إذا قمت بعمل إتصال بقاعدة البيانات من داخل أكثر من فئة أو قمت بعملية الإتصال أكثر من مرة سيتم الإتصال مرة واحدة بقاعدة البيانات إذا إستخدمة الفئة mySQL في عملية الإتصال .

 

دمت بود

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#18

شكرا لك

فأنا ابحث عن الاحتراف مع التعلم فارجو عدم  الانزعاج من كثرة الأسئلة

#19
اقتباس

شكرا لك

فأنا ابحث عن الاحتراف مع التعلم فارجو عدم  الانزعاج من كثرة الأسئلة

- على العكس تماماً , مرحباً بإستفساراتك في أي وقت مازن

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

مواضيع مشابهة