اذهب إلى المحتوى

Adnane Kadri

الأعضاء
  • المساهمات

    5129
  • تاريخ الانضمام

  • تاريخ آخر زيارة

  • عدد الأيام التي تصدر بها

    51

كل منشورات العضو Adnane Kadri

  1. و عليكم السلام و رحمة الله لا أظن أن يجب عليك تعلم إحداها فقط دون الأخرى , بل كلاهما . و هذا لأن لكل منها مجاله التخصصي و إستعمالاته و حاجته التي دعت إلى إنشاءه من الأساس , فالمقارنة بينهما غير منطقية . و لنأخذ كل منهما على حدة كالتالي : يستخدم Ajax بروتوكول HTTP ويمكنه إرسال طلبات باستخدام طرق POST و GET بين العميل والخادم. WebSocket هو بروتوكول اتصال بين العميل والخادم ، وهو يختلف عن HTTP . ففي Ajax ، عندما ترسل طلبًا ، يرسل الخادم استجابة لهذا الطلب ويتم إنهاء الاتصال , و هذا ما يجعله مناسبا لإستعمالات من مثل : التواصل مع واجهات تطبيق برمجية . أي أنه يسمح لتطبيق ما ,من جانب العميل, بطلب الوصول إلى مورد من جانب الخادم (مثلا : طلب صفحة أو صورة أو ملف أو بيانات) . في حين أن باستخدام WebSockets عند إنشاء اتصال بالخادم ، يمكنك التواصل بقدر ما تريد بين العميل والخادم والحفاظ على الاتصال نشطًا في كل لحظة , و هذا يجعله مناسبا للإستعمالات من مثل : تلقي إشعارات الوقت الفعلي أو الدردشة الحية , مثل الإشعار الذي تلقيته بشأن إجابة عن سؤالك هذا . يمكن تلخيص الأمر بشكل بسيط كالتالي : ما وراء الـ AJAX يعتمد إتصالا يتم إغلاقه مباشرة بعد الرد . ما وراء الـ WebSocket يعتمد إتصالا متواصلا . أمثلة توضيحية : يحتاج العميل " أحمد " تفحص صورة من على الخادم , فيقوم بإرسال طلب GET إلى الخادم . يستقبل الخادم الطلب و يقوم بإعادة رد برابط الصورة ليقوم أحمد برؤيتها , و ينتهي الإتصال و يتوقف الخادم عن تبادل أية بيانات بينه و بين أحمد , و سيحتاج أحمد اتصالا جديدا كل مرة يريد فيها طلب شيء من على الخادم . الان , العميل " أحمد " على موقع دردشة , ينتظر أي رسائل تصله . في مقابل أن العميل " عماد " يريد مراسلة " أحمد " . يقوم أحمد بإنشاء إتصال عن طريق بروتوكول ويب سوكيت بينه و بين الخادم , و ما إن وصلت أي رسائل جديدة لأحمد للخادم سيتم تنبيهه فورا . بعد أن يكتب عماد الرسالة و يرسلها , سيلتقط الخادم طلبه و يخزن الرسالة و يقوم فورا بتنبيه أحمد بذلك , فيكتب ردا و هكذا . أي أن من غير المعقول أن يشغل دور أحد الثاني , فلكل منهما منطقه الذي يتعامل به , فكل إستعمال لأحدهما في مجاله ميزة , و أي إستعمال له في غير تخصصه و مجاله عيب و هكذا . أما كاقتراح و تفضيل , فأفضل أن تتعلم Ajax أولا , كونه ما ستحتاج إليه طوال مسارك . ثم في وقت لاحق , قد تدعوك الحاجة إلى تعلم websocket لتحقيق أغراض أو حالات إستعمال معينة . و هو في الغالب ما كان مسار أي مطور . يمكنك تصفح إجابات مختلفة لتعاريف حول ما هو الـ websocket و لما قد نحتاجه هنا . كما قد تحتاج الإطلاع على كيفية التعامل مع ajax في الـ jQuery هنا .
  2. لاحظ أنه لا يوجد لديك فواصل منقوطة في نهايات العديد من الأسطر : السطرين برقم 0 و 1 في بداية النموذج الثاني . السطر برقم 8 في نهاية النموذج الأول . الأسطر برقم 0 و 9 في بداية النموذج الأول . قد أدى هذا إلى تعطيل قراءة السكربت كاملا , و لو قمت بتفحص شاشة الـ console ستجد رسالة تخبرك بما يحدث كالتالي : SyntaxError: missing ; before statement أو : SyntaxError: Unexpected 'document' كما أنه قد يوجد لديك مشكل بتحديد العنصر بالصنف : Applicant في السطر 0 في بداية النموذج الثاني كالتالي : document.getElementByClassName('Applicant 2'); في حين أن العنصر يتوفر كالتالي : <div class="lineheightExtra"> Applicant 2 </div> فها أنت تحاول تحديد العنصر التالي دون توظيف إسم صنفه على نحو صحيح , فالمفترض أن يكون هو ما هو كالتالي : document.getElementByClassName('lineheightExtra'); و ذلك حتى يتم تحديده بشكل صحيح .
  3. أفضل إستعمال مكتبة الجيكيوري DataTable لذلك فهي توفر وصولا أبسط لمختلف الصيغ التي نحتاج التصدير إليها . يتم تضمين ملف الجافاسكربت الخاص بها كالتالي : <script src="https://code.jquery.com/jquery-3.5.1.js"></script> <script src="//cdn.datatables.net/1.11.2/js/jquery.dataTables.min.js"></script> <script src="https://cdn.datatables.net/buttons/2.0.0/js/dataTables.buttons.min.js"></script> ثم ملف التنسيقات الخاص بها : <link rel="stylesheet" href="//cdn.datatables.net/1.11.2/css/jquery.dataTables.min.css" /> <link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.0.0/css/buttons.dataTables.min.css" /> و أخيرا تهيئة المكتبة على جدول معين , مضافا إليها خيارات توفير أزرار التصدير : $(document).ready( function () { $('#myTable').DataTable({ dom: 'Bfrtip', buttons: [ 'excel' ] }); } ); ستلاحظ ظهور زر تصدير أعلى الجدول , يمكنك الضغط على excel للتحصل على جدولك مصدرا بصيغة ملف excel , و سيتم ذلك على الفور .
  4. تكاد تكون أغلب هاته الوظائف ذات أسماء دلالية تدل على وظيفتها , مثلها مثل ملف init.js . فالدالة أو الوظيفة الأولى Ready ترجمة لجاهز : تعبر عن الإستدعاء بعد جهوزية الصفحة , و تحمل مجموع الشيفرات التي يتم إستدعاءها عند الحدث ready , و يتم هذا الحدث في اللحظة التي تكون قد حملت فيها الوثيقة . و الدالة أو الوظيفة الثانية تحمل مجموع الشيفرات التي يتم إستدعاءها عند الحدث load بالنسبة للنافذة , و يخص هذا الحدث تلك اللحظة التي تكون قد حُمّلت فيها كامل الموارد الخارجيّة مثل : روابط ملفات خارجية cdn أو صور . وبذلك تكون التنسيقات قد طُبّقت، ومقاسات الصور عُلمت، وما إلى ذلك . أما الوظيفة المعلقة بإسم Full Height function فتقوم هاته الدالة في الغالب بضبط مقاسات إرتفاع الحاويات و العناصر حتى تأخذ كامل الإرتفاع , مثل عنصر القائمة الجانبية. الوظيفة droopy , قد لا يدل إسمها عليها في الغالب. يلحظ أنها تحوي مجموع الشيفرات التي يتم فيها إضافة الأحداث إلى عناصر , و بعض الأسطر الأخرى التي يتم فيها تهيئة إضافات جيكويري مثل : Tooltip Popover Accordion js Slimscroll الوظيفة chat app تقوم في الغالب بضبط بعض الإعدادت الخاصة بمربع الدردشة , كما أنها تقوم بإضافة بعض الأحداث المتعلقة بذات العنصر . الوظيفة resize تشمل مجموع الشيفرات التي يتم إستدعاءها عند محاولة إعادة ضبط حجم الشاشة . من الصعب جدا تحديد ما يقوم به كل سطر من الشيفرة دون التوغل فيها بشكل كبير جدا , كما أن الملف كغيره من ملفات الجافاسكربت التي تحمل مجموع شيفرات معينة , و بالتالي فإن الوظائف التي يحويها الملف ليست أكثر من وظائف جافاسكربت عادية . فحاجة مبرمج الموقع إلى تنظيم عمله و تهيئة الموقع بشكل أنظف و أكثر تنظيما دعته إلى إنشاء كل الوظائف , التي من شأنها تهيئة : عنصر , مكتبة أو حدث , في ملف منفصل .
  5. هو بداية ليس أكثر من ملف جافاسكربت عادي , و في الغالب الملفات بالإختصار الدلالي init هي إختصار للكلمة initialize و التي تعني بدء أو تهيئة بالعربية . و دليله هو احتواءه على ما هو لازم لتهئية مجموعة الوظائف أو الموقع و تفاعليته مثل الذي لديك . لذلك نجده من يضعه في جافاسكربت و يضم به وضائف من مثل : إضافة أحداث و تفاعليات إلى عناصر الـ DOM أو تهيئة و إعداد أي مكتبات أو إضافات لإستعمالها . وهو نفس ما يقوم به صاحب الموقع بنفس الملف , لاحظ قطعة من سلسلة عمليات إضافة الأحداث : /*Sidebar Navigation*/ $(document).on('click', '#toggle_nav_btn,#open_right_sidebar,#setting_panel_btn', function (e) { $(".dropdown.open > .dropdown-toggle").dropdown("toggle"); return false; }); $(document).on('click', '#toggle_nav_btn', function (e) { $wrapper.removeClass('open-right-sidebar open-setting-panel').toggleClass('slide-nav-toggle'); return false; }); $(document).on('click', '#open_right_sidebar', function (e) { $wrapper.toggleClass('open-right-sidebar').removeClass('open-setting-panel'); return false; }); $(document).on('click', '.product-carousel .owl-nav', function (e) { return false; }); $(document).on('click', 'body', function (e) { if ($(e.target).closest('.fixed-sidebar-right,.setting-panel').length > 0) { return; } $('body > .wrapper').removeClass('open-right-sidebar open-setting-panel'); return; }); $(document).on('show.bs.dropdown', '.nav.navbar-right.top-nav .dropdown', function (e) { $wrapper.removeClass('open-right-sidebar open-setting-panel'); return; }); $(document).on('click', '#setting_panel_btn', function (e) { $wrapper.toggleClass('open-setting-panel').removeClass('open-right-sidebar'); return false; }); $(document).on('click', '#toggle_mobile_nav', function (e) { $wrapper.toggleClass('mobile-nav-open').removeClass('open-right-sidebar'); return; }); لاحظ تهيئة العديد من إضافات الجيكويري و البوتستراب للإستعمال : /*Counter Animation*/ var counterAnim = $('.counter-anim'); if (counterAnim.length > 0) { counterAnim.counterUp({ delay: 10, time: 1000 }); } /*Tooltip*/ if ($('[data-toggle="tooltip"]').length > 0) $('[data-toggle="tooltip"]').tooltip(); /*Popover*/ if ($('[data-toggle="popover"]').length > 0) $('[data-toggle="popover"]').popover() أي أنه ليس أكثر من ملف بإسم دلالي لتنظيم عملية سير الموقع و تهيئة اللازم لسيرها بشكلها الصحيح . و بالتالي فإن ما وصفته بالمكتبات : ليس كذلك و إنما أشبه بالوظائف أو العمليات المنفصلة , و تعليقها أعلى الملف ليس أكثر من فهرسة لمحتويات الملف , فمثلا : الوظيفة Ready تشمل مجموع الشيفرات التي يتم إستدعاءها بعد تحميل الوثيقة , و هي نفسها تستدعي الوظيفة droopy . لا أبدا , فالملف يستعمل فقط جيكويري و سياق لتهئية الموقع , المكتبات , الإضافات و الأحداث . لا , فذلك غير منطقي أبدا . و لكل ملف حاجته و دوره و لا علاقة لأحدهما بالثاني , فـ package.json هو مستند JSON ، يعتمد عليه مدير حزم الجافاسكربت npm لإدارة الحزم و القراءة من عليها . أما ملف init.js فهو مجرد ملف كغيره من ملفات الجافاسكربت , يحمل شيفرات جافاسكربت عادية . الشيء الوحيد الذي يجعل اسمه دالا عليه هو أن هاته الشيفرات تستعمل بغرض التهيئة و التحضير .
  6. المستخدم الذي قام بالتلاعب بقيمة المتغير المؤثرة في شروط عرض مكونات معينة لن يكون تعديل شيفرة المراقبة و إعادة التحميل مشكلة بالنسبة له . كما أن هاته الحالات خاصة جدا , فعوام المستخدمين لا يفكرون بنفس الطريقة . و حتى إن كان و تم الوصول لذلك بأية طريقة كانت , لن يكون من عرض قالب فارغ جدوى من الأساس . أي أن الأهم من كل ذلك : مصادقة طلبات جلب البيانات قبل عرضها , و يكون كل هذا في الواجهة الخلفية بعيدا عن المستخدم . كما أن هذا لا يمنعك من ضبط طريقة التصفح و منع عوام المستخدمين من الوصول إلى صفحات ليست لهم صلاحية الوصول إلى البيانات التي تعرض بهاته المكونات , و يكون ذلك بالتوجيه إلى صفحات عامة أو قابلة للوصول من أي كان في حالة إرسال طلب من مكون خاص لا يمكن لمستخدم عام تصفحه .
  7. المشكلة الوحيدة لديك هي أن قاعدة البيانات التي تحاول القراءة من عليها فارغة , فمن المنطقي أن لا يتم الإنطلاق في الدور foreach و القراءة من عليه . أي أن أي شيفرة بداخل الدور كالتالي : foreach($stnt as $val) { echo 'يوجد بيانات في قاعدة البيانات'; سيتم تجاهلها في حالة ما كان المعاد من تنفيذ الإستعلام stnt مصفوفة فارغة . في حين أن نفس الشيفرة سيتم تنفيذها في حالة كان المعاد من تنفيذ الإستعلام مصفوفة بعناصر يمكن القراءة من عليها عن طريق الدور . و لذلك تأكد من أن الجدول data الذي تحاول القراءة من عليه يمتلك على الأقل قيمة أو أكثر افتراضيا حتى يكون ما داخل الدور foreach قابلا للوصول . و لكن أفهم أن الفكرة التي تحاول تطبيقها هي : و لكن ما هو عيب هاته الطريقة ؟ => هو أنه لن يتم تسجيل أي عضو في حالة ما لم يتم تسجيل على الأقل عضو أو أكثر يدويا من قبل , فهذه هي الطريقة الوحيدة للوصول إلى ما داخل الدور . و لتجاوز هاته المشكلة سنقوم بتطبيق المنطق التالي : يتم قبول أي عضو تلقائيا ما ان لم تكن بياناته مطابقة لعضو اخر مسجل بالفعل . و ذلك عوضا عن : التحقق من أن كامل الأعضاء لا يطابقون بيانات هذا العضو كشرط لتسجيله , بحيث يقوم هذا بإغفال احتمال فراغ قاعدة البيانات . لنقم بالتالي : تعريف متغير isAlreadyRegistered كمتغير يحمل قيمة false افتراضيا . يتم تغيير قيمة isAlreadyRegistered إلى true في حالة مطابقة بيانات أحد الأعضاء المسجلين لبيانات العضو الذي يحاول التسجيل . يتم في مرحلة أخيرة التحقق من قيمة isAlreadyRegistered و التصرف بناء عليها . فإن كانت isAlreadyRegistered تحمل القيمة false تم تسجيل العضو و إلا فلن يمكن ذلك و ستظهر رسالة الخطأ . ستتبع الشيفرة نحوا مشابها : $isAlreadyRegistered = false; foreach($stnt as $val) { if ($val["emailw"] == $this-> mail) { // لاحظ شرط التطابق $isAlreadyRegistered = true; // إعادة تعيين قيمة المتغير break; } } if (!$isAlreadyRegistered) { // return $val["emailw"]; $conn-> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // send data to database .. $stmt = $conn - > prepare("INSERT INTO data (namew, emailw, passwordw, datew) VALUES (:name, :mail, :pass, :date)"); $stmt-> bindParam(':name', $namep); $stmt-> bindParam(':mail', $mailp); $stmt-> bindParam(':pass', $passp); $stmt-> bindParam(':date', $datep); $namep = $this-> name; $mailp = $this-> mail; $passp = $this-> pass; $datep = $this-> date; $stmt-> execute(); return "Successfully connected .."; } else { return 'this email has created ..'; } ثم سيمكنك إنشاء أعضاء في كامل الحالات و وفقا لأي احتمالات . ملاحظة : الشيفرة لديك قد تحتاج بعض التنظيم و التنظيف حتى تصبح مفهومة و سهلة التشخيص و القراءة , و قد كان ذلك ضروريا حتى أستطيع التوغل في شيفرتك و أفهم مرادك منها . يمكنك التحصل على نسخة أكثر تنظيما و تنسيقا لملفك هنا : index.php .
  8. هلا تأكدت من أن مزود الاستضافة الخاص بك يسمح لك بإرسال رسائل البريد الإلكتروني ولا يحد من إرسال رسائل البريد الإلكتروني ؟ و ذلك لأن العديد من مضيفات الويب المشتركة ، وخاصة موفري الاستضافة المجانية ، إما لا تسمح بإرسال رسائل البريد الإلكتروني من خوادمها أو تحد من العدد الذي يمكن إرساله خلال أي فترة زمنية معينة . و قد تحتاج إلى التواصل مع فريق دعمهم للتحقق مما إذا كانت هناك أي قيود مفروضة على إرسال رسائل البريد الإلكتروني أو لا . في مثل هاته الحالات يلحظ سلوك مشابه لدالة mail , إذا تقوم بإعادة قيمة صحيحة و تعتبر أن إرسال الرسالة تام , في حين أنه لا يتم إستقبال أي رسالة في صندوق البريد . شيء اخر قد تحتاج التأكد منه و هو أن القيمة الممررة في : From قيمة صحيحة أي أن عنوان البريد الإلكتروني التالي : info@yhyasyrian.cf موجود بالفعل . ان كان كل شيء صحيحا , قد تحتاج تمكين سجل الأخطاء الخاصة بالوظيفة أو الدالة mail , و لنتأكد أن نقوم بوضع هذا قبل الشيفرة لديك : ini_set("mail.log", "/tmp/mail.log"); ini_set("mail.add_x_header", TRUE); و قد تحتاج في حالات أخرى إستعمال خدمات أو موفرات SMTP أخرى لإرسال و إدارة البريد الإلكتروني , و ذلك لأنها توفر مميزات إضافية و خيارات إرسال أخرى . يقترح أحد التالي : PHPMailer (شائع إستعماله) swiftmailer pearMailer يمكنك التعرف على كيفية إرسال رسالة بإستعمال PHPMailler و إرسال بريد إلكتروني باستخدام php. كما يمكنك القراءة أكثر عن طريقة إرسال بريد إلكتروني في PHP بإستخدام الوظيفة mail .
  9. في الحقيقة فكرة حماية عرض مكون في تطيبقات الصفحة الواحدة أو تطبيقات الويب التقدمية فكرة تعاب فيها هاته التطبيقات , إذ أن اقصى حماية لأي مكون أو أية صفحة عرض هي عن طريق طبقات وسيطة تستعمل قيما و شروطا مهما تم التلاعب فيها وتطبيق الأفكار عليها ستبقى مخزنة أو متحقق منها محليا و على المتصفح . ولكنه يجب الإنتباه إلى أن عرض مكون دون بيانات ليس له معنى فسيكون مجرد قالب , و لذلك التركيز الحقيقي لا يكون على حماية صفحات العرض و المكونات و إنما على البيانات التي تستجلب من الواجهة الخلفية . كما أن التوجه إلى تطبيقات الـ ssr أو الـ server side rendering سيقوم بتجاوز هذا الإشكال و حله بشكل نهائي , و كونك تستخدم vueJS فسيكون إستعمال NuxtJs موافقا و سهلا .
  10. يجب أولا فهم الغرض من القنوات الخاصة أساسا , فالقنوات الخاصة في الويب سوكيت وجدت للتحقق ما ان كان سيسمح للمستخدمين بالاستماع إلى هاته القنوات الخاصة أو لا , و ذلك بالإعتماد على شروط تتوفر فيمن يقوم بطلب الإستماع مثلا أو أية شروط أخرى . يتم تحديد قواعد ترخيص القناة الخاصة هاته بنا في ملف : route / channels.php الخاص بتطبيقنا . تحتاج أولا تعريف القناة بالملف المذكور كالتالي : Broadcast::channel('new-notification.{postUserId}' , function ($postUserId) { }); كما أنها ستحمل شيفرة ما يتم التحقق ما إن كان للمستخدم الحالي الحق في الإستماع لأحداث هاته القناة , كأن يتم مطابقة معرف القناة الخاصة و التأكد من امتلاك المستخدم لمنشور بهذا الإسم , أو أية طريقة تحقق كانت . يمكنك صياغة منطق الشيفرة وفق حاجتك للقناة الخاصة من الأساس . مثلا : Broadcast::channel('new-notification.{postUserId}' , function ($postUserId) { if(auth()->user()->can_view_notfs_of($postUserId)){ return true; } }); بحيث سيكون هذا المسار نقطة تحقق قبل الإشتراك في القناة بالنسبة لمستخدم معين أو تحقق شرط معين . و هذا من جانب الواجهة الخلفية , أما من جانب الواجهة الأمامية فسيتم تحديد نقطة الوصول هاته -نقطة التحقق- بإستعمال الخاصية authEndpoint مرفقا بـ csrf_token : var pusher = new Pusher("4fb4fa908d87ec86abf9", { cluster: '{{ env('PUSHER_APP_CLUSTER') }}', authEndpoint: '/broadcasting/auth', auth: { headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}', } } }); بعد ذلك ستعمل القنوات الخاصة وفق المطلوب .
  11. القناة بالإسم : 'new-notification.'.$this->post_user_id بالفعل قناة خاصة Private Channel لديك , هلا قمت بتوضيح سؤالك أكثر ؟ يمكنك الإستغناء عن laravel ehco إن كنت تستخدم pusher كويب سوكيت دريفر , و لا علاقة لذلك بنوع القناة .
  12. بإنهائك لدورة تطوير واجهات المستخدم ستصبح مطور واجهات مستخدم , و هذا لأنك ستتعرف على كل من : مفهوم الواجهة الأماميّة للموقع front-end وكيفية عملها . أساسيات لغات تطوير واجهات المستخدم: HTML و CSS و JavaScript . استخدام أحدث أدوات التطوير: Bootstrap 4 و jQuery و Sass . التعامل مع خدمة استضافة المشاريع البرمجية GitHub و GitLab . نشر صفحات الموقع على الإنترنت . إعداد هيكل الموقع ووضع خطة العمل . التصميم المتجاوب مع مختلف الأجهزة والشاشات . و مطور واجهة المستخدم هو المسمى الوظيفي لمن يكون مسؤولا عن بناء الموقع من الجانب الشكلي العام من هيكلية و تصميم و تفاعلية . يشمل هذا المسمى الوظيفي الفروع التالية : البرمجة بإستخدام الجافاسكربت و أدواتها , و تصميم الويب بإستخدام الـ css و أدواتها . أي أن التعبير مطور واجهات مستخدم وفق المقدم في دورة واجهات المستخدم يتضمن صفتي " مبرمج " و " مصمم " معا . و للتفصيل أكثر يمكن تعريف كل منهم وفق التعريفات التالية : مصمم الويب : يهتم بالتصميم الخارجي للموقع . مبرمج الويب : الشخص المفوض إليه عمليات التكويد و كتابة الشيفرة , له إمكانية كتابة أكواد و خوارزميات أكثر تعقيدا , لا يعير إهتمام لشخص المستخدم أو تجربته . مطور الويب : إهتمامه أكثر بتجربة المستخدم نحو التطبيق المفوض إليه , معرفته بالمستخدم أكثر و بالتكويد و التعقيد أقل عادة .
  13. مثلما ذكر المدرب حسن حيدر فإن الخاصية ليست قياسية أو على المسار القياسي الذي تحترمه كامل متصفحات الويب كما أنها تابعة لمجموعة الإضافات ذات السابقة webkit- . و يقصد بغير قياسي: أن استخدامها لا يكون في مواقع الإنتاج التي تستهدف كامل المتصفحات و الأجهزة , فالخاصية قد لن تعمل مع كل مستخدم . كما أنه قد يكون هناك أيضا عدم توافق كبير بين عمليات التنفيذ , أو ربما قد يتغير السلوك في المستقبل . يمكنك التعرف على قائمة المتصفحات التي تدعم مجموعات الإضافات webkit هنا . و بشكل عام , تحدد الخاصية -webkit-text-fill-color لون " تعبئة أحرف النص" . فإذا لم يتم تعيين هذه الخاصية ، يتم استخدام خاصية اللون color لها . أي أن : يتم تأويل إستعمال -webkit-text-fill-color على إستعمال الخاصية color إن تم إعطاء لكل منهما قيمة مخالفة للثانية : مثال 1 . الخاصية -webkit-text-fill-color تقبل إستعمال القيمة transparent لها على عكس الخاصية color مما يسمح بتطبيق العديد من الأفكار عليها : مثال 2 . يتم إستعمال الخاصية -webkit-text-fill-color عادة بمحاذاة الخاصيتين -webkit-text-stroke-color و -webkit-text-stroke-width , على عكس الخاصية color التي تستعمل وحدها . الخاصية -webkit-text-fill-color هي خاصية ليست قياسية أي أنها ليست مدعومة من قبل كامل المتصفحات على عكس الخاصية color . إليك قائمة المتصفحات الداعمة : المصدر : https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-text-fill-color
  14. يمكنك إستخدام ما يعرف بالتعليقات الشرطية لحجب المحتوى أو عرض رسالة معينة بناءا على متصفح المستخدم في أي صفحة أو مكون , و كونك تستخدم تطبيق nuxt.js يمكنك مباشرة إضافة هاته الأسطر : <div> <!--[if IE]> <p>عذرا, Internet Explorer غير مدعوم.<p> إستعمل <a href="http://google.com">Chrome</a> بدلا. <![endif]--> <![if !IE]> <Nuxt /> <![endif]> </div> إلى ملف default.vue قبل إخراج ملف dist عن طريق الأمر : npm run generate كما يمكنك إنشاء مكون كامل ليتم عرضه بدلا من رسالة بسيطة : <template> <div> <!--[if IE]> <IENotSupportedComponent /> <![endif]--> <![if !IE]> <Nuxt /> <![endif]> </div> </template> <script> import IENotSupportedComponent from '@/components/IENotSupportedComponent'; export default defineComponent({ name: 'Default', components: { IENotSupportedComponent }, }); </script>
  15. قبل التحدث عن وسم div ينبغي معرفة أن وسوم HTML تنقسم إلى ثلاث فئات رئيسية : Block level Tags : تشمل كل العناصر و الوسوم التي تأخذ كامل عرض حاوياتها افتراضيا . Inline Level Tags : تشمل كل العناصر و الوسوم التي توضع تلقائيا في خط أفقي افتراضيا ، و عندما تنفد المساحة على المحور الأفقي ، فإنها تلتف في السطر التالي وهكذا . Meta Level tags : تشمل كل العناصر و الوسوم التي لا تظهر في الصفحة كعناصر أو تقسيمات أو حاويات , و لكنها تستعمل لمهام أخرى (مثل توجيه محركات البحث نحوها) . وسم div هو وسم Block level tag , و يعبر عن اختصار division بالإنجليزية أو تقسيمة بالعربية . و يستخدم لإنشاء تقسيمات أو أقسام حاوية منفصلة للمحتوى في صفحة الويب مثل حاويات لكل من : استمارة أو نموذج , نص ، صور ، رأس ، تذييل ، شريط تنقل ، إلخ . و بالتالي فإن الغرض من استخدام علامة div هو تقسيم صفحة ويب ليس إلا . إذا نظرت إلى موقع ويب نموذجي ، يمكنك تقسيمه إلى أقسام منطقية. على سبيل المثال ، إذا نظرت إلى صفحة أسئلة البرمجة في أكاديمية حسوب ، يمكنك تقسيمه إلى شريط التنقل أعلى الشاشة ، وقسم المحتوى أي ينقسم إلى شريط تصفح علوي و اخر سفلي و قسم للمحتوى الرئيسي . يمكن تقسيم قسم المحتوى الرئيسي إلى سلسلة من الأسئلة والشريط الجانبي الأيسر . كل عنصر من هذه العناصر موضوع في وسم div لفصله كتقسيمة و عنصر . رغم أن هنالك العديد من الوسوم الأخررى التي يمكن لها أن تقسم صفحة الويب إلى حاويات و أقسام إلا أن إستعمال div شائع لعدة أسباب نذكر من بينها : أن وسم div يحتوي كل من علامة الفتح (<div> ) وعلامة الإغلاق (</div>) بشكل إلزامي لإغلاق الحاوية . يجعلنا هذا نتعرف بسهولة على بداية و نهاية كل حاوية . وسم div هو Block level tag , أي أنه يقوم بالنزول سطرا تلقائيا عند كل وسم فتح له , على عكس وسوم من مثل span أو label التي هي وسوم سطرية inline level tags . وسم div هو عنصر حاوية عامة , على عكس وسم body مثلا الذي يجب أن يتوفر مرة واحدة في هيكلية الـ HTML لكل صفحة . داخل وسم div يمكننا وضع أكثر من عنصر HTML و يمكن تجميعها معًا ويمكننا تطبيق CSS عليها على خلاف لو قمنا مثلا بتعريف هاته العناصر بشكل مباشر في وسم الـ body . كما أنه يقبل أية أنواع من العناصر و الوسوم داخله على عكس وسوم أخرى تشترط امتلاك عناصر محدودة . مثلا : يمكن استخدام وسم div لإنشاء تخطيط لصفحات الويب أو Layouts بالإنجليزية بسهولة و مرونة . لاحظ التخطيط : يمكن تخصيص عرضه و إرتفاعه بشكل مرن جدا , على عكس وسوم أخرى تشترط أن لا تتجاوز عرضا معينا . و هذا في الغالب ما جعل صاحب الفيديو يعتمد تقسيم الصفحة وفق وسوم div , كونه يريد أقصى مرونة و سهولة في تحكمه بعناصر صفحته . ومع ذلك ، اتجاه تطوير الويب في الاونة الأخيرة أصبح يتحرك نحو الاتجاه الدلالي أو الـ semantic direction . فبدلاً من عناصر div العامة ، من المفترض أن تستخدم العلامات الدلالية الأحدث التي تشير بشكل أفضل إلى أي شيفرة تبحث عنها في الصفحة . لذلك أصبح لدينا علامات التنقل nav والقسم section والرأس headere ،و غيرها . و لذلك فمن الناحية النظرية , ستجد البعض يطالبون أو يعتبرون أن من المفترض أن تتم إزالة الحاجة إلى علامات div العامة بشكل نهائي . أما من الناحية العملية ، فلا يزال معظم الأشخاص يستخدمون divs فقط . كونها طريقة مهيمنة و شائعة جدا , أو على الأقل أفضل من الأيام التي كان فيها يتم تصميم الصفحات باستخدام الجداول و الإطارات ! و طبعا هذا بجانب إمتلاكها للمميزات التي تم ذكرها سابقا . تعرف أكثر عن : و أيضا : توثيق وسم div : هنا .
  16. قد يكون سؤالك متشعب كثيرا كونك لم تحدد ما تقصده بالضبط بـ "التعديل على الكود و بناء المواقع " , فعملية بناء المواقع عملية متسلسة و تتفرع إلى كثير من التخصصات و يستعمل فيها الكثير من اللغات . فالمواقع و تطبيقات الويب بصفحة عامة تنقسم إلى قسمين : واجهات خلفية Backend : تمثل كل العمليات و المنطق الحاصل على مستوى الخادم , يتم في هاته المرحلة عادة بناء واجهات تطبيق برمجية لتسهيل ربطها مع الواجهة أو الواجهات الأمامية . واجهات أمامية Frontend : تمثل مجموع التصاميم و التفاعليات و بنى العناصر , يتم في مرحلة بناء الواجهات الأمامية بناء شاشات و قوالب قد تكون تفاعلية و قد تكون صماء . و كون أغلب العمليات تبتدئ من الخادم فسيكون المسؤول الأول عن عرض الصفحة لديك بشكل أو بتنسيق أو تفاعلية معينة , و لذلك نجد صفحات بلواحق php. تحمل شيفرات واجهات أمامية من مثل HTML أو جافاسكربت أو CSS . و لذلك فإن التعديل على هاته الصفحات يكون موجها و مقيدا بالهدف من التعديل : فإن كان الهدف التعديل على الواجهات الأمامية , مثل القوالب , فسيمكن مباشرة التعديل على بنية الـ HTML أو الملفات أو الأسطر المسؤولة عن تنسيق العناصر أو عن تفاعليتها , دون المساس بأي منطق داخل محددي الـ PHP : <?php // PHP هنا شيفرة ?> <div class="container-fluid"> .. </div> <?php // PHP هنا شيفرة ?> أما ان كان الهدف تغيير طريقة تعامل الخادم مع الطلبات و كل عمليات الخادم فسيتطلب التعديل على ما داخل المحددين , و إن لزم خارجهما . فاﻷول هو ما يقوم به مطورو الواجهة الأمامية , و الثاني هو ما يقوم به مطورو الواجهة الخلفية . نعم يمكن و هو المفترض أن يكون , فلا دخل لما يحدث على الواجهة الخلفية في الواجهة الأمامية . و قد لا تتطلب الكثير من التطبيقات و المواقع واجهة خلفية أصلا , مثل قوالب الـ HTML أو صفحات العرض أو أي من المواقع ثابتة المحتوى . و لذلك فإن إستعمال HTML , JS , CSS كاف جدا بهذا الخصوص . التعديل على واجهات المستخدم لا يلزم في الغالب أي معرفة مسبقة بخصوص الواجهات الخلفية في التطبيقات و المواقع المبنية بتنظيم , و لكن كون الواجهة الخلفية هي المحرك الأول فسيكفي - في الغالب - امتلاك معرفة سطحية لسهولة التصفح و التنقل بين الملفات و فهم الشيفرة , قبل على التعديل على ما يخص الواجهة الأمامية منها .
  17. الكود النظيف بشكل عام هو أمر شخصي و ذاتي و لكل مطور وجهة نظر شخصية بخصوصه . ولكن هناك بعض الأفكار التي يتفق عليها الأغلب و يعتبرونها أفضل الممارسات لما يشكل شيفرة نظيفة , مفهومة , قابلة للقراءة و التعديل على نطاق واسع . أي باختصار : و لنأخذ المفهوم بشكل أعمق كالتالي : سهولة الفهم تعني سهولة قراءة الكود ، سواء كان ذلك القارئ هو المؤلف الأصلي للكود أو أي شخص آخر . لذا فهو يقلل من الحاجة إلى التخمين وإمكانية حدوث سوء فهم . من السهل أن نفهمه على كل المستويات ، وعلى وجه التحديد : منطق العمل للتطبيق بأكمله . كيفية تعاون الكائنات و الأصناف المختلفة مع بعضها البعض . دور ومسؤولية كل فئة و كائن . ما تفعله كل دالة و تابع . الغرض من كل تعبير يتم تعريفه , سواء متغير , ثابت أو خاصية . أما سهولة التعديل تعني أن الشيفرة سهلة التوسيع , التطوير وإعادة البناء . كما أنه من السهل إصلاح و تشخيص الأخطاء فيها , و نفس الأمر ينطبق أيضا : سواء كان ذلك القارئ هو المؤلف الأصلي للكود أو أي شخص آخر . و يشمل ذلك النقاط : الكائنات و التوابع صغيرة الحجم ولا تتحمل سوى مسؤولية واحدة (و ذلك احتراما لمبدأ فصل المهام ) . تتوفر الكائنات على واجهات برمجية عامة واضحة و موجزة . يمكن التنبؤ بكبفية عمل الكائنات و توابعها . الكود قابل للاختبار بسهولة ولديه اختبارات وحدة (أو على الأقل من السهل كتابة الاختبارات) . الاختبارات - إن توفرت- فهي سهلة الفهم والتغيير بسهولة . و لكن لما نحتاج الإهتمام أصلا بالكود النظيف ؟ لنقم بتلخيص أهمية الأمر في النقاط التالية : يجب أن تهتم لأن الشفرة (في الغالب ) لا تتم كتابتها مرة واحدة و فقط . و إنما في معظم الأوقات ، تحتاج أنت أو أي شخص آخر إلى العمل على الكود. ولكي تكون قادرًا على العمل عليه بكفاءة ، فأنت بحاجة إلى فهمه بالدرجة الأولى . مبادئ كتابة كود نظيف تمنحك الثقة أثناء كتابة شيفرتك . تكون الأخطاء أسهل للتشخيص و الحل . تجعل الكود سهل للصيانة و التطوير . و قد يتعلق مفهوم الكود النظيف بكثير من المفاهيم الأخرى , من مثل أنماط التصميم و مبادئه و غيرها . و لذلك قد تجد بعضهم يستعير بعض مبادئ تصميم البرمجيات ليستعملها كمبادئ للكود النظيف , من مثل مجموعة مبادئ SOLID (سنأتي لإرفاق سلسلة مقالات تخص كل مبدأ) أو DRY (اختصارا لترجمة لا تكرر نفسك Don't Repeat Yourself ) أو YAGNI (اختصارا لترجمة أنت لن تحتاجها You Aren't Gonna Need It) أو غيرها من المبادئ . و لذلك فهي عملية متشعبة جدا . و لعل الكود النظيف هو ما يصنع الفارق بين مبرمجي نفس اللغة و نفس إطار العمل , فإن كنت لا توليه أهمية أو أولوية فسيجب عليك ذلك . لأنك لن تلتفت إليه بداية كونك بكامل تركيزك وإستيعابك للكود, و لكنك ستجد نفسك في حاجة إليه عندما تبتعد قليلا عن تطوير تطبيقك ثم تقرر العودة إليه . و أتذكر جيدا إضطرار أحد فرق التطوير لنسف الكود بأكمله (الذي كان بحجم 400 ميغا) و إعادته لمجرد أن مطوريه نفسهم عجزوا عن فهمه بعد أقل من سنة من إنطلاقه . يمكنك التعرف أكثر على مبادئ SOLID لتصميم البرمجيات في سلسلة المقالات التالية : S O L I D تعرف أكثر على الشيفرة النظيفة هنا و هنا . كما يمكنك التعرف أكثر على مفهوم الكود النظيف في HTML , CSS و Sass هنا .
  18. لنقم بتناول الأمر بشكل عام على هذا النحو : الـ devDependencies : هي مجموع التبعيات و الحزم المطلوبة للتشغيل على بيئة التطوير , أي تلك التي يتم إستعمالها فقط أثناء التطوير أو الإصدار ، على سبيل المثال : الحزم المستعملة في اختبارات الوحدة . مثل حزمة jest في تطبيقات الـ node , react , angular و الـ vueJS , عناصر و حزم webpack . بحيث تشكل مجموع الأدوات التي تساعدك على إدارة كيفية تطوير التطبيق لديك . هاته الحزم يتم تثبيتها عن طريق مدير الحزم npm مثلا بإضافة الخيار save-dev-- : npm install pakcageName --save-dev الـ Dependencies : و هي مجموع التبعيات و الحزم التي يحتاجها مشروعك ليكون قادرًا على العمل في بيئة الإنتاج . على سبيل المثال : الحزم المستعملة في عرض أو تنسيق أو تفاعلية جزء من أجزاء الصفحة , فلو احتجنا إلى حزمة للحصول على اليوم و الشهر . فسنجد أننا نقوم مثلا باستيراد {getDate} من الحزمة "date-fns" في مكون ما , و بالتالي فإنه بدون هذه الحزمة لن يعمل كودنا . هاته الحزم يتم تثبيتها عن طريق مدير الحزم npm مثلا بدون إضافة أي خيار : npm install myPackage الـ PeerDependencies : هي مجموع الحزم التي تحتاجها حزمة ما لكي تشتغل بشكل طبيعي , و نادرا ما يتم التعامل مع هاته التبعيات و الحزم . و يقصد بها أي حزمة B تتطلبه حزمة معينة A ما ولكنها لا تشمله مع نفسه عند تثبيته . على سبيل المثال : حزمة popper.js مع بوتستراب , فهي حزمة يستعملها Bootstrap 4 لإظهار النوافذ المنبثقة و بعض التأثيرات و التفاعليات في بوتستراب , و لكن بوتستراب لا يتضمنها عند التثبيت و قد نغفل في كثير من الحالات عن تثبيتها فتسبب بعض المشاكل من مثل : مثال 2 : . يطلق هنا على popper.js و مثلها من الحزم لفظ peer dependecies لـ bootstrap . يمكن نمذجة طريقة التعامل معها عن طريق مدير الحزم npm كالتالي : ./node_modules/ | | | +- devDependency | | | | +- dependency/node_modules/ | | | +- peerDependency-1/ | | +- dependency | | | | | +- devDependency/node_modules/ | +- peerDependency-2/ كما يوجد أيضا : الـ bundledDependencies و الـ OptionalDependencies . قد لا يختلف الأمر كثيرا مع بيئات و لغات مختلفة , كما قد تختلف طريقة التعامل مع كل منها مع مدراء الحزم من مثل npm , composer , yarn , pip . سواء في أسماءها أو اللواحق أو الخيارات التي إضافتها لتحديد نوع الحزمة أو التبعية , أو ربما في طريقة تنسيق بنية ملفات الحزم و التبعيات أو أيضا في ملف مدير الحزمة (مثل composer.json و package.json) . و لكن يبقى منطقها و تقسيمها سواءا مهما اختلف كل ذلك .
  19. التعريفات و الأفكار حول هندسة البرمجيات متفاوتة و كثيرة . و قد يصب مجملها و سياقها العام في مفهوم واحد جامع . بحيث يمكن القول على أنها فرع من فروع الهندسة حيث يقوم على مجموعة من الأسس التي تهدف إلى تصميم و تطوير البرامج بجودة عالية تلبي بالدرجة الأولى احتياجات المُستخدمين . يمكن أيضا الاستعانة ببعض المراجع و المصادر العالمية في التعريف بها : و أيضا : مما سبق يمكن فهم أن هندسة البرمجيات ليست كتابة شيفرة أو تكويدا و فقط , فمثل ما شرح المدرب عبد الحميد في تعليق سابق هي جزء من مرحلة التنفيذ . يمكن من هذا إستنتاج أن هندسة البرمجيات عملية إنتاجية لها عدة مراحل أساسية وضرورية للحصول على المُنتج البرمجي النهائي . بحيث يكون الهدف النهائي من أي برنامج هو الحصول على أفضل كفاءة ممكنة بأقل كلفة ممكنة. بحيث يطلق على مجمل هذه المراحل اسم دورة حياة تطوير النظام البرمجي أو بالإنجليزية : Software Development Life Cycle , و اختصارها " SDLC " . و كون فلسفاتها و نماذج بناءها كثيرة و متفاوتة سنأخذ أحد النماذج الكلاسيكية مثالا , هذا النموذج يعرف بنموذج الشلال أو Waterfall Model . لنقل أن هندسة البرمجيات وفق هذا النموذج تتبع بشكل عام المراحل التالية : تحليل المتطلبات Requirement Analysis : في هاته المرحلة يتم تجميع المتطلبات لفهم المشكلة و متطلبات الزبون أو المشروع ، هنا أيضا يتم تقسيم أو توزيع كل موضوع كبير أو معقد إلى اجزاء اصغر من اجل اكتساب فهم أفضل وأسهل للمشكلة والاهداف . التصميم Design : في هاته المرحلة يتم تصميم حلول للمتطلبات التي جمعناها، عملية تحتوي على انشطة معينة مثل صياغة وترتيب، لتحقيق الاهداف , و لا يعنى بالتصميم التصميم بمعناه و إنما تصميم حلول افتراضية أو منمذجة في مخططات لأفضل ما يليق أو ما قد يليق بالمشروع . التنفيذ Implementation : بعد تحديد المتطلبات والأهداف والاتفاق على لغة البرمجة ووضع الخطوط الأساسية للبرنامج وبنيته، يقوم الفريق بتنفيذ “ نموذج أولي Prototype ” للبرنامج . الاختبار Testing : في مرحلة الاختبار، يقوم الفريق باختبار البرنامج والتأكد من أنه يقوم بكافة الوظائف المطلوبة أو يتناسب مع المتطلبات التي تم تحديدها مسبقا . التطوير Evolution : يقوم الفريق بالبحث عن سبل تطوير البرنامج أو تطويره إنطلاقا من MVP (الحد الأدنى للمنتج أو Minimum Viable Product) . يتم اقتراح و إضافة ميزات جديدة له، كما تتم ماقشة إمكانية أو سبل جعله أكثر فاعلية وأكثر كفاءة . المخطط التالي يشرح خطوات النموذج : و بالتالي فإنها عملية منهجية و منظمة للغاية , و في الغالب تتم بالتنسيق بين فرق من مجالات مختلفة . يمكنك الاستزادة عن طرييق قراءة المقالات التالية : ما هي هندسة البرمجيات . مراحل تطوير البرامج في هندسة البرمجيات . دورة حياة البرنامج أو المشروع في هندسة البرمجيات .
  20. يبدوا أن لديك خطأ بسياق تعليمة الـ SQL , و لذلك سيجب إعادة صياغتها على نحو أدق و أصح . هلا قمت بتجربة هاته التعليمة بدلا من تلك التي لديك : CREATE TRIGGER `on_comment` BEFORE INSERT ON `article_likers` FOR EACH ROW BEGIN UPDATE `articles` SET `likes` = `likes` + 1 WHERE `id` = new.`article_id` END ( فلا حاجة لتحديد الجدول في aricles.id عند التعليمة WHERE ) يرجى التأكد أيضا من أن لديك جدولا بإسم article_likers
  21. ستحتاج في هذا إنشاء : ملف عرض : لعرض نموذج الإدخال و رفع الصورة و تقديمها إلى الواجهة الخلفية . متحكم : ليحتوي تابعا يتولى مهمة التحقق من المدخلات و فحص ملف الصورة و تخزينه . مسارين : واحد لعرض نموذج رفع الصورة أو الملف و واحد لإستهداف تابع المتحكم الخاص بالرفع . تعريف المسارين بداخل ملف web.php سيكون كالتالي : Route::view('/upload-image' ,'upload-image'); # إعادة ملف عرض Route::post('/upload-image' , 'UploadImageController@store'); # store إستهداف تابع المتحكم ملف العرض upload-image.blade.php سيحتوي بنية HTML مشابهة للتالي : <form action="/upload-image" method="POST" enctype="multipart/form-data" > <!-- يجب تحديد نوع التشفير --> @method('POST') @csrf <div class="form-group"> <label>صورة</label> <input type="file" name="image" required> </div> <button type="submit">رفع الملف</button> </form> المتحكم UploadImageController.php سيحتوي التابع store بالشيفرة التالية : public function store(Request $request) { // التأكد من أن الطلب يمتلك بالفعل ملف if ($request->hasFile('image')) { // التحقق من الملف صورة بلاحقة ملف صورة $request->validate([ 'image' => 'mimes:jpeg,bmp,png' ]); // images في مجلد app/storage/public تخزين الملف محليا في مجلد $request->image->store('images', 'public'); } return back(); } بعد تقديم النموذج و نجاح التحميل سيمكنك الوصول إلى الملفات المخزنة عن طريق التصفح إلى المسار : app/storage/public/images و ستلاحظ وجود ملف الصورة المرفوعة حديثا . هذا لن يكفي لجعل الصورة قابلة للوصول , فلا يزال عليك إنشاء الرابط الرمزي بين المسارين : storage/public/ و : public/storage سيمكن هذا عن طريق تنفيذ الأمر : php artisan storage:link ستلاحظ إنشاء رابط رمزي بين المجلد storage داخل public و public داخل app/storage . و يمكنك الوصول إلى رابط هاته الصور عن طريق التابع hashName في : // images في مجلد app/storage/public تخزين الملف محليا في مجلد $request->image->store('images', 'public'); $filePath = '/storage' .$request->file->hashName();
  22. يمكنك إستخدام الكائن Date في جافاسكربت و توابعه لطباعة التاريخ المرافق بشكل dd-mm-yy . نحتاج أولا تعريف نموذج عن الكائن Date , مع تمرير التاريخ المراد إلى الدالة البانية الخاصية بالكائن : var date = new Date("Tue Aug 31 2021 14:29:37 GMT+0200 (EET)"); ثم لنقم بقراءة اليوم و الشهر و السنة عن طريق التوابع على الترتيب : getDate و getMonth و getFullYear على هذا النحو : var date = new Date("Tue Aug 31 2021 14:29:37 GMT+0200 (EET)"); var year = date.getFullYear(); var month = date.getMonth() + 1 // لأن عد الأشهر في الكائن يبدأ من الصفر var day = date.getDate(); ثم لنقم بتركيب سلسلة نصية تجمع كل منهم : var date = new Date("Tue Aug 31 2021 14:29:37 GMT+0200 (EET)"); var year = date.getFullYear(); var month = date.getMonth() + 1; // لأن عد الأشهر في الكائن يبدأ من الصفر var day = date.getDate(); var formatted = year + "-" + month + "-" + day; و أخيرا طباعة السلسلة الناتجة : var date = new Date("Tue Aug 31 2021 14:29:37 GMT+0200 (EET)"); var year = date.getFullYear(); var month = date.getMonth() + 1; // لأن عد الأشهر في الكائن يبدأ من الصفر var day = date.getDate(); var formatted = year + "-" + month + "-" + day; console.log(formatted); // "2021-8-31" يمكنك الإطلاع على مثال حي من هنا . كما يمكنك التعرف أكثر على الكائن Date في جافاسكربت هنا و هنا .
  23. تحتاج في هذا إستعمال واجهة خلفية و قاعدة بيانات و هذا لأنك تحتاج حفظ بيانات المستخدمين لإستعمالها مستقبلا في عمليات تسجيل الدخول و الخروج . يعني هذا أن الذاكرة المحلية للتخزين في الجافاسكربت لن تكفي و ستحتاج إلى واجهة خلفية و قاعدة بيانات , و لن يكفي إستعمال الجافاسكربت وحدها لتحقيق ذلك . إن كانت برمجة الواجهة الخلفية مألوفة لديك , فيمكنك تحديد لغة أو إطار عمل الواجهة الخلفية و نظام إدارة قواعد البيانات و سيحاول مدربوا الأكاديمية تبسيط العملية لك . أما إن لم يكن إستعمالها مألوفا لديك و كان جديدا عليك فأنصحك أولا بتعلم برمجة الواجهة الخلفية و التعامل مع قواعد البيانات و من ثم نمذجة نظم مثل الذي تريده بشكل برمجي . و عموما , سيكون منطق العملية كالتالي : يتم إرسال بيانات العضو المراد تسجيله إلى الواجهة الخلفية للتطبيق عن طريق نموذج form . تقوم الواجهة الخلفية بإستقبال البيانات , معالجتها و فحصها . تقوم الواجهة الخلفية بكتابة إستعلام قواعد بيانات ﻹدراج بيانات العضو في قواعد البيانات . يتم تسجيل العضو و حفظ بياناته كعضو غير مؤكد التسجيل . يتم في نفس الوقت عن طريق الواجهة الخلفية توليد سلسلة نصية أو token يتم حفظه في قواعد البيانات و أيضا إرساله إلى البريد الإلكتروني للمستخدم أو بشكل رسالة نصية SMS . يتم لاحقا التقاط و إستقبال الكود أو السلسلة النصية التي يقوم المستخدم بإدخالها محاولا تأكيد حسابه , ثم مطابقتها مع المخزنة في قواعد البيانات . و إن تم التطابق يتم تأكيد حساب المستخدم و يتم تسجيله كعضو مؤكد التسجيل . و قد تختلف بعض التفاصيل بشأن كل خطوة بين لغة برمجية و أخرى .
  24. بجانب ما قام المدربان شرف و أبو عواد بشرحه , فإنه يتم الإعتماد عليها في الإستعلامات أيضا لأن استخدام المفاتيح الرئيسية شائع أيضا كطريقة لتقييد أو ربط البيانات ذات الصلة ببعضها في قاعدة بيانات . و هذا يضمن أن تظل البيانات متسقة وأن قاعدة البيانات لا تحتوي على أية بيانات زائدة عن الحاجة . على سبيل المثال ، إذا قمت بحذف جدول (أو حتى صف في جدول) تعتمد عليه الجداول الأخرى ، فستتم إزالة البيانات المكررة . و يساعد هذا في منع مشاكل تكامل البيانات التي يمكن أن تسبب مشاكل مع التطبيقات التي تستخدم مثل هذه البيانات . و يعني هذا أنه بجانب أن المفاتيح الرئيسية سهلة في الإستعلام و فريدة و غير مكررة هي ضرورية جدا أيضا إذا كان الجدول مؤهلاً كجدول علائقي , أي أن يكون جدول يرتبط بغيره من الجداول بعلاقة ما . أي أنه له دورا علائقيا أيضا . كما أن هناك مشكلة أخرى تتعلق باستخدام السلاسل النصية مثلا كمفتاح أساسي وهي : نظرًا لأنه يتم وضع الفهرس في ترتيب تسلسلي باستمرار ، فإنه عند إنشاء مفتاح جديد يكون في منتصف الترتيب ، يتطلب علينا إعادة ترتيب الفهرس ... لكن إستخدامنا لمفتاح رئيسي يكون تلقائيا كعدد صحيح مرتب يجعلنا نضيف المفتاح الجديد فقط إلى نهاية الفهرس دون أي تداخل . أي أنه له بجانب دوره التبسيطي , و العلائقي دورا ترتيبيا و منطقيا أيضا . و لنأخذ على سبيل المثال , تطبيقات السجلات . فمن غير المنطقي طبعا أن يتغير ترتيب السجل كل مرة يتم فيها إدخال حقل جديد . فكل هذا يؤول إستخدام المفاتيح الرئيسية في أغلب الإستعلامات . و طبعا كل هذا لا يعني هذا الإستغناء عن باقي الأعمدة و الإكتفاء بالإستعلام عن البيانات بمفتاح رئيسي , فقد نحتاج في كثير من الحالات الإستعلام عن البيانات عن طريق أعمدة أخرى من مثل الإستعلامات التي يتم كتابتها في عمليات البحث و الفهرسة .
  25. يبدوا أن مشكلة تثبيت webpack قد تم تجاوزها . يظهر من الخطأ أنه هنالك مشكلة بتثبيت حزمة popper.js و popperjs core أيضا . و ليكن في العلم أن حزمة popper.js هي حزمة يستعملها Bootstrap 4 لإظهار النوافذ المنبثقة و بعض التأثيرات و التفاعليات في بوتستراب. يطلق على popper.js و مثلها من الحزم لفظ peer dependecies , و يقصد بها أي حزمة B تتطلبه حزمة معينة A ما ولكنها لا تشمله مع نفسه عند تثبيته . و بسبب عدم تثبيتها أو تثبيتها على نحو خاطئ , نواجه مثل هاته الأخطاء التي تخبرنا أن واحدة من الحزم تتطلب حزمة أخرى . و لذلك سنحتاج أيضا تثبيت popper.js بشكل مستقل , لنقم بتنفيذ الأمر : npm install popper.js --save أما ان كنت تستعملين نسخ x.5 من بوتستراب فسيتطلب عليك تثبيت popperjs core عوضا عن popper.js , لنتأكد عندها من تثبيت الحزمة عن طريق الأمر : npm install @popperjs/core --save ثم سيكون عليك أخيرا تشغيل أمر البناء مجددا : npm run build إن استمرت مشكلتك بالظهور يرجى إخباري بشأن أيضا أخطاء تظهر .
×
×
  • أضف...