گزشتہ ٹٹوریل میں یہ بتایا گیا تھا کہ اگر آپ اپنی ویب سائیٹ پر صارفین کی تعداد دکھانا چاہیں تو اس کے لیے ویب کاؤنٹر کی کوئی سروس کیسے استعمال کی جا سکتی ہے۔ اس ٹٹوریل میں ہم یہ دیکھیں گے کہ PHP لینگوئج اور MySQL ڈیٹابیس کی مدد سے ہم اپنی ایک کاؤنٹر ایپلی کیشن کیسے تیار کر سکتے ہیں۔ یہ ایپلی کیشن بہت سادہ سی ہے اور اسے آپ بہت سی ویب سائیٹس پر کاؤنٹر دکھانے کے لیے استعمال کر سکتے ہیں۔
یہ ایپلی کیشن دو طرح کی گنتی ڈیٹابیس میں محفوظ کرتی ہے۔ (1) ایک یہ کہ کسی بھی صارف نے ویب سائیٹ کتنی مرتبہ وزٹ کی، مثلاً صارف نے آج اس ویب سائیٹ کے مختلف صفحات دیکھے، پھر اگلے دن یا چند دنوں کے بعد چند صفحات دیکھے تو یہ صارف کی دو وزٹس شمار ہوگئیں۔ (2) دوسری یہ کہ صارف نے ویب سائیٹ کے کتنے صفحات دیکھے، مثلاً پہلی وزٹ میں پانچ صفحات دیکھے، دوسری وزٹ میں سات صفحات دیکھے تو یہ کل بارہ صفحات شمار ہوگئے۔ چنانچہ یہ ایپلی کیشن Site visits کی ویلیو اور Page visits کی ویلیو ایک امیج کے طور پر دکھاتی جسے کوئی بھی ویب سائیٹ اپنے ویب پیجز میں شامل کر سکتی ہے۔
- ایپلی کیشن کے لیے ڈیٹابیس بنائیں
- کاؤنٹر کے PHP کوڈ کی وضاحت
- براؤزر میں کاؤنٹر کا نتیجہ ٹیسٹ کریں
- مزید کام کی ضرورت
1- ایپلی کیشن کے لیے ڈیٹابیس بنائیں
سب سے پہلے ہم ایک ڈیٹابیس بنائیں گے جو اس کاؤنٹر ایپلی کیشن میں سائیٹ وزٹس اور پیج وزٹس کی گنتی محفوظ کرنے کے لیے استعمال کی جائے گی۔ ڈیٹابیس بنانے کے لیے Database ٹیب میں آجائیں۔ ڈیٹابیس کا نام مہیا کریں، اس کے لیے کولیشن مہیا کریں، اور پھر بٹن پر کلک کر کے یہ ڈیٹابیس بنا لیں۔ کولیشن کے لیے ہم نے یونیکوڈ کا انتخاب اس لیے نہیں کیا کہ اس ڈیٹابیس میں انگلش کے علاوہ کسی زبان کا مواد محفوظ نہیں کیا جائے گا۔ اگر اس کی ضرورت پیش آئے تو ہم انفرادی طور پر ٹیبل یا اس کی فیلڈز کے لیے علیحدہ سے کولیشن منتخب کر سکتے ہیں۔
ویب سائیٹس کی کاؤنٹر پروفائلز کے لیے ٹیبل بنائیں
اب ہم ڈیٹابیس کا پہلا ٹیبل بنائیں گے۔ اس ٹیبل کا ہر ریکارڈ ایک الگ ویب سائیٹ کے لیے ہوگا جس میں اس ویب سائیٹ کی وزٹس محفوظ کی جائیں گی۔
- پہلے اسکرین شاٹ کے مطابق 3 فیلڈز پر مشتمل counter_profiles کے نام سے ٹیبل بنائیں۔
- دوسرے اسکرین شاٹ کے مطابق:
- پہلی فیلڈ counter_profile_id کے نام سے بنائیں جس کی مدد سے اس ٹیبل کے ہر ریکارڈ کو ایک منفرد اور خودکار نمبر مہیا کیا جائے گا۔ اس فیلڈ کے لیے INT ڈیٹا ٹائپ منتخب کریں، UNSIGNED ایٹری بیوٹ منتخب کریں، PRIMARY انڈیکس منتخب کریں، اور A_I کا چیک باکس منتخب کریں۔
- دوسری فیلڈ total_site_visits کے نام سے بنائیں، اس کے لیے INT ڈیٹا ٹائپ اور UNSIGNED ایٹری بیوٹ منتخب کریں۔
- تیسری فیلڈ total_page_visits کے نام سے بنائیں، اس کے لیے بھی INT ڈیٹا ٹائپ اور UNSIGNED ایٹری بیوٹ منتخب کریں۔
- آخر میں Save بٹن پر کلک کر کے یہ ٹیبل بنا لیں۔
صارفین کے آئی پی ایڈریسز کے لیے ٹیبل بنائیں
اب ہم ڈیٹابیس کا دوسرا ٹیبل بنائیں گے جس میں وزٹ کرنے والے صارفین کے آئی پی ایڈریسز اور وزٹ کی تاریخ و وقت محفوظ کیے جائیں گے۔
- پہلے اسکرین شاٹ کے مطابق 4 فیلڈز پر مشتمل ip_addresses کے نام سے ٹیبل بنائیں۔
- دوسرے اسکرین شاٹ کے مطابق:
- پہلی فیلڈ ip_address_id کے نام سے بنائیں جس کے لیے INT ڈیٹا ٹائپ، UNSIGNED ایٹری بیوٹ، PRIMARY انڈیکس، اور A_I چیک باکس منتخب کریں۔ یہ فیلڈ اس ٹیبل کے ہر ریکارڈ کو ایک منفرد اور خودکار نمبر مہیا کرے گی۔
- دوسری فیلڈ counter_profile_id کے نام سے بنائیں۔ اس کے لیے INT ڈیٹا ٹائپ، UNSINGED ایٹری بیوٹ، اور INDEX انڈیکس منتخب کریں۔ یہ فیلڈ اس لیے ہے تاکہ اس ٹیبل کا counter_profiles ٹیبل کے ساتھ ریلیشن بنایا جا سکے۔ یعنی اس فیلڈ کی مدد سے ہم یہ جان سکیں گے کہ اس ٹیبل کے کن ریکارڈز کا تعلق counter_profiles ٹیبل کے کس ریکارڈ کے ساتھ ہے۔
- تیسری فیلڈ ip_address کے نام سے بنائیں۔ اس کے لیے VAR CHAR ڈیٹا ٹائپ منتخب کریں، 25 کی گنجائش مقرر کریں، اور INDEX انڈیکس منتخب کریں۔
- چوتھی فیلڈ visit_datetime کے نام سے بنائیں جس کے لیے TIMESTAMP ڈیٹا ٹائپ منتخب کریں۔ اس فیلڈ میں کسی بھی صارف کے وزٹ کی تاریخ اور وقت محفوظ کیے جائیں گے۔ تیسری اور چوتھی فیلڈز کی مدد سے یہ معلوم کیا جائے گا کہ صارف کی گزشتہ اور حالیہ وزٹ میں وقت کا کتنا فرق ہے۔
دونوں ٹیبلز کا آپس میں ریلیشن بنائیں
اب ہم ان دونوں ڈیٹابیس ٹیبلز کا آپس میں ریلیشن قائم کریں گے۔ counter_profiles ٹیبل میں کسی بھی ویب سائیٹ کے لیے کاؤنٹر کا صرف ایک ریکارڈ محفوظ ہوگا۔ جبکہ ip_addresses ٹیبل میں اس ویب سائیٹ کے تمام صارفین کے آئی پی ایڈریسز محفوظ کیے جائیں گے۔ ان دونوں ٹیبلز کا آپس میں ریلیشن قائم کرنے کے لیے counter_profiles ٹیبل میں counter_profile_id فیلڈ کو بطور Primary key استعمال کیا گیا ہے، جبکہ ip_addresses ٹیبل میں counter_profile_id فیلڈ کو بطور Foreign key استعمال کیا جائے گا۔ ریلیشن قائم کرنے کا فائدہ یہ ہے کہ ip_addresses ٹیبل میں ریکارڈ داخل کرنے کے لیے ضروری ہے کہ counter_profiles ٹیبل میں اس کا بالائی ریکارڈ پہلے سے موجود ہو۔ نیز اگر بالائی ٹیبل counter_profiles میں سے کوئی ریکارڈ ڈیلیٹ کرنے کی ضرورت پیش آئے تو اس صورت میں آپ یہ بتا سکتے ہیں کہ ip_addresses ٹیبل میں اس کے ذیلی ریکارڈز کے ساتھ کیا سلوک کیا جائے۔
درج ذیل پہلے اسکرین شاٹ کے مطابق ip_addresses ٹیبل کھولیں اور پھر نیچے موجود Relation view لنک پر کلک کریں۔
دوسرے اسکرین شاٹ کے مطابق counter_profile_id کے سامنے موجود ڈراپ ڈاؤن مینیو میں سے بالائی ٹیبل counter_profiles کی اسی نام کی فیلڈ منتخب کریں۔ اور پھر Save بٹن پر کلک کر کے یہ ریلیشن بنا لیں۔
ڈیٹابیس میں ایک نئے کاؤنٹر کی پروفائل بنائیں
اب درج ذیل اسکرین شاٹ کے مطابق counter_profiles ٹیبل میں ایک نیا ریکارڈ داخل کریں۔ اس نئے بننے والے ریکارڈ میں counter_profile_id کا جو نمبر ہوگا، یہی نمبر ہم ویب پیج کے ایڈریس میں کاؤنٹر کی id کے طور پر استعمال کریں گے۔
2- PHP کوڈ کی وضاحت
درج ذیل کوڈ میں کامنٹس کی لائنوں کے ساتھ نمبر دیے گئے ہیں، ان نمبروں کے اعتبار سے کوڈ کی وضاحت دیکھیں۔
- پہلے یہ دیکھا گیا ہے کہ ویب سائیٹ کے ایڈریس کے ساتھ counterid مہیا کیا گیا ہے یا نہیں۔ کیونکہ یہی وہ نمبر ہے جس کی مدد سے ہم ڈیٹابیس میں سے اس ویب سائیٹ کے لیے کاؤنٹر کا ریکارڈ تلاش کریں گے۔
- پھر ڈیٹابیس کا کنکشن بنایا گیا ہے۔
- پھر ڈیٹابیس کے counter_profiles ٹیبل میں سے اس ویب سائیٹ کے کاؤنٹر کا ریکارڈ تلاش کیا گیا ہے۔
- ریکارڈ ملنے کی صورت میں اس ٹیبل کی ایک فیلڈ total_site_visits کی ویلیو اور دوسری فیلڈ total_page_visits کی ویلیو کو دو الگ ویری ایبلز میں حاصل کیا گیا ہے۔ ان ویلیوز کی مدد سے بعد میں کاؤنٹر کی امیج تیار کی جائے گی۔
- پھر یہ دیکھا گیا ہے کہ ڈیٹابیس کے ip_addresses ٹیبل میں صارف کا ip موجود ہے یا نہیں۔ اگر موجود ہے تو اس کا مطلب ہے کہ صارف پہلے بھی یہ ویب سائیٹ وزٹ کر چکا ہے۔ یہ وزٹ چند منٹ پہلے بھی ہو سکتی ہے اور چند دن پہلے بھی۔ پھر if-statement کے بلاک میں دیکھا گیا ہے کہ اگر صارف کی پچھلی وزٹ آج کے دن کی ہے، تو پھر صرف total_page_visits کے نمبر میں ایک کا اضافہ کیا گیا ہے۔ اور اگر صارف کی گزشتہ وزٹ آج کی نہیں تو پھر دونوں فیلڈز total_site_visits کے نمبر اور total_page_visits کے نمبر میں ایک کا اضافہ کیا گیا ہے۔
- اگر صارف کا ip ٹیبل میں موجود نہیں ہے تو اس کا مطلب یہ لیا گیا ہے کہ صارف کی یہ پہلی وزٹ ہے۔ چنانچہ ip_addresses ٹیبل میں صارف کا آئی پی ایڈریس داخل کیا گیا ہے، اور پھر counter_profiles ٹیبل میں دونوں فیلڈز کے نمبرز میں ایک ایک کا اضافہ کر دیا گیا ہے۔
- آخر میں آپ وہ کوڈ دیکھ رہے ہیں جس کی مدد سے کاؤنٹر کے لیے امیج تیار کی گئی ہے۔ اس میں ()header فنکشن قابل غور ہے جو یہ بتاتا ہے کہ PHP کے اس اسکرپٹ کا نتیجہ ویب پیج کے طور پر نہیں بلکہ امیج کے طور پر صارف کے براؤزر کی طرف بھیجا جائے گا۔
<?php
$total_site_visits = 0;
$total_page_visits = 0;
$datetime = date("Y-m-d h:i:s");
// (1) if counter id provided
if (isset($_GET["counterid"]) && is_numeric($_GET["counterid"])) {
$counter_profile_id = $_GET["counterid"];
// (2) database connection
$database_server = "localhost";
$username = "root";
$password = "";
$database = "web_counter";
$con = mysqli_connect($database_server, $username, $password, $database);
if (mysqli_connect_errno()) {
die('Error: ('. mysqli_connect_errno() .') '. mysqli_connect_error());
}
// (3) find counter profile in database
$counter_select = mysqli_query($con, "SELECT * FROM counter_profiles WHERE counter_profile_id = $counter_profile_id");
if ($counter_row = mysqli_fetch_assoc($counter_select)) {
// (4) variables of site and page visits
$total_site_visits = number_format($counter_row["total_site_visits"]);
$total_page_visits = number_format($counter_row["total_page_visits"]);
// (5) find visitor ip in database
$visitor_ip = $_SERVER["REMOTE_ADDR"];
$ip_select = mysqli_query($con, "SELECT * FROM ip_addresses WHERE counter_profile_id = $counter_profile_id AND ip_address = '$visitor_ip'");
// if ip found, then check if it is same-day visit or not
if ($ip_row = mysqli_fetch_assoc($ip_select)) {
$today_date = date("Y-m-d");
$last_visit_date = date_format(date_create($ip_row["visit_datetime"]), "Y-m-d");
// if same-day visit, then update only total_page_visits
if ($today_date == $last_visit_date) {
$counter_update = mysqli_query($con, "UPDATE counter_profiles SET total_page_visits = (total_page_visits+1) WHERE counter_profile_id = $counter_profile_id");
// if not same-day visit, then update both total_site_visits and total_page_visits
} else {
$counter_update = mysqli_query($con, "UPDATE counter_profiles SET total_site_visits = (total_site_visits+1), total_page_visits = (total_page_visits+1) WHERE counter_profile_id = $counter_profile_id");
$ip_update = mysqli_query($con, "UPDATE ip_addresses SET visit_datetime = '$datetime' WHERE counter_profile_id = $counter_profile_id AND ip_address = '$visitor_ip'");
}
// (6) ip not found
} else {
// insert this ip into 'ip_addresses' table
$ip_insert = mysqli_query($con, "INSERT INTO ip_addresses(counter_profile_id, ip_address, visit_datetime) VALUES($counter_profile_id, '$visitor_ip', '$datetime')");
// update total_site_visits and total_page_visits in 'counter_profiles' table
$counter_update = mysqli_query($con, "UPDATE counter_profiles SET total_site_visits = (total_site_visits+1), total_page_visits = (total_page_visits+1) WHERE counter_profile_id = $counter_profile_id");
}
}
mysqli_close($con);
}
// (7) generate image
$image = imagecreate(110, 30);
$bg_color = imagecolorallocate($image, 255, 255, 255);
$label_color = imagecolorallocate($image, 150, 150, 150);
$digits_color = imagecolorallocate($image, 0, 0, 0);
imagestring($image, 1, 5, 5, "Visits", $label_color);
imagestring($image, 1, 5, 18, "Page views", $label_color);
imagestring($image, 1, 60, 18, $total_page_visits, $digits_color);
imagestring($image, 1, 41, 5, $total_site_visits, $digits_color);
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
?>
3- براؤزر میں کاؤنٹر کا نتیجہ ٹیسٹ کریں
درج ذیل براؤزر کی ایڈریس بار میں جو لنک موجود ہے، اگرچہ یہ امیج ٹیگ میں استعمال کیا جائے گا، لیکن فوری طور پر ٹیسٹ کرنے کے لیے آپ اسے براؤزر میں دیکھ سکتے ہیں۔ یہ صفحہ بار بار ریفریش کرنے پر Page والی کی گنتی بڑھتی جائے گی، جبکہ Visits والی گنتی تب بڑھے گی جب اگلے دن آپ یہی لنک وزٹ کریں گے۔
جبکہ ویب سائیٹ میں یہ کاؤنٹر استعمال کرنے کے لیے درج ذیل امیج ٹیگ ویب پیجز میں شامل کرنا ہوگا۔ اس میں کاؤنٹر کا نمبر دراصل counter_profiles ٹیبل میں موجود counter_profile_id فیلڈ کی ویلیو ہے۔
<img src="http://www.new-counter-service.com/index.php?counterid=1">
4- مزید کام کی ضرورت
- یہ ایپلی کیشن تیار کرنے کے لیے مجھے اس طرح کی کسی دوسری ایپلی کیشن کا کوڈ دیکھنے کا موقع نہیں ملا، اس لیے اس میں بہتری کی کافی گنجائش ہو سکتی ہے۔ اس میں زیادہ تر انحصار ڈیٹابیس کالز پر ہے، اس لیے آپ اسے اپنے ہوسٹنگ اکاؤنٹ پر انسٹال کر کے چند ویب سائیٹس کے لیے استعمال کر سکتے ہیں۔ اگر آپ بہت زیادہ ویب سائیٹس کے لیے اس ایپلی کیشن کو استعمال کرنا چاہیں تو پھر شاید ایک الگ ہوسٹنگ اکاؤنٹ کی ضرورت پیش آئے گی جو صرف اس ایپلی کیشن کے لیے مخصوص ہو۔
- اگر آپ اس ایپلی کیشن کو بطور سروس استعمال کرنا چاہیں تو پھر آپ کو ایک رجسٹریشن فارم بنانا ہوگا تاکہ دیگر ویب سائیٹس والے اس فارم کے ذریعے کاؤنٹر کا کوڈ حاصل کر سکیں، اور پھر اس کوڈ کو اپنی ویب سائیٹس پر استعمال کر سکیں۔
- اور اگر آپ کاؤنٹر کی امیج کا فارمیٹ اس سے بہتر کرنا چاہیں تو اس کے لیے یہ ٹٹوریل دیکھیں۔
- وقت گزرنے کے ساتھ ڈیٹابیس کے ip_addresses ٹیبل میں ہزاروں یا ممکنہ طور پر لاکھوں ریکارڈز اکٹھے ہو سکتے ہیں۔ جبکہ ہمیں اس ایپلی کیشن کے لیے گزشتہ کل کے علاوہ کوئی ریکارڈز نہیں چاہئیں۔ اس مسئلے کا ایک حل یہ ہے کہ ایک PHP فائل میں ڈیٹابیس کیوئری لکھیں جو ip_addresses ٹیبل کے تمام ریکارڈز ڈیلیٹ کر دے۔ اور پھر اس فائل کو اپنے ہوسٹنگ پینل پر موجود ایک فیچر Cron job کے حوالے کر دیں جو اسے ایک مخصوص عرصے کے بعد مثلاً ہر ہفتے چلا دیا کرے گا۔
- آپ دیکھ رہے ہیں کہ میں نے (total_site_visits+1) استعمال کرتے ہوئے ڈیٹابیس فیلڈ کے نمبر میں ایک کا اضافہ کیا ہے، یعنی یہ کیلکولیشن ڈیٹابیس کے ذمے لگائی گئی ہے۔ ایسی ایپلی کیشنز جنہیں بڑے پیمانے پر استعمال کیا جانا ہو، ان میں ڈیٹابیس پر کم سے کم بوجھ ڈالا جاتا ہے۔ اس لیے کہ زیادہ تر ایپلی کیشنز کا ڈیٹابیس سرور ایک ہی ہوتا ہے، جبکہ ویب سرورز جن پر PHP کوڈ چلتا ہے وہ کئی ہو سکتے ہیں۔ چنانچہ بہتر طریقہ یہ ہے کہ PHP کوڈ میں نیا ویری ایبل بنائیں جس میں ایک نمبر کا اضافہ کیا گیا ہو، پھر اسے ڈیٹابیس کیوئری میں استعمال کریں۔
- ڈیٹابیس ٹیبل کی وہ فیلڈ جو آئی پی ایڈریس محفوظ کرنے کے لیے بنائی گئی ہے، اس کے لیے ہم نے VAR CHAR ڈیٹا ٹائپ منتخب کی ہے۔ لیکن کسی بڑی ایپلی کیشن میں استعمال ہونے والی ڈیٹابیس میں IPv4 اور IPv6 آئی پی ایڈریسز کو محفوظ کرنے کے لیے VARBINARY ڈیٹا ٹائپ 16 کی گنجائش کے ساتھ استعمال کی جاتی ہے اور اس مقصد کے لیے خاص فنکشنز INET6_ATON() اور INET6_NTOA() استعمال کیے جاتے ہیں۔
- اس ایپلی کیشن میں ایک اور فیچر شامل کیا جا سکتا ہے کہ صارف کے براؤزر اور آپریٹنگ سسٹم کے بارے میں بھی معلومات حاصل کر لی جائیں۔ براؤزر اور آپریٹنگ سسٹم کے نام اور ورژن نمبر محفوظ کرنے کے لیے ip_addresses ٹیبل میں چند فیلڈز کا اضافہ کرنا ہوگا۔ یہ معلومات PHP سے کیسے حاصل کی جا سکتی ہیں، اس کے لیے یہ ٹٹوریل دیکھیں۔
- نیز اس ایپلی کیشن کوڈ کے چلنے میں اگر کسی وقت کوئی Error واقع ہوا تو اس کا میسج صارف کے براؤزر کی طرف بھیج دیا جائے گا۔ اس صورت حال سے بچنے کے لیے آپ PHP کو اپنا فنکشن مہیا کر سکتے ہیں جو اس ایرر کا میسج آپ کو بذریعہ ای میل بھیج دے یا پھر کسی لاگ فائل میں درج کر دے۔ درج ذیل کوڈ اگر آپ ایپلی کیشن کے شروع میں شامل کر دیں گے تو پھر ایپلی کیشن میں پیدا ہونے والے ایرر کا میسج صارف کے براؤزر کی طرف نہیں بھیجا جائے گا، بلکہ اس فنکشن میں مہیا کیے گئے ای میل ایڈریس پر بھیج دیا جائے گا۔ لیکن آپ ڈیویلپمنٹ کے دوران شاید ایررز کی ای میلز وصول نہیں کرنا چاہیں گے۔ اس کے لیے ای میل والا کوڈ کامنٹ میں تبدیل کر دیں، اور اس کی جگہ آخر میں ایرر میسج پرنٹ کرنے والی لائن استعمال کریں۔
<?php
error_reporting(0);
function myErrorHandlerFunction($error_level, $error_message, $error_file, $error_line, $error_context) {
$error_details = "<b>Level: </b>" . $error_level . "<br><br>";
$error_details .= "<b>Message: </b>" . $error_message . "<br><br>";
$error_details .= "<b>File: </b>" . $error_file . "<br><br>";
$error_details .= "<b>Line: </b>" . $error_line . "<br><br>";
$error_details .= "<b>URL: </b>" . $_SERVER['REQUEST_URI'] . "<br><br>";
$to = "to.email.address@gmail.com";
$subject = "Web Counter: Error in $error_file";
$message = $error_details;
$from = "from.email.address@gmail.com";
$headers = "From: $from\r\n";
$headers .= "Content-type: text/html\r\n";
mail($to,$subject,$message,$headers);
// print $error_details;
}
set_error_handler("myErrorHandlerFunction");
?>
Modified: Tue, 05/08/2018 - 17:48