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

Adnane Kadri

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

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

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

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

    52

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

  1. و عليكم السلام , هلا قمت بالتفصيل أكثر فيما تقصده بـ "تصغير رابط المواضيع بالموقع بإستخدام ملف htaccess. " ؟ كما أن مشكلتك غير واضحة جيدا , يرجى التفصيل أكثر
  2. لنقم بإقتباس التعريفين التالين من ويكي حسوب كالتالي : و لنفترض أن حجم حاوية ما لدينا هو 1000 بكسل . هاته الحاوية تحوي 4 عناصر . قمنا بتحديد flex-basis أو أساس مرن لكل عنصر بـ 200 بكسل . سيجعل هذا العناصر تظهر كالتالي : كل من العناصر الأربع سيمتلك عرضا 200 بكسل .بالإضافة إلى مساحة إضافية متبقية 200 بكسل بعد توزيع العناصر . إذا قمنا الان بإعطاء العنصر الثاني flex-grow أو نمو مرن بمقدار 2 (أي تعويضا لعنصرين flex) ، فسيشغل هذا العنصر الثاني ضعف المساحة المتبقية عن العناصر الأخرى و سيأخذ 200 بكسل إضافية , و سيظهر و كأنه يتمدد على باقي العناصر . لاحظ نمذجة للعملية : و بالتالي ،فإنه من أجل استخدام flex-grow لعنصر ما ، يجب أولاً تعيين flex-basis لينطلق منه الـ flex-grow فيعتبره مرجعا و معيارا يحدد معدل التمدد من عليه , فإن حددنا أساسا بـ 100 بكسل و أعطينا قيمة نمو بـ 3 , فسيكون عنصر الـ flex هذا معوضا لـ 3 من قيمة الأساس أي 300 بكسل . و لتتذكر الأمر على هذا النحو : flex-basis : ترجمة لـ أساس مرن . flex-grow : ترجمة لـ نمو مرن . و لتحديد هذا النمو المرن لن نحتاج إلا لمعرفة ما هو المقدار الذي سينمو به عنصر عن باقي العناصر الأخرى , و عليه فإن : flex-grow تتطلب flex-basis . يمكنك الإطلاع على توثيق كل من الخاصيتين في ويكي حسوب كالتالي : flex-basis . flex-grow .
  3. و عليكم السلام . قبل التعرض للقيم التي تأخذها الخاصية ينبغي أولا معرفة ما الذي تقوم به الخاصية , فالخاصية tranfrom-style أو نمط التحويل تحدد ما إذا كانت العناصر الفرعية أو الأبناء لعنصر ما موضوعة في مساحة ثلاثية الأبعاد أو إذا تم وضعها في مستوى العنصر الأب نفسه . أي أن الخاصية ممكن لها أن تأخذ أحد القيمتين : flat : يعني هذا أن العناصر الأبناء لعنصر ما يمتلك هاته الخاصية سيتم وضعها في نفس مستوى العنصر . preserve-3d : ترجمة للـحفاظ على البعد الثلاثي , و تجعل هاته القيمة الأبناء موضوعة في مساحة ثلاثية الأبعاد خاصة بها . و لإتضاح الفرق جيدا لاحظ الفرق بين الصورتين : الصورة رقم 1 : الصورة رقم 2 : لاحظ في كلتا الصورة أن العنصر الأب parent باللون البرتقالي يمتلك تحويلا معينا يعطيه الإنحناءة ثلاثية الأبعاد التي هو عليها , و مثل ما هو الحال مع محاور ذات العنصر , أي أن المحاور أيضا أعيد تعيينها بعد تطبيق التحويل الذي عليه . في الصورة الأولى : نلاحظ إنتماء العنصر الابن باللون الزهري إلى مستوى عنصر الأب , أي أن العنصر يظهر بشكل وكأنه مواز له , و لكنه في الحقيقة على ذات المستوى , كأن الأمر يجرد هكذا : في الصورة الثانية : نلاحظ تداخل العنصر الاابن باللون الزهري مع العنصر الأب , يظهر ذلك و كأن كل منهما مرسوم ومعبر عنه في مستوى خاص به , هذا المستوى هو مساحة ثلاثية الأبعاد خاصة به . و كأن الأمر هكذا : ففي الأولى : العناصر الأبناء للعنصر الحالي ستكون مسطحةً (flattened) في مستوى العنصر الأب . أي أن العنصر الأب يمتلك القيمة flat في خاصية نمط العنصر . و في الثانية : العناصر الأبناء للعنصر الحالي ستكون موجودةً في الفضاء ثلاثي الأبعاد الخاص بها . أي أن العنصر الأب يمتلك القيمة preserve-3d في خاصية نمط التحويل . و هو ما سؤالك حوله بالضبط . يمكن تلخيص قواعد الـ css لكل من المثالين كالتالي : صورة 1 : transform-style: flat; صورة 2 : transform-style: preserve-3d; تعرف أكثر على الخاصية transform-style من هنا . كما يمكنك الإطلاع على المثال الذي تم طرحه و التلاعب بقيم الخاصية من هنا .
  4. يمكنك تشغيل الأمر التالي مباشرة : /opt/lampp/lampp start أو عن طريق sudo كالتالي : sudo /opt/lampp/lampp start ستلاحظ مجموعة تعليمات تخبرك بتمام تشغيله كالتالي : Starting XAMPP for Linux 1.5.3a... XAMPP: Starting Apache with SSL (and PHP5)... XAMPP: Starting MySQL... XAMPP: Starting ProFTPD... XAMPP for Linux started. ثم سيمكنك التصفح إلى : http://localhost بشكل عادي أو : https://localhost في حالة تشغيل دعم ssl أيضا . و لإيقافه لن تحتاج إلا لتشغيل نفس الأمر مرفقا بالتعليمة stop بدل start : sudo /opt/lampp/lampp stop بعض الأوامر الأخرى التي قد تحتاج لها في نفس الإطار : sudo /opt/lampp/lampp restart # إعادة التشغيل sudo /opt/lampp/lampp startapache # تشغيل خادم أباتشي فقط sudo /opt/lampp/lampp stopapache # إيقاف تشغيل خادم أباتشي فقط sudo /opt/lampp/lampp startssl # تشغيل دعم أس أس ال من قبل خادم اباتشي sudo /opt/lampp/lampp stopssl # إيقاف تشغيل دعم أس أس ال من قبل خادم اباتشي sudo /opt/lampp/lampp startmysql # تشغيل قواعد بيانات مايسكول sudo /opt/lampp/lampp stopmysql #إيقاف تشغيل قواعد بيانات مايسكول sudo /opt/lampp/lampp startftp # ProFTP تشغيل خدمة sudo /opt/lampp/lampp stopftp # ProFTPإيقاف تشغيل خدمة sudo /opt/lampp/lampp security # عمل اختبار تحقق سريع
  5. و عليكم السلام و رحمة الله لا أظن أن يجب عليك تعلم إحداها فقط دون الأخرى , بل كلاهما . و هذا لأن لكل منها مجاله التخصصي و إستعمالاته و حاجته التي دعت إلى إنشاءه من الأساس , فالمقارنة بينهما غير منطقية . و لنأخذ كل منهما على حدة كالتالي : يستخدم Ajax بروتوكول HTTP ويمكنه إرسال طلبات باستخدام طرق POST و GET بين العميل والخادم. WebSocket هو بروتوكول اتصال بين العميل والخادم ، وهو يختلف عن HTTP . ففي Ajax ، عندما ترسل طلبًا ، يرسل الخادم استجابة لهذا الطلب ويتم إنهاء الاتصال , و هذا ما يجعله مناسبا لإستعمالات من مثل : التواصل مع واجهات تطبيق برمجية . أي أنه يسمح لتطبيق ما ,من جانب العميل, بطلب الوصول إلى مورد من جانب الخادم (مثلا : طلب صفحة أو صورة أو ملف أو بيانات) . في حين أن باستخدام WebSockets عند إنشاء اتصال بالخادم ، يمكنك التواصل بقدر ما تريد بين العميل والخادم والحفاظ على الاتصال نشطًا في كل لحظة , و هذا يجعله مناسبا للإستعمالات من مثل : تلقي إشعارات الوقت الفعلي أو الدردشة الحية , مثل الإشعار الذي تلقيته بشأن إجابة عن سؤالك هذا . يمكن تلخيص الأمر بشكل بسيط كالتالي : ما وراء الـ AJAX يعتمد إتصالا يتم إغلاقه مباشرة بعد الرد . ما وراء الـ WebSocket يعتمد إتصالا متواصلا . أمثلة توضيحية : يحتاج العميل " أحمد " تفحص صورة من على الخادم , فيقوم بإرسال طلب GET إلى الخادم . يستقبل الخادم الطلب و يقوم بإعادة رد برابط الصورة ليقوم أحمد برؤيتها , و ينتهي الإتصال و يتوقف الخادم عن تبادل أية بيانات بينه و بين أحمد , و سيحتاج أحمد اتصالا جديدا كل مرة يريد فيها طلب شيء من على الخادم . الان , العميل " أحمد " على موقع دردشة , ينتظر أي رسائل تصله . في مقابل أن العميل " عماد " يريد مراسلة " أحمد " . يقوم أحمد بإنشاء إتصال عن طريق بروتوكول ويب سوكيت بينه و بين الخادم , و ما إن وصلت أي رسائل جديدة لأحمد للخادم سيتم تنبيهه فورا . بعد أن يكتب عماد الرسالة و يرسلها , سيلتقط الخادم طلبه و يخزن الرسالة و يقوم فورا بتنبيه أحمد بذلك , فيكتب ردا و هكذا . أي أن من غير المعقول أن يشغل دور أحد الثاني , فلكل منهما منطقه الذي يتعامل به , فكل إستعمال لأحدهما في مجاله ميزة , و أي إستعمال له في غير تخصصه و مجاله عيب و هكذا . أما كاقتراح و تفضيل , فأفضل أن تتعلم Ajax أولا , كونه ما ستحتاج إليه طوال مسارك . ثم في وقت لاحق , قد تدعوك الحاجة إلى تعلم websocket لتحقيق أغراض أو حالات إستعمال معينة . و هو في الغالب ما كان مسار أي مطور . يمكنك تصفح إجابات مختلفة لتعاريف حول ما هو الـ websocket و لما قد نحتاجه هنا . كما قد تحتاج الإطلاع على كيفية التعامل مع ajax في الـ jQuery هنا .
  6. لاحظ أنه لا يوجد لديك فواصل منقوطة في نهايات العديد من الأسطر : السطرين برقم 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'); و ذلك حتى يتم تحديده بشكل صحيح .
  7. أفضل إستعمال مكتبة الجيكيوري 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 , و سيتم ذلك على الفور .
  8. تكاد تكون أغلب هاته الوظائف ذات أسماء دلالية تدل على وظيفتها , مثلها مثل ملف init.js . فالدالة أو الوظيفة الأولى Ready ترجمة لجاهز : تعبر عن الإستدعاء بعد جهوزية الصفحة , و تحمل مجموع الشيفرات التي يتم إستدعاءها عند الحدث ready , و يتم هذا الحدث في اللحظة التي تكون قد حملت فيها الوثيقة . و الدالة أو الوظيفة الثانية تحمل مجموع الشيفرات التي يتم إستدعاءها عند الحدث load بالنسبة للنافذة , و يخص هذا الحدث تلك اللحظة التي تكون قد حُمّلت فيها كامل الموارد الخارجيّة مثل : روابط ملفات خارجية cdn أو صور . وبذلك تكون التنسيقات قد طُبّقت، ومقاسات الصور عُلمت، وما إلى ذلك . أما الوظيفة المعلقة بإسم Full Height function فتقوم هاته الدالة في الغالب بضبط مقاسات إرتفاع الحاويات و العناصر حتى تأخذ كامل الإرتفاع , مثل عنصر القائمة الجانبية. الوظيفة droopy , قد لا يدل إسمها عليها في الغالب. يلحظ أنها تحوي مجموع الشيفرات التي يتم فيها إضافة الأحداث إلى عناصر , و بعض الأسطر الأخرى التي يتم فيها تهيئة إضافات جيكويري مثل : Tooltip Popover Accordion js Slimscroll الوظيفة chat app تقوم في الغالب بضبط بعض الإعدادت الخاصة بمربع الدردشة , كما أنها تقوم بإضافة بعض الأحداث المتعلقة بذات العنصر . الوظيفة resize تشمل مجموع الشيفرات التي يتم إستدعاءها عند محاولة إعادة ضبط حجم الشاشة . من الصعب جدا تحديد ما يقوم به كل سطر من الشيفرة دون التوغل فيها بشكل كبير جدا , كما أن الملف كغيره من ملفات الجافاسكربت التي تحمل مجموع شيفرات معينة , و بالتالي فإن الوظائف التي يحويها الملف ليست أكثر من وظائف جافاسكربت عادية . فحاجة مبرمج الموقع إلى تنظيم عمله و تهيئة الموقع بشكل أنظف و أكثر تنظيما دعته إلى إنشاء كل الوظائف , التي من شأنها تهيئة : عنصر , مكتبة أو حدث , في ملف منفصل .
  9. هو بداية ليس أكثر من ملف جافاسكربت عادي , و في الغالب الملفات بالإختصار الدلالي 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 فهو مجرد ملف كغيره من ملفات الجافاسكربت , يحمل شيفرات جافاسكربت عادية . الشيء الوحيد الذي يجعل اسمه دالا عليه هو أن هاته الشيفرات تستعمل بغرض التهيئة و التحضير .
  10. المستخدم الذي قام بالتلاعب بقيمة المتغير المؤثرة في شروط عرض مكونات معينة لن يكون تعديل شيفرة المراقبة و إعادة التحميل مشكلة بالنسبة له . كما أن هاته الحالات خاصة جدا , فعوام المستخدمين لا يفكرون بنفس الطريقة . و حتى إن كان و تم الوصول لذلك بأية طريقة كانت , لن يكون من عرض قالب فارغ جدوى من الأساس . أي أن الأهم من كل ذلك : مصادقة طلبات جلب البيانات قبل عرضها , و يكون كل هذا في الواجهة الخلفية بعيدا عن المستخدم . كما أن هذا لا يمنعك من ضبط طريقة التصفح و منع عوام المستخدمين من الوصول إلى صفحات ليست لهم صلاحية الوصول إلى البيانات التي تعرض بهاته المكونات , و يكون ذلك بالتوجيه إلى صفحات عامة أو قابلة للوصول من أي كان في حالة إرسال طلب من مكون خاص لا يمكن لمستخدم عام تصفحه .
  11. المشكلة الوحيدة لديك هي أن قاعدة البيانات التي تحاول القراءة من عليها فارغة , فمن المنطقي أن لا يتم الإنطلاق في الدور 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 .
  12. هلا تأكدت من أن مزود الاستضافة الخاص بك يسمح لك بإرسال رسائل البريد الإلكتروني ولا يحد من إرسال رسائل البريد الإلكتروني ؟ و ذلك لأن العديد من مضيفات الويب المشتركة ، وخاصة موفري الاستضافة المجانية ، إما لا تسمح بإرسال رسائل البريد الإلكتروني من خوادمها أو تحد من العدد الذي يمكن إرساله خلال أي فترة زمنية معينة . و قد تحتاج إلى التواصل مع فريق دعمهم للتحقق مما إذا كانت هناك أي قيود مفروضة على إرسال رسائل البريد الإلكتروني أو لا . في مثل هاته الحالات يلحظ سلوك مشابه لدالة 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 .
  13. في الحقيقة فكرة حماية عرض مكون في تطيبقات الصفحة الواحدة أو تطبيقات الويب التقدمية فكرة تعاب فيها هاته التطبيقات , إذ أن اقصى حماية لأي مكون أو أية صفحة عرض هي عن طريق طبقات وسيطة تستعمل قيما و شروطا مهما تم التلاعب فيها وتطبيق الأفكار عليها ستبقى مخزنة أو متحقق منها محليا و على المتصفح . ولكنه يجب الإنتباه إلى أن عرض مكون دون بيانات ليس له معنى فسيكون مجرد قالب , و لذلك التركيز الحقيقي لا يكون على حماية صفحات العرض و المكونات و إنما على البيانات التي تستجلب من الواجهة الخلفية . كما أن التوجه إلى تطبيقات الـ ssr أو الـ server side rendering سيقوم بتجاوز هذا الإشكال و حله بشكل نهائي , و كونك تستخدم vueJS فسيكون إستعمال NuxtJs موافقا و سهلا .
  14. يجب أولا فهم الغرض من القنوات الخاصة أساسا , فالقنوات الخاصة في الويب سوكيت وجدت للتحقق ما ان كان سيسمح للمستخدمين بالاستماع إلى هاته القنوات الخاصة أو لا , و ذلك بالإعتماد على شروط تتوفر فيمن يقوم بطلب الإستماع مثلا أو أية شروط أخرى . يتم تحديد قواعد ترخيص القناة الخاصة هاته بنا في ملف : 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() }}', } } }); بعد ذلك ستعمل القنوات الخاصة وفق المطلوب .
  15. القناة بالإسم : 'new-notification.'.$this->post_user_id بالفعل قناة خاصة Private Channel لديك , هلا قمت بتوضيح سؤالك أكثر ؟ يمكنك الإستغناء عن laravel ehco إن كنت تستخدم pusher كويب سوكيت دريفر , و لا علاقة لذلك بنوع القناة .
  16. بإنهائك لدورة تطوير واجهات المستخدم ستصبح مطور واجهات مستخدم , و هذا لأنك ستتعرف على كل من : مفهوم الواجهة الأماميّة للموقع front-end وكيفية عملها . أساسيات لغات تطوير واجهات المستخدم: HTML و CSS و JavaScript . استخدام أحدث أدوات التطوير: Bootstrap 4 و jQuery و Sass . التعامل مع خدمة استضافة المشاريع البرمجية GitHub و GitLab . نشر صفحات الموقع على الإنترنت . إعداد هيكل الموقع ووضع خطة العمل . التصميم المتجاوب مع مختلف الأجهزة والشاشات . و مطور واجهة المستخدم هو المسمى الوظيفي لمن يكون مسؤولا عن بناء الموقع من الجانب الشكلي العام من هيكلية و تصميم و تفاعلية . يشمل هذا المسمى الوظيفي الفروع التالية : البرمجة بإستخدام الجافاسكربت و أدواتها , و تصميم الويب بإستخدام الـ css و أدواتها . أي أن التعبير مطور واجهات مستخدم وفق المقدم في دورة واجهات المستخدم يتضمن صفتي " مبرمج " و " مصمم " معا . و للتفصيل أكثر يمكن تعريف كل منهم وفق التعريفات التالية : مصمم الويب : يهتم بالتصميم الخارجي للموقع . مبرمج الويب : الشخص المفوض إليه عمليات التكويد و كتابة الشيفرة , له إمكانية كتابة أكواد و خوارزميات أكثر تعقيدا , لا يعير إهتمام لشخص المستخدم أو تجربته . مطور الويب : إهتمامه أكثر بتجربة المستخدم نحو التطبيق المفوض إليه , معرفته بالمستخدم أكثر و بالتكويد و التعقيد أقل عادة .
  17. مثلما ذكر المدرب حسن حيدر فإن الخاصية ليست قياسية أو على المسار القياسي الذي تحترمه كامل متصفحات الويب كما أنها تابعة لمجموعة الإضافات ذات السابقة 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
  18. يمكنك إستخدام ما يعرف بالتعليقات الشرطية لحجب المحتوى أو عرض رسالة معينة بناءا على متصفح المستخدم في أي صفحة أو مكون , و كونك تستخدم تطبيق 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>
  19. قبل التحدث عن وسم 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 : هنا .
  20. قد يكون سؤالك متشعب كثيرا كونك لم تحدد ما تقصده بالضبط بـ "التعديل على الكود و بناء المواقع " , فعملية بناء المواقع عملية متسلسة و تتفرع إلى كثير من التخصصات و يستعمل فيها الكثير من اللغات . فالمواقع و تطبيقات الويب بصفحة عامة تنقسم إلى قسمين : واجهات خلفية Backend : تمثل كل العمليات و المنطق الحاصل على مستوى الخادم , يتم في هاته المرحلة عادة بناء واجهات تطبيق برمجية لتسهيل ربطها مع الواجهة أو الواجهات الأمامية . واجهات أمامية Frontend : تمثل مجموع التصاميم و التفاعليات و بنى العناصر , يتم في مرحلة بناء الواجهات الأمامية بناء شاشات و قوالب قد تكون تفاعلية و قد تكون صماء . و كون أغلب العمليات تبتدئ من الخادم فسيكون المسؤول الأول عن عرض الصفحة لديك بشكل أو بتنسيق أو تفاعلية معينة , و لذلك نجد صفحات بلواحق php. تحمل شيفرات واجهات أمامية من مثل HTML أو جافاسكربت أو CSS . و لذلك فإن التعديل على هاته الصفحات يكون موجها و مقيدا بالهدف من التعديل : فإن كان الهدف التعديل على الواجهات الأمامية , مثل القوالب , فسيمكن مباشرة التعديل على بنية الـ HTML أو الملفات أو الأسطر المسؤولة عن تنسيق العناصر أو عن تفاعليتها , دون المساس بأي منطق داخل محددي الـ PHP : <?php // PHP هنا شيفرة ?> <div class="container-fluid"> .. </div> <?php // PHP هنا شيفرة ?> أما ان كان الهدف تغيير طريقة تعامل الخادم مع الطلبات و كل عمليات الخادم فسيتطلب التعديل على ما داخل المحددين , و إن لزم خارجهما . فاﻷول هو ما يقوم به مطورو الواجهة الأمامية , و الثاني هو ما يقوم به مطورو الواجهة الخلفية . نعم يمكن و هو المفترض أن يكون , فلا دخل لما يحدث على الواجهة الخلفية في الواجهة الأمامية . و قد لا تتطلب الكثير من التطبيقات و المواقع واجهة خلفية أصلا , مثل قوالب الـ HTML أو صفحات العرض أو أي من المواقع ثابتة المحتوى . و لذلك فإن إستعمال HTML , JS , CSS كاف جدا بهذا الخصوص . التعديل على واجهات المستخدم لا يلزم في الغالب أي معرفة مسبقة بخصوص الواجهات الخلفية في التطبيقات و المواقع المبنية بتنظيم , و لكن كون الواجهة الخلفية هي المحرك الأول فسيكفي - في الغالب - امتلاك معرفة سطحية لسهولة التصفح و التنقل بين الملفات و فهم الشيفرة , قبل على التعديل على ما يخص الواجهة الأمامية منها .
  21. الكود النظيف بشكل عام هو أمر شخصي و ذاتي و لكل مطور وجهة نظر شخصية بخصوصه . ولكن هناك بعض الأفكار التي يتفق عليها الأغلب و يعتبرونها أفضل الممارسات لما يشكل شيفرة نظيفة , مفهومة , قابلة للقراءة و التعديل على نطاق واسع . أي باختصار : و لنأخذ المفهوم بشكل أعمق كالتالي : سهولة الفهم تعني سهولة قراءة الكود ، سواء كان ذلك القارئ هو المؤلف الأصلي للكود أو أي شخص آخر . لذا فهو يقلل من الحاجة إلى التخمين وإمكانية حدوث سوء فهم . من السهل أن نفهمه على كل المستويات ، وعلى وجه التحديد : منطق العمل للتطبيق بأكمله . كيفية تعاون الكائنات و الأصناف المختلفة مع بعضها البعض . دور ومسؤولية كل فئة و كائن . ما تفعله كل دالة و تابع . الغرض من كل تعبير يتم تعريفه , سواء متغير , ثابت أو خاصية . أما سهولة التعديل تعني أن الشيفرة سهلة التوسيع , التطوير وإعادة البناء . كما أنه من السهل إصلاح و تشخيص الأخطاء فيها , و نفس الأمر ينطبق أيضا : سواء كان ذلك القارئ هو المؤلف الأصلي للكود أو أي شخص آخر . و يشمل ذلك النقاط : الكائنات و التوابع صغيرة الحجم ولا تتحمل سوى مسؤولية واحدة (و ذلك احتراما لمبدأ فصل المهام ) . تتوفر الكائنات على واجهات برمجية عامة واضحة و موجزة . يمكن التنبؤ بكبفية عمل الكائنات و توابعها . الكود قابل للاختبار بسهولة ولديه اختبارات وحدة (أو على الأقل من السهل كتابة الاختبارات) . الاختبارات - إن توفرت- فهي سهلة الفهم والتغيير بسهولة . و لكن لما نحتاج الإهتمام أصلا بالكود النظيف ؟ لنقم بتلخيص أهمية الأمر في النقاط التالية : يجب أن تهتم لأن الشفرة (في الغالب ) لا تتم كتابتها مرة واحدة و فقط . و إنما في معظم الأوقات ، تحتاج أنت أو أي شخص آخر إلى العمل على الكود. ولكي تكون قادرًا على العمل عليه بكفاءة ، فأنت بحاجة إلى فهمه بالدرجة الأولى . مبادئ كتابة كود نظيف تمنحك الثقة أثناء كتابة شيفرتك . تكون الأخطاء أسهل للتشخيص و الحل . تجعل الكود سهل للصيانة و التطوير . و قد يتعلق مفهوم الكود النظيف بكثير من المفاهيم الأخرى , من مثل أنماط التصميم و مبادئه و غيرها . و لذلك قد تجد بعضهم يستعير بعض مبادئ تصميم البرمجيات ليستعملها كمبادئ للكود النظيف , من مثل مجموعة مبادئ SOLID (سنأتي لإرفاق سلسلة مقالات تخص كل مبدأ) أو DRY (اختصارا لترجمة لا تكرر نفسك Don't Repeat Yourself ) أو YAGNI (اختصارا لترجمة أنت لن تحتاجها You Aren't Gonna Need It) أو غيرها من المبادئ . و لذلك فهي عملية متشعبة جدا . و لعل الكود النظيف هو ما يصنع الفارق بين مبرمجي نفس اللغة و نفس إطار العمل , فإن كنت لا توليه أهمية أو أولوية فسيجب عليك ذلك . لأنك لن تلتفت إليه بداية كونك بكامل تركيزك وإستيعابك للكود, و لكنك ستجد نفسك في حاجة إليه عندما تبتعد قليلا عن تطوير تطبيقك ثم تقرر العودة إليه . و أتذكر جيدا إضطرار أحد فرق التطوير لنسف الكود بأكمله (الذي كان بحجم 400 ميغا) و إعادته لمجرد أن مطوريه نفسهم عجزوا عن فهمه بعد أقل من سنة من إنطلاقه . يمكنك التعرف أكثر على مبادئ SOLID لتصميم البرمجيات في سلسلة المقالات التالية : S O L I D تعرف أكثر على الشيفرة النظيفة هنا و هنا . كما يمكنك التعرف أكثر على مفهوم الكود النظيف في HTML , CSS و Sass هنا .
  22. لنقم بتناول الأمر بشكل عام على هذا النحو : الـ 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) . و لكن يبقى منطقها و تقسيمها سواءا مهما اختلف كل ذلك .
  23. التعريفات و الأفكار حول هندسة البرمجيات متفاوتة و كثيرة . و قد يصب مجملها و سياقها العام في مفهوم واحد جامع . بحيث يمكن القول على أنها فرع من فروع الهندسة حيث يقوم على مجموعة من الأسس التي تهدف إلى تصميم و تطوير البرامج بجودة عالية تلبي بالدرجة الأولى احتياجات المُستخدمين . يمكن أيضا الاستعانة ببعض المراجع و المصادر العالمية في التعريف بها : و أيضا : مما سبق يمكن فهم أن هندسة البرمجيات ليست كتابة شيفرة أو تكويدا و فقط , فمثل ما شرح المدرب عبد الحميد في تعليق سابق هي جزء من مرحلة التنفيذ . يمكن من هذا إستنتاج أن هندسة البرمجيات عملية إنتاجية لها عدة مراحل أساسية وضرورية للحصول على المُنتج البرمجي النهائي . بحيث يكون الهدف النهائي من أي برنامج هو الحصول على أفضل كفاءة ممكنة بأقل كلفة ممكنة. بحيث يطلق على مجمل هذه المراحل اسم دورة حياة تطوير النظام البرمجي أو بالإنجليزية : Software Development Life Cycle , و اختصارها " SDLC " . و كون فلسفاتها و نماذج بناءها كثيرة و متفاوتة سنأخذ أحد النماذج الكلاسيكية مثالا , هذا النموذج يعرف بنموذج الشلال أو Waterfall Model . لنقل أن هندسة البرمجيات وفق هذا النموذج تتبع بشكل عام المراحل التالية : تحليل المتطلبات Requirement Analysis : في هاته المرحلة يتم تجميع المتطلبات لفهم المشكلة و متطلبات الزبون أو المشروع ، هنا أيضا يتم تقسيم أو توزيع كل موضوع كبير أو معقد إلى اجزاء اصغر من اجل اكتساب فهم أفضل وأسهل للمشكلة والاهداف . التصميم Design : في هاته المرحلة يتم تصميم حلول للمتطلبات التي جمعناها، عملية تحتوي على انشطة معينة مثل صياغة وترتيب، لتحقيق الاهداف , و لا يعنى بالتصميم التصميم بمعناه و إنما تصميم حلول افتراضية أو منمذجة في مخططات لأفضل ما يليق أو ما قد يليق بالمشروع . التنفيذ Implementation : بعد تحديد المتطلبات والأهداف والاتفاق على لغة البرمجة ووضع الخطوط الأساسية للبرنامج وبنيته، يقوم الفريق بتنفيذ “ نموذج أولي Prototype ” للبرنامج . الاختبار Testing : في مرحلة الاختبار، يقوم الفريق باختبار البرنامج والتأكد من أنه يقوم بكافة الوظائف المطلوبة أو يتناسب مع المتطلبات التي تم تحديدها مسبقا . التطوير Evolution : يقوم الفريق بالبحث عن سبل تطوير البرنامج أو تطويره إنطلاقا من MVP (الحد الأدنى للمنتج أو Minimum Viable Product) . يتم اقتراح و إضافة ميزات جديدة له، كما تتم ماقشة إمكانية أو سبل جعله أكثر فاعلية وأكثر كفاءة . المخطط التالي يشرح خطوات النموذج : و بالتالي فإنها عملية منهجية و منظمة للغاية , و في الغالب تتم بالتنسيق بين فرق من مجالات مختلفة . يمكنك الاستزادة عن طرييق قراءة المقالات التالية : ما هي هندسة البرمجيات . مراحل تطوير البرامج في هندسة البرمجيات . دورة حياة البرنامج أو المشروع في هندسة البرمجيات .
  24. يبدوا أن لديك خطأ بسياق تعليمة الـ 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
  25. ستحتاج في هذا إنشاء : ملف عرض : لعرض نموذج الإدخال و رفع الصورة و تقديمها إلى الواجهة الخلفية . متحكم : ليحتوي تابعا يتولى مهمة التحقق من المدخلات و فحص ملف الصورة و تخزينه . مسارين : واحد لعرض نموذج رفع الصورة أو الملف و واحد لإستهداف تابع المتحكم الخاص بالرفع . تعريف المسارين بداخل ملف 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();
×
×
  • أضف...