ANWBH

Members
  • عدد منشوراتي

    25
  • تاريخ الإنضمام

  • تاريخ اخر زياره

السمعه بالموقع

12 Good

عن العضو ANWBH

  • الرتبه
    مبدع مثابر
  • تاريخ الميلاد 01/24/91

معلومات عامة

  • الجنس
    ذكر
  • السكن
    Bahrain
  • هواياتي
    404

اخر الزوار

1344 زياره للملف الشخصي
  1. السلام عليكم ورحمة الله وبركاته.. في هذا الدرس الثالث من دروس النود جي اس سنقوم بتعلم كيفية ضبط ويب سيرفر NGINX للعمل مع تطبيقات / مايكرو سيرفس الNodeJS و تحويل requests الى بورتات تطبيقاتك بشكل ضمني ماهو الnginx؟ ببساطة هو بروكسي سيرفر عالي الاداء او ويب سيرفر، بديل الapache. في ماذا يستخدم؟ يستخدم في ريفيرس بروكسي للبروتوكولات HTTP, HTTPS, SMTP, IMAP, POP3 و كذلك لعمل توازن الضغط على السيرفر مثلا عندما يكون هناك عدد كبير جدا من الrequests تستطيع توزيع هذه الطلبات بالupstream بين عدة بورتات في نفس السيرفر او سيرفر خارجي مثلا اذا كان التطبيق او الموقع مبرمج بالNodeJS. بالعربي: لا تحاتي بتعرف كلشي بعد شوي. اولا: تثبيت الويب سيرفر. لتثبيت الويب سيرفر nginx اتبع التعليمات / الخطوات التالية: افتح التيرمنال وقم بإيقاف الapache اذا كان مثبت sudo /etc/init.d/apache stop حدث sudo apt-get update ثبت sudo apt-get install nginx تأكد ان الويب سيرفر يعمل sudo /etc/init.d/nginx status ملاحظة: مهم جدا ايقاف Apache قبل تثبيت Nginx ثانيا: تشغيل تطبيقك الNode على الدومين الرئيسي. لتشغيل التطبيق عليك تحويل جميع الطلبات requests التي تأتي من العميل الى الPort الذي يعمل عليه التطبيق (3000 مثلا) عبر الويب سيرفر NGINX. ولعمل ذلك، افتح التيرمنال و قم بمتابعة هذه الاوامر اذهب لمجلد الويب سيرفر cd /etc/ngin/sites-available اكتب ls وسترى ملف بإسم default. افتح الملف للتعديل بإستخدام vim او nano وفي هذا الدرس سنستخدم الاول sudo vim default امسح كلشي واكتب هذا الكود server { listen 80 default_server; listen [::]:80 default_server; server_name www.example.com example.com; access_log /path/to/log/static_domain_access.log; location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-NginX-Proxy true; proxy_pass http://127.0.0.1:3000; proxy_redirect off; } } اخيرا قم بإعادة تشغيل الويب سيرفر افتح المتصفح و اكتب موقعك http://www example.com Bonus إذا كان لديك تطبيق \ موقع كبير جدا او API و تريد عمل load balancing لتوزيع عمليه الطلبات في الصورتين ادناه الطريقة لذلك, لاحظ ان التطبيق يعمل على اكثر من بورت وكذلك الـproxy pass هو عباره عن اسم الـupstream .cluster تطبيق الNode كونفيقريشن الـNginx
  2. السلام عليكم ورحمة الله وبركاته.. في هذا الدرس الثالث من دروس النود جي اس سنقوم بتعلم كيفية ضبط ويب سيرفر NGINX للعمل مع تطبيقات / مايكرو سيرفس الNodeJS و تحويل requests الى بورتات تطبيقاتك بشكل ضمني ماهو الnginx؟ ببساطة هو بروكسي سيرفر عالي الاداء او ويب سيرفر، بديل الapache. في ماذا يستخدم؟ يستخدم في ريفيرس بروكسي للبروتوكولات HTTP, HTTPS, SMTP, IMAP, POP3 و كذلك لعمل توازن الضغط على السيرفر مثلا عندما يكون هناك عدد كبير جدا من الrequests تستطيع توزيع هذه الطلبات بالupstream بين عدة بورتات في نفس السيرفر او سيرفر خارجي مثلا اذا كان التطبيق او الموقع مبرمج بالNodeJS. بالعربي: لا تحاتي بتعرف كلشي بعد شوي. اولا: تثبيت الويب سيرفر. لتثبيت الويب سيرفر nginx اتبع التعليمات / الخطوات التالية: افتح التيرمنال وقم بإيقاف الapache اذا كان مثبت sudo /etc/init.d/apache stop حدث sudo apt-get update ثبت sudo apt-get install nginx تأكد ان الويب سيرفر يعمل sudo /etc/init.d/nginx status ملاحظة: مهم جدا ايقاف Apache قبل تثبيت Nginx ثانيا: تشغيل تطبيقك الNode على الدومين الرئيسي. لتشغيل التطبيق عليك تحويل جميع الطلبات requests التي تأتي من العميل الى الPort الذي يعمل عليه التطبيق (3000 مثلا) عبر الويب سيرفر NGINX. ولعمل ذلك، افتح التيرمنال و قم بمتابعة هذه الاوامر اذهب لمجلد الويب سيرفر cd /etc/ngin/sites-available اكتب ls وسترى ملف بإسم default. افتح الملف للتعديل بإستخدام vim او nano وفي هذا الدرس سنستخدم الاول sudo vim default امسح كلشي واكتب هذا الكود server { listen 80 default_server; listen [::]:80 default_server; server_name www.example.com example.com; access_log /path/to/log/static_domain_access.log; location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-NginX-Proxy true; proxy_pass http://127.0.0.1:3000; proxy_redirect off; } } اخيرا قم بإعادة تشغيل الويب سيرفر افتح المتصفح و اكتب موقعك http://www example.com Bonus إذا كان لديك تطبيق \ موقع كبير جدا او API و تريد عمل load balancing لتوزيع عمليه الطلبات في الصورتين ادناه الطريقة لذلك, لاحظ ان التطبيق يعمل على اكثر من بورت وكذلك الـproxy pass هو عباره عن اسم الـupstream .cluster تطبيق الNode كونفيقريشن الـNginx
  3. السلام عليكم و رحمة الله و بركاته .. عودة الى الجزء الاول، وضحت كيفية ارسال بيانات من تطبيق الNode الى Pug وكيفية استقبال البيانات في الطرف الاخر و عرضها. في هذا الدرس سنتعامل مع قاعدة البيانات ونرسل البيانات بطريقتين مختلفتين: سيتم ارسال جميع البيانات من احد الجداول الى الواجهة و سأعرض لكم طريقة التعامل مع هذا النوع من البيانات المرسله سننشأه items عباره عن json objects وبعدها نرسلهم. الطريقة الأولى: و بالحديث عن قواعد البيانات، سنستخدم قاعدة بيانات MySQL هذه المره ( الرجاء الرجوع للدرس الاول للحصول على كافة التجهيزات لهذا الدرس). / هنا , انشأ قاعدة بيانات بإسم company وجدول employees مثلا ومن ثم اضف هذه المدخلات. -- phpMyAdmin SQL Dump -- version 4.5.4.1deb2ubuntu2 -- http://www.phpmyadmin.net -- -- Host: localhost -- Generation Time: Jun 09, 2017 at 10:41 AM -- Server version: 5.7.18-0ubuntu0.16.04.1 -- PHP Version: 7.1.5-1+deb.sury.org~xenial+2 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Database: `company` -- -- -------------------------------------------------------- -- -- Table structure for table `employees` -- CREATE TABLE `employees` ( `ID` int(11) NOT NULL, `name` text COLLATE utf8_unicode_ci NOT NULL, `position` text COLLATE utf8_unicode_ci NOT NULL, `office` text COLLATE utf8_unicode_ci NOT NULL, `age` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- -- Dumping data for table `employees` -- INSERT INTO `employees` (`ID`, `name`, `position`, `office`, `age`) VALUES (1, 'Airi Satou', 'Accountant', 'Tokyo', 23), (2, 'Airi Satou', 'Accountant', 'Tokyo', 23), (3, 'Donna Snider', 'Customer Support', 'New York', 27), (4, 'Brenden Wagner', 'Software Engineer', 'San Francisco', 28), (5, 'Caesar Vance', 'Pre-Sales Support', 'New York', 23), (6, 'Cedric Kelly', 'Senior Javascript Developer', 'Edinburgh', 22), (7, 'Dai Rios', 'Personnel Lead', 'Edinburgh', 35); -- -- Indexes for dumped tables -- -- -- Indexes for table `employees` -- ALTER TABLE `employees` ADD PRIMARY KEY (`ID`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `employees` -- ALTER TABLE `employees` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; افتح ملف app.js و انشأ هذا الاوبجكت لعمل connection بين التطبيق وقاعدة البيانات // connection var connection = mysql.createConnection({ host : 'localhost', user : '...', password : '...', database : 'db_name' }); بعد ذلك، سنقوم بتعديل صفحة الـdetails في ملف app.js - المسار الذي يعرض صفحة الـdetails - لعمل Selection query app.get('/details', function(req, res) { connection.query('SELECT * From `employees`', function (error, results, fields) { if (error) throw error; console.log('The solution is: ', results); res.render('details', { title: 'Details - Pug ExpressJS NodeJS Tutorial', employees: results }); }); }); الـsyntax بسيط جدا، اولا connection وهو متغير التوصيل مم ثم query ثابته بعد ذلك الكويري &nbsp;ومن ثم الارقيومنتس (لمعلومات اكثر تجدونها هنا https://github.com/mysqljs/mysql/blob/master/Readme.md ) مخرجات اي query دائما ما يكون json object بالتالي متغير results هو عباره عن list of objects [ { "prop1":"value1", "prop2":"value2" }, { "prop1":"value3", "prop2":"value4" } ] نرجع إلى ملف details.pug ونقوم بتعديل block الجدول إلى التالي table#example.display.nowrap.dataTable.dtr-inline.collapsed(cellspacing='0') thead tr(role='row') th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Name: activate to sort column ascending', style='width: 142px;') Name th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Position: activate to sort column ascending', style='width: 192px;') Position th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Office: activate to sort column ascending', style='width: 89px;') Office th.dt-body-right.sorting_asc(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Age: activate to sort column descending', style='width: 37px;', aria-sort='ascending') Age tfoot tr th(rowspan='1', colspan='1') Name th(rowspan='1', colspan='1') Position th(rowspan='1', colspan='1') Office th.dt-body-right(rowspan='1', colspan='1') Age tbody for employee in employees tr.odd(role='row') td #{employee.name} td #{employee.position} td #{employee.office} td.dt-body-right.sorting_1 #{employee.age} نلاحظ وجود الـfor loop و طريقة استقبال وعرض المعلومات بسطر واحد فقط و ترجمته حرفيا ان لكل موظف في اوبجكت الموظفين ( الذي ارسلناه من الـNode ) قم بعمل صف في الجدول واضف مابعده for employee in employees tr.odd(role='row') td #{employee.name} td #{employee.position} td #{employee.office} td.dt-body-right.sorting_1 #{employee.age} بهذا انتهينا من الجزء الأول للدرس وننتقل للجزء الثاني: هذا الجزء من الدرس يتعلق بكيفية عمل items بشكل تخصيصي .. ان ماذا لو انك لا تريد ان تضم عمر الموظف في جدول العرض؟ سنقوم بالتالي في ملف app.js و details.pug - وكلشئ آخر يبقى كما هو: //app.js app.get('/details', function (req, res) { connection.query('SELECT * From `employees`', function (error, results, fields) { if (error) { throw error; } else { console.log('The solution is: ', results); var employees_json = []; for (var index = 0; index < results.length; index++) { var item = { name: results[index].name, position: results[index].position, office: results[index].office } employees_json.push(item); } res.render('details', { title: 'Details - Pug ExpressJS NodeJS Tutorial', employees: employees_json }); } }); }); //details.pug table#example.display.nowrap.dataTable.dtr-inline.collapsed(cellspacing='0') thead tr(role='row') th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Name: activate to sort column ascending', style='width: 142px;') Name th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Position: activate to sort column ascending', style='width: 192px;') Position th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Office: activate to sort column ascending', style='width: 89px;') Office //th.dt-body-right.sorting_asc(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Age: activate to sort column descending', style='width: 37px;', aria-sort='ascending') Age tfoot tr th(rowspan='1', colspan='1') Name th(rowspan='1', colspan='1') Position th(rowspan='1', colspan='1') Office th.dt-body-right(rowspan='1', colspan='1') Age tbody for employee in employees tr.odd(role='row') td #{employee.name} td #{employee.position} td #{employee.office} //td.dt-body-right.sorting_1 #{employee.age} إضغط هنا لتحميل ملفات الدرس الثاني anwbh-app-lesson2.zip
  4. السلام عليكم و رحمة الله و بركاته .. عودة الى الجزء الاول، وضحت كيفية ارسال بيانات من تطبيق الNode الى Pug وكيفية استقبال البيانات في الطرف الاخر و عرضها. في هذا الدرس سنتعامل مع قاعدة البيانات ونرسل البيانات بطريقتين مختلفتين: سيتم ارسال جميع البيانات من احد الجداول الى الواجهة و سأعرض لكم طريقة التعامل مع هذا النوع من البيانات المرسله سننشأه items عباره عن json objects وبعدها نرسلهم. الطريقة الأولى: و بالحديث عن قواعد البيانات، سنستخدم قاعدة بيانات MySQL هذه المره ( الرجاء الرجوع للدرس الاول للحصول على كافة التجهيزات لهذا الدرس). / هنا , انشأ قاعدة بيانات بإسم company وجدول employees مثلا ومن ثم اضف هذه المدخلات. -- phpMyAdmin SQL Dump -- version 4.5.4.1deb2ubuntu2 -- http://www.phpmyadmin.net -- -- Host: localhost -- Generation Time: Jun 09, 2017 at 10:41 AM -- Server version: 5.7.18-0ubuntu0.16.04.1 -- PHP Version: 7.1.5-1+deb.sury.org~xenial+2 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Database: `company` -- -- -------------------------------------------------------- -- -- Table structure for table `employees` -- CREATE TABLE `employees` ( `ID` int(11) NOT NULL, `name` text COLLATE utf8_unicode_ci NOT NULL, `position` text COLLATE utf8_unicode_ci NOT NULL, `office` text COLLATE utf8_unicode_ci NOT NULL, `age` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; -- -- Dumping data for table `employees` -- INSERT INTO `employees` (`ID`, `name`, `position`, `office`, `age`) VALUES (1, 'Airi Satou', 'Accountant', 'Tokyo', 23), (2, 'Airi Satou', 'Accountant', 'Tokyo', 23), (3, 'Donna Snider', 'Customer Support', 'New York', 27), (4, 'Brenden Wagner', 'Software Engineer', 'San Francisco', 28), (5, 'Caesar Vance', 'Pre-Sales Support', 'New York', 23), (6, 'Cedric Kelly', 'Senior Javascript Developer', 'Edinburgh', 22), (7, 'Dai Rios', 'Personnel Lead', 'Edinburgh', 35); -- -- Indexes for dumped tables -- -- -- Indexes for table `employees` -- ALTER TABLE `employees` ADD PRIMARY KEY (`ID`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `employees` -- ALTER TABLE `employees` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; افتح ملف app.js و انشأ هذا الاوبجكت لعمل connection بين التطبيق وقاعدة البيانات // connection var connection = mysql.createConnection({ host : 'localhost', user : '...', password : '...', database : 'db_name' }); بعد ذلك، سنقوم بتعديل صفحة الـdetails في ملف app.js - المسار الذي يعرض صفحة الـdetails - لعمل Selection query app.get('/details', function(req, res) { connection.query('SELECT * From `employees`', function (error, results, fields) { if (error) throw error; console.log('The solution is: ', results); res.render('details', { title: 'Details - Pug ExpressJS NodeJS Tutorial', employees: results }); }); }); الـsyntax بسيط جدا، اولا connection وهو متغير التوصيل مم ثم query ثابته بعد ذلك الكويري &nbsp;ومن ثم الارقيومنتس (لمعلومات اكثر تجدونها هنا https://github.com/mysqljs/mysql/blob/master/Readme.md ) مخرجات اي query دائما ما يكون json object بالتالي متغير results هو عباره عن list of objects [ { "prop1":"value1", "prop2":"value2" }, { "prop1":"value3", "prop2":"value4" } ] نرجع إلى ملف details.pug ونقوم بتعديل block الجدول إلى التالي table#example.display.nowrap.dataTable.dtr-inline.collapsed(cellspacing='0') thead tr(role='row') th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Name: activate to sort column ascending', style='width: 142px;') Name th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Position: activate to sort column ascending', style='width: 192px;') Position th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Office: activate to sort column ascending', style='width: 89px;') Office th.dt-body-right.sorting_asc(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Age: activate to sort column descending', style='width: 37px;', aria-sort='ascending') Age tfoot tr th(rowspan='1', colspan='1') Name th(rowspan='1', colspan='1') Position th(rowspan='1', colspan='1') Office th.dt-body-right(rowspan='1', colspan='1') Age tbody for employee in employees tr.odd(role='row') td #{employee.name} td #{employee.position} td #{employee.office} td.dt-body-right.sorting_1 #{employee.age} نلاحظ وجود الـfor loop و طريقة استقبال وعرض المعلومات بسطر واحد فقط و ترجمته حرفيا ان لكل موظف في اوبجكت الموظفين ( الذي ارسلناه من الـNode ) قم بعمل صف في الجدول واضف مابعده for employee in employees tr.odd(role='row') td #{employee.name} td #{employee.position} td #{employee.office} td.dt-body-right.sorting_1 #{employee.age} بهذا انتهينا من الجزء الأول للدرس وننتقل للجزء الثاني: هذا الجزء من الدرس يتعلق بكيفية عمل items بشكل تخصيصي .. ان ماذا لو انك لا تريد ان تضم عمر الموظف في جدول العرض؟ سنقوم بالتالي في ملف app.js و details.pug - وكلشئ آخر يبقى كما هو: //app.js app.get('/details', function (req, res) { connection.query('SELECT * From `employees`', function (error, results, fields) { if (error) { throw error; } else { console.log('The solution is: ', results); var employees_json = []; for (var index = 0; index < results.length; index++) { var item = { name: results[index].name, position: results[index].position, office: results[index].office } employees_json.push(item); } res.render('details', { title: 'Details - Pug ExpressJS NodeJS Tutorial', employees: employees_json }); } }); }); //details.pug table#example.display.nowrap.dataTable.dtr-inline.collapsed(cellspacing='0') thead tr(role='row') th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Name: activate to sort column ascending', style='width: 142px;') Name th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Position: activate to sort column ascending', style='width: 192px;') Position th.sorting(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Office: activate to sort column ascending', style='width: 89px;') Office //th.dt-body-right.sorting_asc(tabindex='0', aria-controls='example', rowspan='1', colspan='1', aria-label='Age: activate to sort column descending', style='width: 37px;', aria-sort='ascending') Age tfoot tr th(rowspan='1', colspan='1') Name th(rowspan='1', colspan='1') Position th(rowspan='1', colspan='1') Office th.dt-body-right(rowspan='1', colspan='1') Age tbody for employee in employees tr.odd(role='row') td #{employee.name} td #{employee.position} td #{employee.office} //td.dt-body-right.sorting_1 #{employee.age} إضغط هنا لتحميل ملفات الدرس الثاني anwbh-app-lesson2.zip
  5. السلام عليكم و رحمة الله و بركاته.. في هذا الموضوع سنتحدث عن عن علاقة إطار العمل ExpressJS مع الباترن NodeJS و كيفية عمل Pug as template engine اولا: حتى لا تكون هناك امور مبهمه و ابعاد الغيوم التي تدور حول اذهان الكثير من يريد العمل او التوجه لهذا الباترن يجب عرض بعض من الحقائق: الـNodeJS ليست لغة جديدة .. انما بيئة مبرمجة بالـJS. هذه البيئه تعمل في جهة السيرفر. ان كنت مبرمج AngularJS or ReactJS ليس هناك سطر محدد تربط فيه بين تطبيقك الNode مع الفريموورك الذي تعمل به. طريقة الربط تكون من خلال HTTP requests. تستطيع التعامل مع قواعد البيانات المختلفه مباشره بالـNode مثل MySQL, MariaDB و اشهرهم في هذا المجال هي MongoDB. نعود مرة اخرى للـExpressJS الذي هو يعتبر فريم وورك ابعد مما ان يقال عنه "مساعد" في تطبيقات الـNode. بإستخدام هذا الفريم وورك الذي يعمل كذلك في السيرفر، يتم تسهيل العمل و كمية الكود في تطبيق الـNode بشكل كبير جدا. مثال على تطبيق Node بإستخدام فريم وورك ExpressJS وسيتم شرح اجزائه جميعها var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!') }); app.listen(3000, function () { console.log('Example app listening on port 3000!') }); اول سطرين استدعاء موديول الاكسبرس و من ثم دالة الاكسبرس في المتغير app الذي استخدمناه في صنع التطبيق. الشطر الثاني get هو عبارة عن نوع الـhttp request قد يكون GET, POST, DELETE, UPDATE etc …. بعد ذلك يأتي المسار - لتفاصيل اكثر حول هذا الجزء الرجاء زيارة الدرس السابق. نننقل الآن الى امر اخر في الـExpressJS وهو الـtemplating ( عمل الواجهات UI و استقبال البيانات المرسلة من الـNode ) لعمل الواجهات الديناميكيه يفضل استخدام محركات التمبليت التي تتوافق مع الاكسبرس وهي PUG - know as Jade Mustache EJS و في هذا الدرس سنستخدم المحرك الاول لعمل صفحة ويب اعتيادية و اخرى ديناميكية, لصنع واجهة بمحرك التمبليت pug يجب عليك ان تتقن او ان تاخذ فكره عن هذا المحرك لتعرف كيفية كتابه الكود ومثال على ذلك doctype html html(lang='en') head title Jade script(type='text/javascript'). foo = true; bar = function () {}; if (foo) { bar(1 + 5) } body h1 Jade - node template engine #container.col p You are amazing p | Jade is a terse and simple | templating language with a | strong focus on performance | and powerful features. يعادل في الHTML <!DOCTYPE html> <html lang="en"> <head> <title>Jade</title> <script type="text/javascript"> foo = true; bar = function () {}; if (foo) { bar(1 + 5) } </script> </head> <body> <h1>Jade - node template engine</h1> <div id="container" class="col"> <p>You are amazing</p> <p> Jade is a terse and simple templating language with a strong focus on performance and powerful features. </p> </div> </body> </html> لمعلومات اكثر حول اللغة اطلع على موقعهم الرسمي وبذلك سنقوم بإنشاء مجلدات ومستندات بهذه الطريقة حمل الـbootstrap وانقل كل من bootstrap.min.css إلى مجلد css , انقل bootstrap.min.js إلى مجلد js بعد ذلك إبدأ بتثبيت الـpackages التي سنعمل بها من خلال فتح الـterminal في مجلد myapp من خلال الاوامر التالية $ npm install express --save $ npm install cookie-parser --save $ npm install body-parser --save $ npm install mysql --save افتح ملف التطبيق app.js وقم بإستدعاء هذه البكجات var express = require('express'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var mysql = require('mysql'); الآن نبدأ بإعداد config فريم وورك الـExpressJS مع cookie-parser body-parser ( سنستخدمهم لاحقا ) var router = express.Router(); var app = express(); app.use(bodyParser.json({limit: "50mb"})); app.use(cookieParser()); var urlencodedParser = bodyParser.urlencoded({ extended: true, parameterLimit:50000 }); app.use("/", router); نضيف امكانية استخدام ملفات الـcss, js , images etc من خلال استخدام الـmiddleware ـexpress static بإعطاء مسار وهمي لهذه الملفات app.use('/css', express.static(__dirname + '/public/css')); app.use('/js', express.static(__dirname + '/public/js')); نرى وجود ملفات الـcss and js في مجلد public/css ولكن المسار الذي سنكتبه في الكود هو فقط css/ وليس بالضرورة ان يكون اسم المسار الوهمي ذو علاقه بالمسار الاساسي .. تستطيع ان تسميه مثلا sambosa/ و في الحقيقة هو public/css/ تحديد نوع الـtemplate engine الذي سنستخدمه في هذا التطبيق مع تحديد مسار مجلد الـviews الذي يحتوي على صفحات الموقع او التطبيق app.set('views', __dirname + '/views'); app.set('view engine', 'pug'); بعد إنشاء ملفات الـpug في إحدى الخطوات السابقه , انسخ والصق كود الصفحتين index.pug and layout.pug details.pug كلن على حدى //layout.pug doctype html html head title= title script(src='https://code.jquery.com/jquery-3.2.1.min.js') link(rel='stylesheet', href='/css/bootstrap.min.css') script(src='/js/bootstrap.min.js') body nav.navbar.navbar-default .container .navbar-header button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#navbar', aria-expanded='false', aria-controls='navbar') span.sr-only Toggle navigation span.icon-bar span.icon-bar span.icon-bar a.navbar-brand(href='/') NodeJS #navbar.navbar-collapse.collapse ul.nav.navbar-nav li.active a(href='/') Home li a(href='/details') details li.dropdown a.dropdown-toggle(href='#', data-toggle='dropdown', role='button', aria-haspopup='true', aria-expanded='false') | Dropdown span.caret ul.dropdown-menu li a(href='#') Action li a(href='#') Another action li a(href='#') Something else here li.divider(role='separator') li.dropdown-header Nav header li a(href='#') Separated link li a(href='#') One more separated link block content //index.pug extends layout block content .container h1 #{msg} p #{username} , welcome to the first templating tutorial //details.pug extends layout block content .container .table-responsive h2 user table p This is all users we have so far table.table.table-bordered#example thead tr th Firstname th Lastname th Email tbody tr td John td Doe td john@example.com tr td Mary td Moe td mary@example.com tr td July td Dooley td july@example.com link(rel='stylesheet', type='text/css', href='https://cdn.datatables.net/v/dt/dt-1.10.15/datatables.min.css') script(type='text/javascript', src='https://cdn.datatables.net/v/dt/dt-1.10.15/datatables.min.js') script(). $(document).ready(function() { $('#example').DataTable(); }); ملاحظة: نستخدم extends layout لكي لا نكرر الـhead في الصفحات الاخرى , مثل include في الـPHP ( في هذا الدرس ) - الاستخدام الحقيقي للـlayout هو تصميم شكل معين لصفحات معينه .. كـtemplate خاص مثلا - معلومات اكثر من خلال الرابط هنا الأن تم تجهيز المستوى الأول من التطبيق وهو الـconfigurations , ننتقل إلى النص الآخر وهو الـroutes . اولا route الصفحة الرئيسية سيكون كالتالي app.get('/', function(req, res) { res.render('index', { title: 'Pug ExpressJS NodeJS Tutorial', username: 'abdulla', msg: 'Hey There!' }) }); نلاحظ ان مسار الـroute هو مجرد slash للامام .. بذلك يتم تحديد المسار الرئيسي للتطبيق, بعد ذلك res.render اي تعني response render حيث يقوم تطبيق الـNode بالأجابة من بعد عمل طلب request من طرف المستخدم , للتوضيح اكثر الـHTTP هو عباره عن بروتوكول طلب و اجابة وبذلك request and response - req, res فعند طلب العميل امر ما يجب عليه ان يحصل على شي ما في المقابل. و كما موضع في الدالة اعلاه ان الـresponse هو عباره عن عمل render لملف index.pug الموجود في مجلد views مع ارسال ثلاث متغيرات title, username and msg , و طريقة استقبال البيانات في الـpug هي كالتالي ( يوجد اكثر من طريقة ) h1 #{username} p Welcome to #{title} خطوة اخيره لتشغيل التطبيق يجب تحديد بورت معين ولنفترض 3000 app.listen(3000, function() { console.log('The app is running http://localhost:3000'); }); افتح الـterminal داخل مجلد التطبيق myapp واكتب الامر التالي لتشغيل التطبيق node app.js افتح المتطفح على المسار انتهى الدرس الاول .. تم من خلاله عمل configuration لتطبيق الـnode الذي سنستخدمه في الدروس القادمة تثبيت template engine و توصيله مع تطبيق الـNode ارسال بيانات من الـNode إلى pug الدرس القادم سيكون هناك سنعرض لكم كيفية التعامل مع قواعد البيانات وإرسال المعلومات الى pug للحصول على ملفات العمل تجدونهم في المرفقات, بعد تحميل الملف قم بفك الضغط انتقل إلى داخل المجلد واكتب الأمر التالي لتثبيت جميع الـpackages دفعة واحده $ npm install --save أضغط هنا لتحميل ملفات العمل anwbh-app.zip موقع مساعد لتحويل كودات الـHTML إلى Pug http://html2jade.org
  6. السلام عليكم و رحمة الله و بركاته.. في هذا الموضوع سنتحدث عن عن علاقة إطار العمل ExpressJS مع الباترن NodeJS و كيفية عمل Pug as template engine اولا: حتى لا تكون هناك امور مبهمه و ابعاد الغيوم التي تدور حول اذهان الكثير من يريد العمل او التوجه لهذا الباترن يجب عرض بعض من الحقائق: الـNodeJS ليست لغة جديدة .. انما بيئة مبرمجة بالـJS. هذه البيئه تعمل في جهة السيرفر. ان كنت مبرمج AngularJS or ReactJS ليس هناك سطر محدد تربط فيه بين تطبيقك الNode مع الفريموورك الذي تعمل به. طريقة الربط تكون من خلال HTTP requests. تستطيع التعامل مع قواعد البيانات المختلفه مباشره بالـNode مثل MySQL, MariaDB و اشهرهم في هذا المجال هي MongoDB. نعود مرة اخرى للـExpressJS الذي هو يعتبر فريم وورك ابعد مما ان يقال عنه "مساعد" في تطبيقات الـNode. بإستخدام هذا الفريم وورك الذي يعمل كذلك في السيرفر، يتم تسهيل العمل و كمية الكود في تطبيق الـNode بشكل كبير جدا. مثال على تطبيق Node بإستخدام فريم وورك ExpressJS وسيتم شرح اجزائه جميعها var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!') }); app.listen(3000, function () { console.log('Example app listening on port 3000!') }); اول سطرين استدعاء موديول الاكسبرس و من ثم دالة الاكسبرس في المتغير app الذي استخدمناه في صنع التطبيق. الشطر الثاني get هو عبارة عن نوع الـhttp request قد يكون GET, POST, DELETE, UPDATE etc …. بعد ذلك يأتي المسار - لتفاصيل اكثر حول هذا الجزء الرجاء زيارة الدرس السابق. نننقل الآن الى امر اخر في الـExpressJS وهو الـtemplating ( عمل الواجهات UI و استقبال البيانات المرسلة من الـNode ) لعمل الواجهات الديناميكيه يفضل استخدام محركات التمبليت التي تتوافق مع الاكسبرس وهي PUG - know as Jade Mustache EJS و في هذا الدرس سنستخدم المحرك الاول لعمل صفحة ويب اعتيادية و اخرى ديناميكية, لصنع واجهة بمحرك التمبليت pug يجب عليك ان تتقن او ان تاخذ فكره عن هذا المحرك لتعرف كيفية كتابه الكود ومثال على ذلك doctype html html(lang='en') head title Jade script(type='text/javascript'). foo = true; bar = function () {}; if (foo) { bar(1 + 5) } body h1 Jade - node template engine #container.col p You are amazing p | Jade is a terse and simple | templating language with a | strong focus on performance | and powerful features. يعادل في الHTML <!DOCTYPE html> <html lang="en"> <head> <title>Jade</title> <script type="text/javascript"> foo = true; bar = function () {}; if (foo) { bar(1 + 5) } </script> </head> <body> <h1>Jade - node template engine</h1> <div id="container" class="col"> <p>You are amazing</p> <p> Jade is a terse and simple templating language with a strong focus on performance and powerful features. </p> </div> </body> </html> لمعلومات اكثر حول اللغة اطلع على موقعهم الرسمي وبذلك سنقوم بإنشاء مجلدات ومستندات بهذه الطريقة حمل الـbootstrap وانقل كل من bootstrap.min.css إلى مجلد css , انقل bootstrap.min.js إلى مجلد js بعد ذلك إبدأ بتثبيت الـpackages التي سنعمل بها من خلال فتح الـterminal في مجلد myapp من خلال الاوامر التالية $ npm install express --save $ npm install cookie-parser --save $ npm install body-parser --save $ npm install mysql --save افتح ملف التطبيق app.js وقم بإستدعاء هذه البكجات var express = require('express'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var mysql = require('mysql'); الآن نبدأ بإعداد config فريم وورك الـExpressJS مع cookie-parser body-parser ( سنستخدمهم لاحقا ) var router = express.Router(); var app = express(); app.use(bodyParser.json({limit: "50mb"})); app.use(cookieParser()); var urlencodedParser = bodyParser.urlencoded({ extended: true, parameterLimit:50000 }); app.use("/", router); نضيف امكانية استخدام ملفات الـcss, js , images etc من خلال استخدام الـmiddleware ـexpress static بإعطاء مسار وهمي لهذه الملفات app.use('/css', express.static(__dirname + '/public/css')); app.use('/js', express.static(__dirname + '/public/js')); نرى وجود ملفات الـcss and js في مجلد public/css ولكن المسار الذي سنكتبه في الكود هو فقط css/ وليس بالضرورة ان يكون اسم المسار الوهمي ذو علاقه بالمسار الاساسي .. تستطيع ان تسميه مثلا sambosa/ و في الحقيقة هو public/css/ تحديد نوع الـtemplate engine الذي سنستخدمه في هذا التطبيق مع تحديد مسار مجلد الـviews الذي يحتوي على صفحات الموقع او التطبيق app.set('views', __dirname + '/views'); app.set('view engine', 'pug'); بعد إنشاء ملفات الـpug في إحدى الخطوات السابقه , انسخ والصق كود الصفحتين index.pug and layout.pug details.pug كلن على حدى //layout.pug doctype html html head title= title script(src='https://code.jquery.com/jquery-3.2.1.min.js') link(rel='stylesheet', href='/css/bootstrap.min.css') script(src='/js/bootstrap.min.js') body nav.navbar.navbar-default .container .navbar-header button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#navbar', aria-expanded='false', aria-controls='navbar') span.sr-only Toggle navigation span.icon-bar span.icon-bar span.icon-bar a.navbar-brand(href='/') NodeJS #navbar.navbar-collapse.collapse ul.nav.navbar-nav li.active a(href='/') Home li a(href='/details') details li.dropdown a.dropdown-toggle(href='#', data-toggle='dropdown', role='button', aria-haspopup='true', aria-expanded='false') | Dropdown span.caret ul.dropdown-menu li a(href='#') Action li a(href='#') Another action li a(href='#') Something else here li.divider(role='separator') li.dropdown-header Nav header li a(href='#') Separated link li a(href='#') One more separated link block content //index.pug extends layout block content .container h1 #{msg} p #{username} , welcome to the first templating tutorial //details.pug extends layout block content .container .table-responsive h2 user table p This is all users we have so far table.table.table-bordered#example thead tr th Firstname th Lastname th Email tbody tr td John td Doe td john@example.com tr td Mary td Moe td mary@example.com tr td July td Dooley td july@example.com link(rel='stylesheet', type='text/css', href='https://cdn.datatables.net/v/dt/dt-1.10.15/datatables.min.css') script(type='text/javascript', src='https://cdn.datatables.net/v/dt/dt-1.10.15/datatables.min.js') script(). $(document).ready(function() { $('#example').DataTable(); }); ملاحظة: نستخدم extends layout لكي لا نكرر الـhead في الصفحات الاخرى , مثل include في الـPHP ( في هذا الدرس ) - الاستخدام الحقيقي للـlayout هو تصميم شكل معين لصفحات معينه .. كـtemplate خاص مثلا - معلومات اكثر من خلال الرابط هنا الأن تم تجهيز المستوى الأول من التطبيق وهو الـconfigurations , ننتقل إلى النص الآخر وهو الـroutes . اولا route الصفحة الرئيسية سيكون كالتالي app.get('/', function(req, res) { res.render('index', { title: 'Pug ExpressJS NodeJS Tutorial', username: 'abdulla', msg: 'Hey There!' }) }); نلاحظ ان مسار الـroute هو مجرد slash للامام .. بذلك يتم تحديد المسار الرئيسي للتطبيق, بعد ذلك res.render اي تعني response render حيث يقوم تطبيق الـNode بالأجابة من بعد عمل طلب request من طرف المستخدم , للتوضيح اكثر الـHTTP هو عباره عن بروتوكول طلب و اجابة وبذلك request and response - req, res فعند طلب العميل امر ما يجب عليه ان يحصل على شي ما في المقابل. و كما موضع في الدالة اعلاه ان الـresponse هو عباره عن عمل render لملف index.pug الموجود في مجلد views مع ارسال ثلاث متغيرات title, username and msg , و طريقة استقبال البيانات في الـpug هي كالتالي ( يوجد اكثر من طريقة ) h1 #{username} p Welcome to #{title} خطوة اخيره لتشغيل التطبيق يجب تحديد بورت معين ولنفترض 3000 app.listen(3000, function() { console.log('The app is running http://localhost:3000'); }); افتح الـterminal داخل مجلد التطبيق myapp واكتب الامر التالي لتشغيل التطبيق node app.js افتح المتطفح على المسار انتهى الدرس الاول .. تم من خلاله عمل configuration لتطبيق الـnode الذي سنستخدمه في الدروس القادمة تثبيت template engine و توصيله مع تطبيق الـNode ارسال بيانات من الـNode إلى pug الدرس القادم سيكون هناك سنعرض لكم كيفية التعامل مع قواعد البيانات وإرسال المعلومات الى pug للحصول على ملفات العمل تجدونهم في المرفقات, بعد تحميل الملف قم بفك الضغط انتقل إلى داخل المجلد واكتب الأمر التالي لتثبيت جميع الـpackages دفعة واحده $ npm install --save أضغط هنا لتحميل ملفات العمل anwbh-app.zip موقع مساعد لتحويل كودات الـHTML إلى Pug http://html2jade.org
  7. السلام عليكم ورحمة الله وبركاته .. من بعد المقدمة حول قاعدة بيانات الـMongoDB حيث تم التعرف على: ما نوع قاعدة البيانات. كيفية تخزين البيانات فيها. العمليات البسيطة منها الـfind. الفروقات السطيحة مابين الـMongoDB و قواعد البيانات الأخرى من نوع RDBMS. لماذا انصح بالتحول إلى هذا النوع من قواعد البيانات. إذا , اصبح هناك نظرة شاملة حول هذا النوع من قواعد البيانات و في هذا الدرس سنبدأ بأول العمليات المهمة والاساسية التي تسمى بـCRUD اختصارا إلى: Create Read Update Delete نبدأ بسمه تعالى, افتح الـCMD او الـTerminal و اكتب الكوماند التالي لتفعيل خدمة الـMongoDB في جهازك بعد ذلك افتح CMD آخر واكتب الكوماند التالي للدخول على MongoDB Shell بعد الدخول على الـMongoDB Shell لمعلومات اكثر اكتب help لندا بتصفح قواعد البيانات الموجوده مسبقا في بكتابه show dbs ستظهر قاعدة بيانات واحده اسمها local تحتوي على collection بإسم startup_log وهنا ننوه مره اخرى بأن: اسم الـTable في الـMongoDB هو Collection اسم الـRow في الـMongoDB هو Document قم بإنشاء قاعدة بيانات جديدة و اختارها من خلال كوماند واحد و DATABASE_NAME تعني اسم قاعدة البيانات التي تريد عملها ولنفترض abdullashop بعد انشاء قاعدة البيانات واختيارها نبدأ الآن بعمل collection بإسم مثلا customers db.createCollection("customers") //results /* { "ok" : 1 } */ أولا: Create الأن نأتي لموضوع الإضافه بداخل الكولكشن .. للإضافه هناك ثلاث خيارات ممكن استخدامها: db.collection.insert() - old db.collection.insertOne() New in version 3.2 db.collection.insertMany() New in version 3.2 و في هذا الدرس سنستخدم insertMany لإضافة اكثر من document في collection بإستخدام كوماند واحد Syntax db.collection.insertMany( { [ <document 1> , <document 2>, ... ] }, { writeConcern: <document>, ordered: <boolean> } ) ماسنضيفه بداخل الكولكشن هو ( اعمل نسخ ومن ثم لصق في الـCMD) db.customers.insertMany([ { cus_name: "Abdulla Jassim", payment: 10, branch: "Hamad Town" }, { cus_name: "Mohammed Yousif", payment: 12, branch: "Saar" }, { cus_name: "Yassir Khalaf", payment: 4.5, branch: "Isa Town" }, { cus_name: "omar khalid", payment: 7.2, branch: "Manama" }, { cus_name: "Reem Ali", payment: 34, branch: "Riffa" }, { cus_name: "Fatima Talal", payment: 9.6, branch: "Manama" } ]) // results // /* { "acknowledged" : true, "insertedIds" : [ ObjectId("5803b8ccf9f236bb5591f181"), ObjectId("5803b8ccf9f236bb5591f182"), ObjectId("5803b8ccf9f236bb5591f183"), ObjectId("5803b8ccf9f236bb5591f184"), ObjectId("5803b8ccf9f236bb5591f185"), ObjectId("5803b8ccf9f236bb5591f186") ] } */ ثانيا: Read بعد عمل قاعدة البيانات , كولكشن و إضافه دوكيومنتس تأتي العمليه الثانية في الـCRUD وهي Read او Find في مصطلحات الـMongoDB وللبحث \ لقراءة جميع المدخلات التي في جدول customers تكون بالكماند التالي ( ملاحظة pretty() function فقط لعرض الناتج بشكل اوضح ) Syntax db.collection.find() db.cunstomers.find({}).pretty() // results // /* { "_id" : ObjectId("5803b8ccf9f236bb5591f181"), "cus_name" : "Abdulla Jassim", "payment" : 10, "branch" : "Hamad Town" } { "_id" : ObjectId("5803b8ccf9f236bb5591f182"), "cus_name" : "Mohammed Yousif", "payment" : 12, "branch" : "Saar" } { "_id" : ObjectId("5803b8ccf9f236bb5591f183"), "cus_name" : "Yassir Khalaf", "payment" : 4.5, "branch" : "Isa Town" } { "_id" : ObjectId("5803b8ccf9f236bb5591f184"), "cus_name" : "omar khalid", "payment" : 7.2, "branch" : "Manama" } { "_id" : ObjectId("5803b8ccf9f236bb5591f185"), "cus_name" : "Reem Ali", "payment" : 34, "branch" : "Riffa" } { "_id" : ObjectId("5803b8ccf9f236bb5591f186"), "cus_name" : "Fatima Talal", "payment" : 9.6, "branch" : "Manama" } */ تطبيقات حول db.collection.find استخرج اسماء جميع الأشخاص الذين دفعوا اكثر من 10 دنانير .. سيكون الكوماند db.customers.find( { payment:{$gt: 10} }, { payment: 0, branch: 0 , _id: 0 } ) /* { payment:{$gt: 10} } = the condition where payment $gt greater than 10 { payment: 0, branch: 0 , _id: 0 } = exclude these fields/cols from results Resutls: { "cus_name" : "Mohammed Yousif" } { "cus_name" : "Reem Ali" } */ استخرج جميع من يحتوي اسمه على المقطع al db.customers.find({cus_name: /al/}).pretty() // Results // /* { "_id" : ObjectId("5803b8ccf9f236bb5591f183"), "cus_name" : "Yassir Khalaf", "payment" : 4.5, "branch" : "Isa Town" } { "_id" : ObjectId("5803b8ccf9f236bb5591f184"), "cus_name" : "omar khalid", "payment" : 7.2, "branch" : "Manama" } { "_id" : ObjectId("5803b8ccf9f236bb5591f186"), "cus_name" : "Fatima Talal", "payment" : 9.6, "branch" : "Manama" } */ ثالثا: Update لتحديث دوكيومنت معين او عدد من الدوكيومنتس يعتمد على الحاله التي تواجهها: db.collection.update() - old db.collection.updateOne() New in version 3.2 db.collection.updateMany() New in version 3.2 db.collection.replaceOne() New in version 3.2 ولكن لنبدأ بابسط الاوامر Syntax db.collection.updateOne(filter, update, options) وأمثلة على ذلك , تحديث مدفوعات من اسمه Abdulla إلى 14 db.customers.updateOne({"cus_name": "Abdulla Jassim"}, {$set: {"payment": 14} }) /* set payment = 14 where cus_name= 'Abdulla Jassim' Resutls If Match { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 } Results If No Match { "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 } */ وبنفس الطريقة تستطيع تعديل اكثر من document دفعة واحده بإستخدام db.collection.updateMany رابعا: Delete في الحقيقة لا يوجد الكثير للحديث عنه في عملية الحذف لان الاتجاه والنتيجه واحده في كل الحالات حيث انه سيتم حذف الدوكيومنت التي تحدده db.collection.remove() - old db.collection.deleteOne() New in version 3.2 db.collection.deleteMany() New in version 3.2 و ساينتكس الحذف سيكون Syntax db.collection.deleteOne() مثال على حذف احد الدوكيومنتس في Collection الـcustomers db.customers.deleteOne({_id: ObjectId("5803b8ccf9f236bb5591f186") }) /* Resutls If match { "acknowledged" : true, "deletedCount" : 1 } Resutls If !match { "acknowledged" : true, "deletedCount" : 0 */ مثال آخر على حذف اكثر من document دفعة واحده db.customers.deleteMany({"payment": {$not: {$eq: 0 } } }) /* Delete all document from customers where paymanet != 0 {$not: {$eq: 0 } } means != 0 Results If match { "acknowledged" : true, "deletedCount" : 5 } Results If !match (the statment is right but no such documents found) { "acknowledged" : true, "deletedCount" : 0 } */
  8. البدأ بعمليات الـCRUD في قاعدة بيانات الـMongoDB السلام عليكم ورحمة الله وبركاته .. من بعد المقدمة حول قاعدة بيانات الـMongoDB حيث تم التعرف على: ما نوع قاعدة البيانات. كيفية تخزين البيانات فيها. العمليات البسيطة منها الـfind. الفروقات السطيحة مابين الـMongoDB و قواعد البيانات الأخرى من نوع RDBMS. لماذا انصح بالتحول إلى هذا النوع من قواعد البيانات. إذا , اصبح هناك نظرة شاملة حول هذا النوع من قواعد البيانات و في هذا الدرس سنبدأ بأول العمليات المهمة والاساسية التي تسمى بـCRUD اختصارا إلى: Create Read Update Delete نبدأ بسمه تعالى, افتح الـCMD او الـTerminal و اكتب الكوماند التالي لتفعيل خدمة الـMongoDB في جهازك بعد ذلك افتح CMD آخر واكتب الكوماند التالي للدخول على MongoDB Shell بعد الدخول على الـMongoDB Shell لمعلومات اكثر اكتب help لندا بتصفح قواعد البيانات الموجوده مسبقا في بكتابه show dbs ستظهر قاعدة بيانات واحده اسمها local تحتوي على collection بإسم startup_log وهنا ننوه مره اخرى بأن: اسم الـTable في الـMongoDB هو Collection اسم الـRow في الـMongoDB هو Document قم بإنشاء قاعدة بيانات جديدة و اختارها من خلال كوماند واحد و DATABASE_NAME تعني اسم قاعدة البيانات التي تريد عملها ولنفترض abdullashop بعد انشاء قاعدة البيانات واختيارها نبدأ الآن بعمل collection بإسم مثلا customers db.createCollection("customers") //results /* { "ok" : 1 } */ أولا: Create الأن نأتي لموضوع الإضافه بداخل الكولكشن .. للإضافه هناك ثلاث خيارات ممكن استخدامها: db.collection.insert() - old db.collection.insertOne() New in version 3.2 db.collection.insertMany() New in version 3.2 و في هذا الدرس سنستخدم insertMany لإضافة اكثر من document في collection بإستخدام كوماند واحد Syntax db.collection.insertMany( { [ <document 1> , <document 2>, ... ] }, { writeConcern: <document>, ordered: <boolean> } ) ماسنضيفه بداخل الكولكشن هو ( اعمل نسخ ومن ثم لصق في الـCMD) db.customers.insertMany([ { cus_name: "Abdulla Jassim", payment: 10, branch: "Hamad Town" }, { cus_name: "Mohammed Yousif", payment: 12, branch: "Saar" }, { cus_name: "Yassir Khalaf", payment: 4.5, branch: "Isa Town" }, { cus_name: "omar khalid", payment: 7.2, branch: "Manama" }, { cus_name: "Reem Ali", payment: 34, branch: "Riffa" }, { cus_name: "Fatima Talal", payment: 9.6, branch: "Manama" } ]) // results // /* { "acknowledged" : true, "insertedIds" : [ ObjectId("5803b8ccf9f236bb5591f181"), ObjectId("5803b8ccf9f236bb5591f182"), ObjectId("5803b8ccf9f236bb5591f183"), ObjectId("5803b8ccf9f236bb5591f184"), ObjectId("5803b8ccf9f236bb5591f185"), ObjectId("5803b8ccf9f236bb5591f186") ] } */ ثانيا: Read بعد عمل قاعدة البيانات , كولكشن و إضافه دوكيومنتس تأتي العمليه الثانية في الـCRUD وهي Read او Find في مصطلحات الـMongoDB وللبحث \ لقراءة جميع المدخلات التي في جدول customers تكون بالكماند التالي ( ملاحظة pretty() function فقط لعرض الناتج بشكل اوضح ) Syntax db.collection.find() db.cunstomers.find({}).pretty() // results // /* { "_id" : ObjectId("5803b8ccf9f236bb5591f181"), "cus_name" : "Abdulla Jassim", "payment" : 10, "branch" : "Hamad Town" } { "_id" : ObjectId("5803b8ccf9f236bb5591f182"), "cus_name" : "Mohammed Yousif", "payment" : 12, "branch" : "Saar" } { "_id" : ObjectId("5803b8ccf9f236bb5591f183"), "cus_name" : "Yassir Khalaf", "payment" : 4.5, "branch" : "Isa Town" } { "_id" : ObjectId("5803b8ccf9f236bb5591f184"), "cus_name" : "omar khalid", "payment" : 7.2, "branch" : "Manama" } { "_id" : ObjectId("5803b8ccf9f236bb5591f185"), "cus_name" : "Reem Ali", "payment" : 34, "branch" : "Riffa" } { "_id" : ObjectId("5803b8ccf9f236bb5591f186"), "cus_name" : "Fatima Talal", "payment" : 9.6, "branch" : "Manama" } */ تطبيقات حول db.collection.find استخرج اسماء جميع الأشخاص الذين دفعوا اكثر من 10 دنانير .. سيكون الكوماند db.customers.find( { payment:{$gt: 10} }, { payment: 0, branch: 0 , _id: 0 } ) /* { payment:{$gt: 10} } = the condition where payment $gt greater than 10 { payment: 0, branch: 0 , _id: 0 } = exclude these fields/cols from results Resutls: { "cus_name" : "Mohammed Yousif" } { "cus_name" : "Reem Ali" } */ استخرج جميع من يحتوي اسمه على المقطع al db.customers.find({cus_name: /al/}).pretty() // Results // /* { "_id" : ObjectId("5803b8ccf9f236bb5591f183"), "cus_name" : "Yassir Khalaf", "payment" : 4.5, "branch" : "Isa Town" } { "_id" : ObjectId("5803b8ccf9f236bb5591f184"), "cus_name" : "omar khalid", "payment" : 7.2, "branch" : "Manama" } { "_id" : ObjectId("5803b8ccf9f236bb5591f186"), "cus_name" : "Fatima Talal", "payment" : 9.6, "branch" : "Manama" } */ ثالثا: Update لتحديث دوكيومنت معين او عدد من الدوكيومنتس يعتمد على الحاله التي تواجهها: db.collection.update() - old db.collection.updateOne() New in version 3.2 db.collection.updateMany() New in version 3.2 db.collection.replaceOne() New in version 3.2 ولكن لنبدأ بابسط الاوامر Syntax db.collection.updateOne(filter, update, options) وأمثلة على ذلك , تحديث مدفوعات من اسمه Abdulla إلى 14 db.customers.updateOne({"cus_name": "Abdulla Jassim"}, {$set: {"payment": 14} }) /* set payment = 14 where cus_name= 'Abdulla Jassim' Resutls If Match { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 } Results If No Match { "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 } */ وبنفس الطريقة تستطيع تعديل اكثر من document دفعة واحده بإستخدام db.collection.updateMany رابعا: Delete في الحقيقة لا يوجد الكثير للحديث عنه في عملية الحذف لان الاتجاه والنتيجه واحده في كل الحالات حيث انه سيتم حذف الدوكيومنت التي تحدده db.collection.remove() - old db.collection.deleteOne() New in version 3.2 db.collection.deleteMany() New in version 3.2 و ساينتكس الحذف سيكون Syntax db.collection.deleteOne() مثال على حذف احد الدوكيومنتس في Collection الـcustomers db.customers.deleteOne({_id: ObjectId("5803b8ccf9f236bb5591f186") }) /* Resutls If match { "acknowledged" : true, "deletedCount" : 1 } Resutls If !match { "acknowledged" : true, "deletedCount" : 0 */ مثال آخر على حذف اكثر من document دفعة واحده db.customers.deleteMany({"payment": {$not: {$eq: 0 } } }) /* Delete all document from customers where paymanet != 0 {$not: {$eq: 0 } } means != 0 Results If match { "acknowledged" : true, "deletedCount" : 5 } Results If !match (the statment is right but no such documents found) { "acknowledged" : true, "deletedCount" : 0 } */ تم ترقية هذا الطرح المميز الى صفحة المقالات
  9. ماهي قاعدة بيانات الـMongoDB؟ في السابق كان الحديث حول قواعدة البيانات المعروفه و المتوارد بين اقطاب المبرمجين من مختلف الأصعدة ابتدا من web developers إلى الـsoftware developers على مختلف المنصات windows, OSX, Linux و جل الحديث كان يدور حول نوع واحد فقط وهو RDBMS Relational database management system مثل MS SQL Server, IBM DB2, Oracle, MySQL, and Microsoft Access التي تعتمد في حفظ البيانات داخل جداول ولكن في الآونة الأخيرة و بعد صدور عدد من JS Frameworks و ارتفاع عدد مستخدمي لغة الجافاسكربت بدأت شركة 10GEN في العمل على قاعدة بيانات من نوع مختلف تماما عما سبق ذكرة وهي NoSQL تحت اسم MongoDB اي قاعدة بيانات لا توجد بها علاقة بين الجداول وتعتمد في حفظ البيانات كمستندات BOSN ويعد هذا النوع الأشهر بين عائلة الـNoSQL وهنا ننوه بأن جميع ما تعرفه عن الـSQL Databases قد يتغير فبالتاكيد لن يكون هناك كوريز بالطريقة التي اعتدت العمل عليها. 1- أمثله وبما ان الكثير من المبرمجين لديه خلفية في الـMySQL سأقوم بمقارنة سريعة حول الأختلافات السطحية بين المونجو والـMySQL: اسم الـTable في الـMongoDB هو Collection اسم الـRow في الـMongoDB هو Document تعتمد قواعد بيانات الـRDBMS على الجداول كالنحو التالي: بينما قاعدة بيانات الـMongoDB تعتمد على BSON وهذا يعني Binary Encoding Of JSON Objects وتكون كالنحو التالي: { "_id" : ObjectId("57fe832b13e6a51130a23d2a"), "ID" : 1, "username" : "abdulla", "email" : "abdulla@gmail.com" } { "_id" : ObjectId("57fe832b13e6a51130a23d2b"), "ID" : 2, "username" : "omar", "email" : "omar.g@gmail.com" } { "_id" : ObjectId("57fe832b13e6a51130a23d2c"), "ID" : 3, "username" : "mohammed", "email" : "mohd@hotmail.com" } امثلة حول الفروقات في عمليات الـQueries مابين الـMongoDB و الـMySQL OR RDBMS ولنفترض بأن لدينا جدول و كولكشن يحتويان على عدد من الصفوف والدوكيومنتس فيهم معلومات حول مستخدمين عرض جميع المستخدمين من هم دون السن الـ24 SELECT * FROM users WHERE age < 24 db.users.find({"age": { $lt: 24 }}) // $lt = less than عرض جميع المستخدمين الذين اعمارهم مابين الـ20 والـ30 SELECT * FROM `users` WHERE `age` BETWEEN 20 AND 30 db.users.find({ age: { $gt: 20, $lt: 30 }}) // $gt = greater than عرض المستخدمين الذين اسمائهم تحتوي على حرف A في الاول او الاخير او المنتصف لايهم SELECT * FROM `users` WHERE username LIKE %A% db.users.find({username: /A/}) و في حالة الإضافة INSERT INTO `users` (username,age,status) VALUES ('abdulla',25,'active') db.users.insertOne({username: "abdulla", age: 25, status: "active"}) ولكن هناك فارق كبير في هذه الكويري و بما ان قاعدة بيانات الـMongoDB ليست Relational بالتالي ليس هناك Schema محدده عند الإضافه فتستطيع مثلا إضافة document بمتغير col,field ليس موجود في الـdocument السابق او التالي في نفس الـCollection وبهذا يقال للـMongoDB بأن اهم مميزات هذا النوع من قواعد البيانات بأنه Flexible او Dynamic Schema ومثال على ذلك: db.users.insert([ { username: { fname: "abdulla", lname: "bahraini" }, age: 25, status: "active" }, { username: "mohammed", age: 19, status: "not active" } ]) 2- لماذا التحول الى MongoDB ( وجهة نظر ) كما اسلفنا سابقا ومع صدور عدد من js frameworks وبالاخص Meanjs المعني ب expressjs , angularjs & nodejs بالاضافه الmongodb و توسع هذه الفريموركس بشكل ضخم و رهيب جدا ومنها النود التي اصبحت خطر داهم على لغة الphp مقارنة بالسرعة, الاداء الرهيب وتناغم المونجو مع هذه الفريموركس بشكل افضل سبب في توجه الكثير من المطورين الى المونجو. ليس عند هذا الحد وحسب بل نظرا الى سرعة المونجو حسب الاحصائيات تبين اهمه الانتقال من قواعد البيانات الاعتيادية الى المونجو. تجربة اضافه 10000 صف و دوكيومنت في MySQL و MongoDB .. نلاحظ الفرق في سرعة الاداء احتاج المونجو الى ثانتين لتنفيذ المهمه بينما الMySQL احتاج الى 3 دقائق تقريبا. 3-التثبيت لتثبيت الـMongoDB قم بالدخول على الرابط واختر ما يناسب نظام جهازك بعد التثبيت إن كنت من متسخدمي الوندوز انشأ مجلد في داخل الـC (في حال تم تثبيت المونجو في السي) أضف المتغير التالي في PATH Environment وتجده في المسار التالي this pc >> proprieties >> Advanced System Settings >> Advanced tab >> Environment Variables >> in System Variables find PATH then Click Edit افتح الـCMD واكتب الكوماند التالي لتفعيل خدمه الـMongoDB في جهازك وستعمل على بورت 27017 بشكل افتراضي ثم افتح CMD أخر واكتب الكوماند التالي للدخول على MongoDB SHELL بالتالي ستكون داخل الـMongoDB SHELL وتستطيع التعامل معه من خلال الاوامر المباشرة وللإطلاع اكثر اكتب help
  10. ماهي قاعدة بيانات الـMongoDB؟ في السابق كان الحديث حول قواعدة البيانات المعروفه و المتوارد بين اقطاب المبرمجين من مختلف الأصعدة ابتدا من web developers إلى الـsoftware developers على مختلف المنصات windows, OSX, Linux و جل الحديث كان يدور حول نوع واحد فقط وهو RDBMS Relational database management system مثل MS SQL Server, IBM DB2, Oracle, MySQL, and Microsoft Access التي تعتمد في حفظ البيانات داخل جداول ولكن في الآونة الأخيرة و بعد صدور عدد من JS Frameworks و ارتفاع عدد مستخدمي لغة الجافاسكربت بدأت شركة 10GEN في العمل على قاعدة بيانات من نوع مختلف تماما عما سبق ذكرة وهي NoSQL تحت اسم MongoDB اي قاعدة بيانات لا توجد بها علاقة بين الجداول وتعتمد في حفظ البيانات كمستندات BOSN ويعد هذا النوع الأشهر بين عائلة الـNoSQL وهنا ننوه بأن جميع ما تعرفه عن الـSQL Databases قد يتغير فبالتاكيد لن يكون هناك كوريز بالطريقة التي اعتدت العمل عليها. 1- أمثله وبما ان الكثير من المبرمجين لديه خلفية في الـMySQL سأقوم بمقارنة سريعة حول الأختلافات السطحية بين المونجو والـMySQL: اسم الـTable في الـMongoDB هو Collection اسم الـRow في الـMongoDB هو Document تعتمد قواعد بيانات الـRDBMS على الجداول كالنحو التالي: بينما قاعدة بيانات الـMongoDB تعتمد على BSON وهذا يعني Binary Encoding Of JSON Objects وتكون كالنحو التالي: { "_id" : ObjectId("57fe832b13e6a51130a23d2a"), "ID" : 1, "username" : "abdulla", "email" : "abdulla@gmail.com" } { "_id" : ObjectId("57fe832b13e6a51130a23d2b"), "ID" : 2, "username" : "omar", "email" : "omar.g@gmail.com" } { "_id" : ObjectId("57fe832b13e6a51130a23d2c"), "ID" : 3, "username" : "mohammed", "email" : "mohd@hotmail.com" } امثلة حول الفروقات في عمليات الـQueries مابين الـMongoDB و الـMySQL OR RDBMS ولنفترض بأن لدينا جدول و كولكشن يحتويان على عدد من الصفوف والدوكيومنتس فيهم معلومات حول مستخدمين عرض جميع المستخدمين من هم دون السن الـ24 SELECT * FROM users WHERE age < 24 db.users.find({"age": { $lt: 24 }}) // $lt = less than عرض جميع المستخدمين الذين اعمارهم مابين الـ20 والـ30 SELECT * FROM `users` WHERE `age` BETWEEN 20 AND 30 db.users.find({ age: { $gt: 20, $lt: 30 }}) // $gt = greater than عرض المستخدمين الذين اسمائهم تحتوي على حرف A في الاول او الاخير او المنتصف لايهم SELECT * FROM `users` WHERE username LIKE %A% db.users.find({username: /A/}) و في حالة الإضافة INSERT INTO `users` (username,age,status) VALUES ('abdulla',25,'active') db.users.insertOne({username: "abdulla", age: 25, status: "active"}) ولكن هناك فارق كبير في هذه الكويري و بما ان قاعدة بيانات الـMongoDB ليست Relational بالتالي ليس هناك Schema محدده عند الإضافه فتستطيع مثلا إضافة document بمتغير col,field ليس موجود في الـdocument السابق او التالي في نفس الـCollection وبهذا يقال للـMongoDB بأن اهم مميزات هذا النوع من قواعد البيانات بأنه Flexible او Dynamic Schema ومثال على ذلك: db.users.insert([ { username: { fname: "abdulla", lname: "bahraini" }, age: 25, status: "active" }, { username: "mohammed", age: 19, status: "not active" } ]) 2- لماذا التحول الى MongoDB ( وجهة نظر ) كما اسلفنا سابقا ومع صدور عدد من js frameworks وبالاخص Meanjs المعني ب expressjs , angularjs & nodejs بالاضافه الmongodb و توسع هذه الفريموركس بشكل ضخم و رهيب جدا ومنها النود التي اصبحت خطر داهم على لغة الphp مقارنة بالسرعة, الاداء الرهيب وتناغم المونجو مع هذه الفريموركس بشكل افضل سبب في توجه الكثير من المطورين الى المونجو. ليس عند هذا الحد وحسب بل نظرا الى سرعة المونجو حسب الاحصائيات تبين اهمه الانتقال من قواعد البيانات الاعتيادية الى المونجو. تجربة اضافه 10000 صف و دوكيومنت في MySQL و MongoDB .. نلاحظ الفرق في سرعة الاداء احتاج المونجو الى ثانتين لتنفيذ المهمه بينما الMySQL احتاج الى 3 دقائق تقريبا. 3-التثبيت لتثبيت الـMongoDB قم بالدخول على الرابط واختر ما يناسب نظام جهازك بعد التثبيت إن كنت من متسخدمي الوندوز انشأ مجلد في داخل الـC (في حال تم تثبيت المونجو في السي) أضف المتغير التالي في PATH Environment وتجده في المسار التالي this pc >> proprieties >> Advanced System Settings >> Advanced tab >> Environment Variables >> in System Variables find PATH then Click Edit افتح الـCMD واكتب الكوماند التالي لتفعيل خدمه الـMongoDB في جهازك وستعمل على بورت 27017 بشكل افتراضي ثم افتح CMD أخر واكتب الكوماند التالي للدخول على MongoDB SHELL بالتالي ستكون داخل الـMongoDB SHELL وتستطيع التعامل معه من خلال الاوامر المباشرة وللإطلاع اكثر اكتب help تم ترقية هذا الطرح المميز الى صفحة المقالات
  11. السلام عليكم ورحمة الله وبركاته من خلال الدرسين السابقين والملاحظات: ماهو الNode.js؟ الدرس الأول في الNode.js عمل تسجيل دخول ملاحظات في الـJQuery مع الـNode.js تم التعرف على الفرق بين الـNode.js والـPHP , ماهو سبب تفوق سرعة النود وماهو النود جي اس مجملا , كما تم طرح الدرس الأول عن كيفية عمل خاصية تسجيل الدخول و حفظ الكوكيز في المتصفح ومنها يكون: عمل كونكشن مع الداتا بيس ارسال البيانات من فورم , طريقة استقبال المعلومات المرسلة , وبشكل خاص في الـNode.js , التعامل مع الـCookies بعد تسجيل الدخول ,كيفية التعامل مع البيانات من ومطابقتها مع قاعدة البيانات. في هذا الدرس الثاني سيتم عمل خاصية البحث بالطريقة الاعتيادية اولا ومن ثم سيكون هناك درس آخر لتبيان التغييرات لعمل البحث بشكل حي Live. إذا, لنبدأ هذا الدرس حيث سأفترض اولا بأنك اتممت قراءة الدرس الأول وتطبيق الدرس الأول و فهم ملاحظات الـJQuery مع الـNode.js , سنبدأ بعمل ملف الـبحث ومثلا يكون كالتالي: <!DOCTYPE html> <html lang="en"> <head id="head"> </head> <script src='js/jquery.js'></script> <script src="js/head.layout.js"></script> <script src="js/search.js"></script> <body> <!--/.nav-start --> <!-- Navigation Goes Here --> <nav class="navbar navbar-default"> <script src="js/nav.js"></script> </nav> <!--/.nav-end --> <div class="container"> <div class="col-md-12"> <div class="col-md-3"> <form class="form-horizontal" action="/api/search" method="GET" id='searhform'> <div class="form-group"> <label for="search"><h4><i class="fa fa-search" id="spinning_animation"></i> Search Key</h4></label> <input name='search' id='search' class="form-control" class="form-control" /> </div> <div class="form-group"> <button type="submit" class="btn btn-primary"> Search</button> </div> </form> </div> </div> <div class="col-md-12"> <!-- Search Results --> <div id="search_results"></div> </div> </div> </body> </html> والملف الآخر في مجلد js يحتوي على ajax لإرسال قيمة الـinput#search $(document).ready(function() { //Ajax Search $(document).on("submit","#searhform",function(e){ $("#search_results").empty(); $("#spinning_animation").removeClass("fa fa-search"); $("#spinning_animation").addClass("fa fa-circle-o-notch fa-spin"); var search = $("#search").val(); $.ajax({ type: "GET", url: "api/search", async:true, timeout: 500, data: {search:search}, success: function(response){ // $(".img-responsive").hide(); $("#spinning_animation").removeClass("fa fa-circle-o-notch fa-spin"); $("#spinning_animation").addClass("fa fa-search"); $.each( response, function( key, val ) { if(val.ID != null){ $("#search_results").append( "<div class='col-md-3 text-center'>"+ "<div class='box'>"+ "<h3>"+val.car_name+"</h3>"+ "<p>Brand: "+val.car_brand+"<p>"+ "<p>Model: "+val.car_model+"<p>"+ "</div>"+ "</div>" ); } else{ $("#spinning_animation").removeClass("fa fa-circle-o-notch fa-spin"); $("#spinning_animation").addClass("fa fa-search"); $("#search_results").html("<p style='color:red;'>No Results</p>"); } }); }, error: function(){ $("#spinning_animation").removeClass("fa fa-circle-o-notch fa-spin"); $("#spinning_animation").addClass("fa fa-search"); $("#search_results").html("<p style='color:red;'>Error In Request</p>"); } }); e.preventDefault(); }); }); البحث سيكون في قاعدة البيانات التي سبق وعملتها وللتأكد , هذه هي القاعدة والجدول الذي سنبحث فيه حيث يحتوي على car_name, car_model, car_brand, ID (Primary) SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; -- -- Table structure for table `cars` -- CREATE TABLE `cars` ( `ID` int(11) NOT NULL, `car_name` text NOT NULL, `car_brand` text NOT NULL, `car_model` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Dumping data for table `cars` -- INSERT INTO `cars` (`ID`, `car_name`, `car_brand`, `car_model`) VALUES (1, 'Nissan Patrol', 'Nissan', 2016), (2, 'Camaro SS', 'Chevy', 2010), (3, 'Mustang', 'Ford', 2013), (4, 'S500', 'Mercedes', 2009), (5, '330i', 'BMW', 2014); -- ------------------------------------ -- -- Indexes for dumped tables -- -- -- Indexes for table `cars` -- ALTER TABLE `cars` ADD PRIMARY KEY (`ID`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `cars` -- ALTER TABLE `cars` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; وبهذا تم الانتهاء من اعداد قاعدة البيانات, ملف الـsearch.html وكذلك Ajax لارسال قيمة البحث إلى الـserver.js , لننتقل إلى ملف الـserver.js ونضيف الـroute المسؤول عن استقبال قيمة متغير البحث, عمل اللازم و ارجاع الناتج بعد ذلك .. حيث سيكون كالتالي: var http = require('http'); var express = require("express"); var mysql = require('mysql'); var app = express(); app.use('/bootstrap', express.static(__dirname + '/bootstrap')); app.use('/css', express.static(__dirname + '/css')); app.use('/js', express.static(__dirname + '/js')); app.use('/images', express.static(__dirname + '/images')); app.use('/faawesome', express.static(__dirname + '/faawesome')); var mysql = require('mysql'); var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : '', database : 'cars' }); app.get('/api/search', function (req, res) { var searchkey = req.query.search; console.log(JSON.stringify(searchkey, null, 4)); if(searchkey != ""){ connection.query('SELECT * FROM cars WHERE `car_name` LIKE ?',"%"+searchkey+"%", function(err, rows, fields) { if (err){ throw err; } else { if(rows.length > 0){ res.writeHead(200, {'Content-Type': 'application/json'}); console.log(JSON.stringify(rows, null, 4)); res.end(JSON.stringify(rows ,null, 4)); } } }); } else { res.send("Nothing"); } }); app.get('/',function(req,res){ res.redirect("/home"); }); app.get('/home',function(req,res){ res.sendFile(__dirname + "/home.html"); }); app.get('/search',function(req,res){ res.sendFile(__dirname + "/search.html"); }); app.listen(3000,function(){ console.log("Working on port 3000"); }); شرح: هنا نلاحظ الـRoute المسؤول عن استقبال قيمة متغير البحث app.get('/api/search', function (req, res) { var searchkey = req.query.search; console.log(JSON.stringify(searchkey, null, 4)); if(searchkey != ""){ connection.query('SELECT * FROM cars WHERE `car_name` LIKE ?',"%"+searchkey+"%", function(err, rows, fields) { if (err){ throw err; } else { if(rows.length > 0){ res.writeHead(200, {'Content-Type': 'application/json'}); console.log(JSON.stringify(rows, null, 4)); res.end(JSON.stringify(rows ,null, 4)); } } }); } else { res.send("Nothing"); } }); خطوة اخيرا , قم بتشغيل التطبيق من خلال الأمر node server.js افتح المتصفح على الصفحة 127.0.0.1:3000/search الملفات المرفقة js/nav.js $(".navbar.navbar-default").append( "<div class='container'>"+ "<div class='navbar-header'>"+ "<button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='#navbar' aria-expanded='false' aria-controls='navbar'>"+ "<span class='sr-only'>Toggle navigation</span>"+ "<span class='icon-bar'></span>"+ "<span class='icon-bar'></span>"+ "<span class='icon-bar'></span>"+ "</button>"+ "<a class='navbar-brand home' href='home'>"+ "<img src='images/nodejs-logo.png' style='max-width:52px;height:auto;' class='hidden-xs'>"+ "<img src='images/nodejs-logo-small.png' class='visible-xs'><span class='sr-only'></span>"+ "</a>"+ "</div>"+ "<div id='navbar' class='collapse navbar-collapse'>"+ "<ul class='nav navbar-nav navbar-left' id='uls'>"+ "<li class='active'><a style='color: #FFF;'><i class='fa fa-home'></i> Home</a></li>"+ "<li><a href='about'><i class='fa fa-folder-open'></i> About</a></li>"+ "<li><a href='contact'><i class='fa fa-phone'></i> Contact</a></li>"+ "</ul>"+ "</div>"+ "</div>" ); js/head.layout.js // $(document).ready(function() { $("#head").append( "<meta charset='utf-8'>"+ "<meta http-equiv='X-UA-Compatible' content='IE=edge'>"+ "<meta name='viewport' content='width=device-width, initial-scale=1'>"+ "<title>Search / NodeJS Bootstrap 101</title>"+ "<link rel='stylesheet' href='bootstrap/css/bootstrap.css'>"+ "<link href='css/style.blue.css' rel='stylesheet' id='theme-stylesheet'>"+ "<link rel='stylesheet' href='faawesome/css/font-awesome.css' media='screen' title='Font Awesome'>"+ "<script src='js/jquery.form.js'></script>"+ "<script src='bootstrap/js/bootstrap.js'></script>" ); // });
  12. السلام عليكم ورحمة الله وبركاته من خلال الدرسين السابقين والملاحظات: ماهو الNode.js؟ الدرس الأول في الNode.js عمل تسجيل دخول ملاحظات في الـJQuery مع الـNode.js تم التعرف على الفرق بين الـNode.js والـPHP , ماهو سبب تفوق سرعة النود وماهو النود جي اس مجملا , كما تم طرح الدرس الأول عن كيفية عمل خاصية تسجيل الدخول و حفظ الكوكيز في المتصفح ومنها يكون: عمل كونكشن مع الداتا بيس ارسال البيانات من فورم , طريقة استقبال المعلومات المرسلة , وبشكل خاص في الـNode.js , التعامل مع الـCookies بعد تسجيل الدخول ,كيفية التعامل مع البيانات من ومطابقتها مع قاعدة البيانات. في هذا الدرس الثاني سيتم عمل خاصية البحث بالطريقة الاعتيادية اولا ومن ثم سيكون هناك درس آخر لتبيان التغييرات لعمل البحث بشكل حي Live. إذا, لنبدأ هذا الدرس حيث سأفترض اولا بأنك اتممت قراءة الدرس الأول وتطبيق الدرس الأول و فهم ملاحظات الـJQuery مع الـNode.js , سنبدأ بعمل ملف الـبحث ومثلا يكون كالتالي: <!DOCTYPE html> <html lang="en"> <head id="head"> </head> <script src='js/jquery.js'></script> <script src="js/head.layout.js"></script> <script src="js/search.js"></script> <body> <!--/.nav-start --> <!-- Navigation Goes Here --> <nav class="navbar navbar-default"> <script src="js/nav.js"></script> </nav> <!--/.nav-end --> <div class="container"> <div class="col-md-12"> <div class="col-md-3"> <form class="form-horizontal" action="/api/search" method="GET" id='searhform'> <div class="form-group"> <label for="search"><h4><i class="fa fa-search" id="spinning_animation"></i> Search Key</h4></label> <input name='search' id='search' class="form-control" class="form-control" /> </div> <div class="form-group"> <button type="submit" class="btn btn-primary"> Search</button> </div> </form> </div> </div> <div class="col-md-12"> <!-- Search Results --> <div id="search_results"></div> </div> </div> </body> </html> والملف الآخر في مجلد js يحتوي على ajax لإرسال قيمة الـinput#search $(document).ready(function() { //Ajax Search $(document).on("submit","#searhform",function(e){ $("#search_results").empty(); $("#spinning_animation").removeClass("fa fa-search"); $("#spinning_animation").addClass("fa fa-circle-o-notch fa-spin"); var search = $("#search").val(); $.ajax({ type: "GET", url: "api/search", async:true, timeout: 500, data: {search:search}, success: function(response){ // $(".img-responsive").hide(); $("#spinning_animation").removeClass("fa fa-circle-o-notch fa-spin"); $("#spinning_animation").addClass("fa fa-search"); $.each( response, function( key, val ) { if(val.ID != null){ $("#search_results").append( "<div class='col-md-3 text-center'>"+ "<div class='box'>"+ "<h3>"+val.car_name+"</h3>"+ "<p>Brand: "+val.car_brand+"<p>"+ "<p>Model: "+val.car_model+"<p>"+ "</div>"+ "</div>" ); } else{ $("#spinning_animation").removeClass("fa fa-circle-o-notch fa-spin"); $("#spinning_animation").addClass("fa fa-search"); $("#search_results").html("<p style='color:red;'>No Results</p>"); } }); }, error: function(){ $("#spinning_animation").removeClass("fa fa-circle-o-notch fa-spin"); $("#spinning_animation").addClass("fa fa-search"); $("#search_results").html("<p style='color:red;'>Error In Request</p>"); } }); e.preventDefault(); }); }); البحث سيكون في قاعدة البيانات التي سبق وعملتها وللتأكد , هذه هي القاعدة والجدول الذي سنبحث فيه حيث يحتوي على car_name, car_model, car_brand, ID (Primary) SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; -- -- Table structure for table `cars` -- CREATE TABLE `cars` ( `ID` int(11) NOT NULL, `car_name` text NOT NULL, `car_brand` text NOT NULL, `car_model` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Dumping data for table `cars` -- INSERT INTO `cars` (`ID`, `car_name`, `car_brand`, `car_model`) VALUES (1, 'Nissan Patrol', 'Nissan', 2016), (2, 'Camaro SS', 'Chevy', 2010), (3, 'Mustang', 'Ford', 2013), (4, 'S500', 'Mercedes', 2009), (5, '330i', 'BMW', 2014); -- ------------------------------------ -- -- Indexes for dumped tables -- -- -- Indexes for table `cars` -- ALTER TABLE `cars` ADD PRIMARY KEY (`ID`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `cars` -- ALTER TABLE `cars` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; وبهذا تم الانتهاء من اعداد قاعدة البيانات, ملف الـsearch.html وكذلك Ajax لارسال قيمة البحث إلى الـserver.js , لننتقل إلى ملف الـserver.js ونضيف الـroute المسؤول عن استقبال قيمة متغير البحث, عمل اللازم و ارجاع الناتج بعد ذلك .. حيث سيكون كالتالي: var http = require('http'); var express = require("express"); var mysql = require('mysql'); var app = express(); app.use('/bootstrap', express.static(__dirname + '/bootstrap')); app.use('/css', express.static(__dirname + '/css')); app.use('/js', express.static(__dirname + '/js')); app.use('/images', express.static(__dirname + '/images')); app.use('/faawesome', express.static(__dirname + '/faawesome')); var mysql = require('mysql'); var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : '', database : 'cars' }); app.get('/api/search', function (req, res) { var searchkey = req.query.search; console.log(JSON.stringify(searchkey, null, 4)); if(searchkey != ""){ connection.query('SELECT * FROM cars WHERE `car_name` LIKE ?',"%"+searchkey+"%", function(err, rows, fields) { if (err){ throw err; } else { if(rows.length > 0){ res.writeHead(200, {'Content-Type': 'application/json'}); console.log(JSON.stringify(rows, null, 4)); res.end(JSON.stringify(rows ,null, 4)); } } }); } else { res.send("Nothing"); } }); app.get('/',function(req,res){ res.redirect("/home"); }); app.get('/home',function(req,res){ res.sendFile(__dirname + "/home.html"); }); app.get('/search',function(req,res){ res.sendFile(__dirname + "/search.html"); }); app.listen(3000,function(){ console.log("Working on port 3000"); }); شرح: هنا نلاحظ الـRoute المسؤول عن استقبال قيمة متغير البحث app.get('/api/search', function (req, res) { var searchkey = req.query.search; console.log(JSON.stringify(searchkey, null, 4)); if(searchkey != ""){ connection.query('SELECT * FROM cars WHERE `car_name` LIKE ?',"%"+searchkey+"%", function(err, rows, fields) { if (err){ throw err; } else { if(rows.length > 0){ res.writeHead(200, {'Content-Type': 'application/json'}); console.log(JSON.stringify(rows, null, 4)); res.end(JSON.stringify(rows ,null, 4)); } } }); } else { res.send("Nothing"); } }); خطوة اخيرا , قم بتشغيل التطبيق من خلال الأمر node server.js افتح المتصفح على الصفحة 127.0.0.1:3000/search الملفات المرفقة js/nav.js $(".navbar.navbar-default").append( "<div class='container'>"+ "<div class='navbar-header'>"+ "<button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='#navbar' aria-expanded='false' aria-controls='navbar'>"+ "<span class='sr-only'>Toggle navigation</span>"+ "<span class='icon-bar'></span>"+ "<span class='icon-bar'></span>"+ "<span class='icon-bar'></span>"+ "</button>"+ "<a class='navbar-brand home' href='home'>"+ "<img src='images/nodejs-logo.png' style='max-width:52px;height:auto;' class='hidden-xs'>"+ "<img src='images/nodejs-logo-small.png' class='visible-xs'><span class='sr-only'></span>"+ "</a>"+ "</div>"+ "<div id='navbar' class='collapse navbar-collapse'>"+ "<ul class='nav navbar-nav navbar-left' id='uls'>"+ "<li class='active'><a style='color: #FFF;'><i class='fa fa-home'></i> Home</a></li>"+ "<li><a href='about'><i class='fa fa-folder-open'></i> About</a></li>"+ "<li><a href='contact'><i class='fa fa-phone'></i> Contact</a></li>"+ "</ul>"+ "</div>"+ "</div>" ); js/head.layout.js // $(document).ready(function() { $("#head").append( "<meta charset='utf-8'>"+ "<meta http-equiv='X-UA-Compatible' content='IE=edge'>"+ "<meta name='viewport' content='width=device-width, initial-scale=1'>"+ "<title>Search / NodeJS Bootstrap 101</title>"+ "<link rel='stylesheet' href='bootstrap/css/bootstrap.css'>"+ "<link href='css/style.blue.css' rel='stylesheet' id='theme-stylesheet'>"+ "<link rel='stylesheet' href='faawesome/css/font-awesome.css' media='screen' title='Font Awesome'>"+ "<script src='js/jquery.form.js'></script>"+ "<script src='bootstrap/js/bootstrap.js'></script>" ); // }); تم ترقية هذا الطرح المميز الى صفحة المقالات
  13. هذه مجرد فقط البداية والسكيورتي سيكون عبارة عن ملاحظات لا اكثر خصوصا مع هذا البكج، حيث يعمل escape للvalues بشكل اوتوماتيكي رغم ذلك، سيتم شرح الpool و الconnection.escape لاحقا هناك تكمله لهذا الدرس كما تلاحظ بوجود جدول السيارات
  14. شخصيا لا احبذ عمل رقولار اكسبرشن للايميلات لاسباب كثيرة اهمها عدم امكانية حصر الدومين اكستنشن دوت كوم ام دوت نت ام دوت اورق ليس بالامر الكافي لهذا الامر .. الحل الوحيد الممكن عمله هو عملية الvalidation بعد التسجيل لتفعيل الحساب مثلا.
  15. ..... بعد المقدمة عن باترن الـNode.js في المقال السابق سأقوم بشرح اهم الدروس التي لطالما كانت اولى الخطوات المتبعه في جميع اللغات لمعرفة كيفية التعامل مع: قواعد البيانات. طريقة ارسال المعلومات من Form. طريقة استقبال المعلومات المرسلة. وبشكل خاص في الـNode.js , كيفية التعامل مع البيانات من ومطابقتها مع قاعدة البيانات. التعامل مع الـCookies بعد تسجيل الدخول. في بداية هذا الدرس, سأفترض امرين الأول هو مسبقا بأنك قمت بتثبيت الـ Dependencies وهم: npm install mysql npm install express npm install cookie-parser والثاني هو ان تكون لديك معرفة متوسطة مسبقة بلغة الـ javascript و jquery وبعد التأكد من التثبيت, اعمل قاعدة بيانات سواء كانت خارجية ام داخليةوستكون كالتالي مثلا: -- phpMyAdmin SQL Dump -- version 4.5.1 -- http://www.phpmyadmin.net -- -- Host: 127.0.0.1 -- Generation Time: Sep 09, 2016 at 11:50 PM -- Server version: 10.1.16-MariaDB -- PHP Version: 5.6.24 SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; SET time_zone = "+00:00"; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8mb4 */; -- -- Database: `cars` -- -- -------------------------------------------------------- -- -- Table structure for table `cars` -- CREATE TABLE `cars` ( `ID` int(11) NOT NULL, `car_name` text NOT NULL, `car_brand` text NOT NULL, `car_model` int(11) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Dumping data for table `cars` -- INSERT INTO `cars` (`ID`, `car_name`, `car_brand`, `car_model`) VALUES (1, 'Nissan Patrol', 'Nissan', 2016), (2, 'Camaro SS', 'Chevy', 2010), (3, 'Mustang', 'Ford', 2013), (4, 'S500', 'Mercedes', 2009), (5, '330i', 'BMW', 2014); -- -------------------------------------------------------- -- -- Table structure for table `users` -- CREATE TABLE `users` ( `ID` int(11) NOT NULL, `username` text NOT NULL, `password` text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -- -- Dumping data for table `users` -- INSERT INTO `users` (`ID`, `username`, `password`) VALUES (1, 'androidworldbh', '123123'), (2, 'user2', 'bahrain'), (3, 'user3', '4567'); -- -- Indexes for dumped tables -- -- -- Indexes for table `cars` -- ALTER TABLE `cars` ADD PRIMARY KEY (`ID`); -- -- Indexes for table `users` -- ALTER TABLE `users` ADD PRIMARY KEY (`ID`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `cars` -- ALTER TABLE `cars` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; -- -- AUTO_INCREMENT for table `users` -- ALTER TABLE `users` MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; اسم قاعدة البيانات هو cars تحتوي على جدولين users,cars وكل جدول يحتوي على بيانات كما هو موضح في الكود السابق. بعد ذلك قم بعمل ملف اسمه ولنفترض server.js يحتوي على التالي وبالتفصيل سأقوم بعرض الملف .. في البداية نستدعي مانريد من Packages var http = require('http'); var express = require("express"); var cookieParser = require('cookie-parser'); var mysql = require('mysql'); var app = express(); نقوم بعمل الـRouting لنحدد للتطبيق المعني بالمتغير app كيفية استجابة طلب المتصفح ( العميل ) والـSyntax هو app.METHOD(PATH, HANDLER); في ملف server.js ستقوم بإضافة app.use(cookieParser()); app.use('/bootstrap', express.static(__dirname + '/bootstrap')); app.use('/css', express.static(__dirname + '/css')); app.use('/js', express.static(__dirname + '/js')); app.use('/images', express.static(__dirname + '/images')); app.use('/faawesome', express.static(__dirname + '/faawesome')); لتستطيع استخدام الملفات الـCSS & JS وكذلك الصور , ولنستهل ربط قاعدة البيانات بالتطبيق من خلال الكود التالي: var connection = mysql.createConnection({ host : 'localhost', user : 'root', password : '', database : 'cars' }); ملاحظة: تستطيع استدعاء المتغيرات السابقة من ملف خارجي وبالغالب يتم تسميته بـconfig.js يحتوي على جميع المتغيرات الثابته constants مثل متغيرات ربط قواعد البيانات او ماشابه ذلك ولكن في هذا المثال سنستعمل الطريقة الإعتيادية والمباشرة. وبهذا تم اعداد وربط قاعدة البيانات مع التطبيق, وبما ان هذا الدرس عبارة عن كيفية عمل تسجيل دخول سنقوم بكتابة كود الفورم داخل ملف login.html ( وسأفترض مسبقا بأنك تعرف ذلك ): <div class="container"> <div class="card card-container"> <img id="profile-img" class="profile-img-card" src="images/nodejs-logo.png" /> <p id="profile-name" class="profile-name-card"></p> <form class="form-signin" action="/api/login" method="get" id="loginForm"> <span id="reauth-email" class="reauth-email"></span> <input type="text" id="username" class="form-control" placeholder="Username" name="username" required autofocus> <input type="password" id="password" class="form-control" placeholder="Password" name="password" required> <div id="remember" class="checkbox"> <label> <input type="checkbox" value="remember-me"> Remember me </label> </div> <button class="btn btn-lg btn-primary btn-block btn-signin" type="submit">Sign in</button> </form> <a href="#" class="forgot-password" id="status"> Forgot the password? </a> </div> </div> سكربت ارسال بيانات فورم تسجيل الدخول في ملف الـhtml سيكون: <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script> <script> $(document).ready(function() { $('#loginForm').submit(function() { $("#status").empty().text("loging in..."); $(this).ajaxSubmit({ error: function(xhr) { status('Error: ' + xhr.status); }, success: function(response) { console.log(response) if(response == 401){ $("#status").html("Error In Provided Info"); } else { window.location.href = '/home/'+response; } } }); return false; }); }); </script> نعود مرة اخرى لملف server.js ونضيف routing الفورم الذي بدوره يستقبل بيانات الدخول وهم اسم المستخدم username والباسسورد password ويطابق ما تم ارساله من قبل المستخدم مع ماهو موجود في جدول Users في قاعدة البيانات app.get('/api/login', function (req, res) { var user_credentials = { username: req.query.username, password: req.query.password } connection.query('SELECT * FROM users WHERE `username` = ?',user_credentials.username, function(err, rows, fields) { if (err) throw err; if(rows.length > 0){ var userpass = rows[0].password; if(userpass == user_credentials.password){ console.log(JSON.stringify(user_credentials, null, 4)); res.send(user_credentials.username); } else { return res.json(401); console.log("password aint right"); } } }); }); هنا نلاحظ عدة امور اولها الميثود المستخدم في هذا الـrouting او الـcontroller كما يستميه البعض وهي GET , ذلك يعني انه يجب على ميثود الفورم الذي عملته ان يكون GET ليستقبل البيانات app.get الملاحظة الثانية هي المتغيرين الأثنين وهم اسم المستخدم والباسسورد , تستطيع استخدامهم في الكود بشكل مباشر بهذه الطريقة var username = req.query.username var pssword = req.query.password ولكن لسهولة التعامل قمنا بإضافتهم إلى متغير user_credentials بهذه الطريقة var user_credentials = { username: req.query.username, password: req.query.password } ولأستدعاء اسم المستخدم مثلا: user_credentials.username ولمعلومات طرق عمل الـqueries الرجاء زيارة الرابط التالي: https://www.npmjs.com/package/mysql الملاحظة الثالثة وهي rows.length , عند execute الكويري, البكج المستخدم بشكل مباشر يقوم بإرجاع عدة بيانات تستطيع الإطلاع عليها في الـconsole وإحدى هذه الأمور هي عدد الصفوف التي هي متطابقة مع الكويري connection.query('SELECT * FROM users WHERE `username` = ?',user_credentials.username, function(err, rows, fields) ... وستكون بالعادة صف واحد, لذلك نضع شرط إذا كان عدد الصفوف المعنية بالكويري اكثر من صفر rows.length > 0 ذلك يعني بأن اسم المستخدم موجود في قاعدة البيانات ونطابق الـpassword كالتالي: if(rows.length > 0){ var userpass = rows[0].password; // الباسسورد الذي تم استخراجه من الصف المرجع من الكويري if(userpass == user_credentials.password){ console.log(JSON.stringify(user_credentials, null, 4)); res.send(user_credentials.username); } else { return res.json(401); console.log("password aint right"); } } إذا كان كلمة المرور متطابقة, سنقوم بإرسال اسم المستخدم مرة اخرى لصفحة login.html لنرسلها إلى صفحة اخرى المعنية بحفظ الـcookies res.send(user_credentials.username); او اذا كانت كلمة المرور غير متطابقة سنرسل json عبارة عن return res.json(401); وفي ajax صفحة الـlogin.html success: function(response) { console.log(response) if(response == 401){ $("#status").html("Error In Provided Info"); // إذا كان الكود المسترجع هو 401 ذلك يعني بأن كلمة السر غير متطابقة } else { window.location.href = '/home/'+response; // خلاف ذلك, سنرسل اسم المستخدم إلى روتنج معني بحفظ اسم المستخدم في كوكيز } } إذا كانت كلمات السر متطابقة, ميثود الـAjax ستقوم بتحويل المستخدم إلى Routing لحفظ اسم المستخدم في كوكيز , وكود الـRounting هو: app.get('/home/:user',function(req,res){ res.cookie('name', req.params.user).redirect('/home'); }); الذي بدوره يحفظ اسم المستخدم في كوكيز بعنوان name وبعد ذلك يحوله إلى صفحة الـhome.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Node.js Bootstrap 101</title> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"> <script src="/bootstrap/js/bootstrap.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script> <script type="text/javascript"> $.ajax({ type: "GET", url: '/api/cookies', success: function(response) { if(response != "undefined"){ $("#uls").append("<li><a href='logout'><i class='fa fa-lock'></i> Logout</a></li>"); $("#navbar").append("<ul class='nav navbar-nav navbar-right'><li><a href='#'><i class='fa fa-user'></i> Welcome Back. "+response+"</a></li></ul>") } else { window.location.href = '/login'; } }, error: function(){ window.location.href = '/login'; } }); </script> </head> <body> <nav class="navbar navbar-default"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Node.js</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav" id="uls"> <li class="active"><a href="#">Home</a></li> <li><a href="about">About</a></li> <li><a href="contact">Contact</a></li> </ul> </div> <!--/.nav-collapse --> </div> </nav> <div class="container"> <div class="col-md-12"> <h1>Home Page</h1> <h3>Bootstrap & NodeJS</h3> </div> </div> </body> </html> و لا تنسى كتابة routing صفحتي الlogin and home و كذلك اللسنر في ملف server.js app.get('/',function(req,res){ res.redirect("/home"); }); app.get('/home',function(req,res){ res.cookie('name', req.cookies.name).sendFile(__dirname + "/home.html"); }); app.get('/login',function(req,res){ res.sendFile(__dirname + "/login.html"); }); app.listen(3000,function(){ console.log("Working on port 3000"); }); وللتاكد بأنه تم حفظ اسم المستخدم سنعمل routing اخر وهو: app.get('/api/cookies', function (req, res) { if(res.cookie('name', req.cookies.name) != null){ res.send(req.cookies.name); } else { res.cookie('name', "undefined") return res.json(401); } }); او من خلال console متصفح chrome بكتابة وبهذا, تستطيع تشغيل التطبيق الآن من خلال كوماند: node server.js و في المتصفح 127.0.0.1:3000/home

عالم البرمجة

عالم البرمجة مقالات برمجة و دورات مجانية لإحتراف البرمجة هدفنا تبسيط البرمجة ونشرها بيد الكل بشكل ممتع ومتطور ومحدث بإستمرار لمواكبة جديد تطورات البرمجة الحديثة و المتقدمة بدون مقابل