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

Adnane Kadri

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

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

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

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

    51

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

  1. لا يفترض بتطبيق اللارافيل أن يقوم بالسماح لك بتصفح محتويات المجلد public بمجرد إستعمالك لمسار نسبي كالتالي: http://domain.dm/public حيث يوفر لارافيل نظاما كاملا للتوجيه Routing، أين يقوم التطبيق بإلتقاط المسار الذي تقوم بطلبه وإعادة المطلوب كأن يقوم بإستهداف متحكم controller أو ملف عرض view. سيمكن كل هذا بتعريف هذا المسار في ملف web.php الذي يضم كامل مسارات الويب لموقعك. وفي حالة غياب تعريف كالتالي: Route::get('/public' ,function(){ echo '!يتم إلتقاط مسارك بنجاح'; }); سيتم ببساطة توجيهك إلى صفحة Not found وعرض كود الخطأ 404 ، وهذا في الغالب ما حدث معك. قد تحتاج التعرف أكثر عن لارافيل ، أو التوجيه في لارافيل.
  2. يمكنك الإستعانة بالواجهات البرمجية التي تقوم بتحليل عنوان IP وإستنتاج دولة الزائر المرافقة لهذا الـIP. واحدة من الواجهات السهل التعامل معها هي واجهة ip-api، أين يمكنك إرسال طلبية HTTP من النوع GET مرفقة بعنوان IP الزائر لجلب كامل المعلومات الخاصة بهذا العنوان. يتم إرسال الطلبيات إلى نقطة الوصول التالية: http://ip-api.com/json/{ip-address} مثال عن الردود التي تقدمها الواجهة: { status: "success", country: "Algeria", countryCode: "DZ", region: "25", regionName: "Constantine", city: "Constantine", zip: "25010", lat: 36.368, lon: 6.6172, timezone: "Africa/Algiers", isp: "new", org: "", as: "AS36947 Telecom Algeria", query: "244.244.244.244" } سيمكنك بعد ذلك قراءة أي خاصية من هذا الرد. مثل خاصية country أو countryCode لتوظيفها في خدمة غرضك. خطوات لتوظيف الفكرة في مثالك: لنقل أن الدالة getUsersCountries تقوم بجلب الدول التي يأتي منها زوارك. تقوم هاته الدالة بإستعلام قراءة من قواعد البيانات لقراءة جميع عناوين الـ IP الخاصة بزوارك. تقوم الدالة بإرسال طلبيات GET إلى نقطة الوصول المذكورة سابقا لإستنتاج الدول التي يأتي منها زوارك (يمكنك إستعمال الدالة file_get_contents). يتم تخزين هاته الدول في مصفوفة. يتم فلترة عناصر هاته المصفوفة وجلب العناصر الغير مكررة (يمكنك إستعمال الدالة array_unique). => النتيجة: مصفوفة تحمل كامل بلدان الزوار. تعديل : لتجنب حظرك عن طريق هاته الواجهة، لا يفضل إرسال العديد من الطلبيات مرة واحدة مثل المنطق الذي ستقوم الدالة المرفقة كمثال بإتباعه، عوضا عن ذلك قم بتخزين اسم الدولة مباشرة بدل عنوان IP أو بجانبه في إستعلام INSERT الذي تقوم به في جدول totalview.
  3. لاحظ أنك على مستوى الجافاسكربت لا تقوم بالتفريق أصلا بين محتويات المنتج الأول ومحتويات المنتج الثاني ، فكامل الصور ذات الصنف demo تشير إلى صور المنتج الأول ولا يتم أبدا اعتبار المنتج الثاني. لماذا يحدث هذا؟ لأنك تقوم بعرض المنتج بناء على ترتيبه في شجرة العناصر الحاوية للصنف Slides في الدالة showSlides: var slides = document.getElementsByClassName("Slides"); ولو قمت بتتبع فهرس الشريحة النشطة slideIndex عن طريق طباعته في الـ console فستجد أنه دوما يأخذ القيم 1,2,3 . وبالتالي فإن عناصر الصور الكبيرة التي سيتم تحديدها هي دوما العناصر الثلاث الأولى التي تحمل الصنف Slides . ولن يتم اعتبار ما إن كانت من الصف الأول أو الثاني ، أو إن كانت تخص المنتج الأول أو الثاني. ما الحل؟ أظن أن الحل بتعديلات بسيطة هو في تــمــييــز الصور المصغرة للمنتج الأول عن الصور المصغرة للمنتج الثاني وبالتالي فإن عرض صورة كبيرة عن طريق صورة صغيرة في المنتج الأول لن تتداخل مع الصورة الكبيرة للمنتج الثاني وهكذا. إذا كيف نخبر الجافاسكربت أننا في الصف الأول أو الثاني؟ لعمل ذلك قمت بالتصفح في شجرة الوثيقة والبحث عن الأب component-content لأن الذي يميز المنتج الأول والثاني هو أن كل واحد منهما في حاوٍ مختلف : <!-- ////////////////////// first product --> <div class="component-content"> العناصر التي يتم ضغطها من هذا الحاوي تشير إلى الحاوي الأب هذا </div> <!-- ////////////////////// second product --> <div class="component-content"> العناصر التي يتم ضغطها من هذا الحاوي تشير إلى الحاوي الأب هذا </div> وذلك عن طريق التصفح في شجرة الاباء إنطلاقا من العنصر الذي تم الضغط عليه: function currentSlide(n ,activeImg) { var parentContainer = activeImg.parentNode .parentNode .parentNode .parentNode; /* <div class="component-content"> الأب الرابع <div class="component-container-img"> الأب الثالث <div class="slider-component"> الأب الثاني <div class="Slides"> الأب الأول <img src="./img/1.png" onclick="openModal();currentSlide(1 ,this)" alt="img-1"> */ showSlides(slideIndex = n ,parentContainer); حيث أن عند الضغط على صورة مصغرة : يتم إلتقاط الصورة المضغوطة عن طريق الدالة currentSlide . تخزين الأب الحاوي لها في متغير . لاحظ أيضا أني قمت بتمرير هذا المتغير إلى الدالة showSlides التي ستستعمله في عدم الخلط بين المنتج الأول والثاني: function showSlides(n ,parentContainer) { var i; /* المنتمية للحاوي الذي نقوم بتحديده لها فقط Slides تحديد العناصر ذات الصنف */ /* وكأننا نخبر الجافاسكربت ألا تخلط بين الحاويين */ var slides = parentContainer.getElementsByClassName("Slides"); سيكون هذا كافيا لعمل عرض الشرائح عند التحريك، ولكن ستبقى هنالك خطوة أخرى، هي في تحديد الشريحة النشطة افتراضية، فإستدعاءنا للدالة showSlides هنا غير كافٍ: var slideIndex = 1; showSlides(slideIndex); كونها لا تقوم بتحديد حاو المنتج الذي نقوم بعرض شريحته النشطة، ولذلك لنقم بشكل إفتراضي بعرض : الشريحة الأولى من الحاوي الأول . الشريحة الثانية من الحاوي الثاني . كالتالي: var slideIndex = 1; /*تحديد كامل الحاويات*/ var containers = document.querySelectorAll('.component-content'); /* عرض الشريحة الأولى من الحاو الأول */ showSlides(slideIndex ,containers[0]); /* عرض الشريحة الأولى من الحاو الثاني */ showSlides(slideIndex ,containers[1]); فتكون الشيفرة كاملة: /** * عرض الشريحة الحالية * إزالة الصنف النشط من الصور المصغرة الغير نشطة * */ function currentSlide(n ,activeImg) { // الذي تم من داخله استدعاء الدالة component-content تحديد الأب الرابع : أي العنصر ذي الصنف var parentContainer = activeImg.parentNode.parentNode.parentNode.parentNode; showSlides(slideIndex = n ,parentContainer); // الصور المصغرة الخاصة بهذا الحاوي فقط var imgs = parentContainer.querySelectorAll(".demo"); for(i=0; i < imgs.length ;i++){ imgs[i].classList.remove('active'); } activeImg.classList.add('active'); } var containers = document.querySelectorAll('.component-content'); showSlides(slideIndex ,containers[0]); showSlides(slideIndex ,containers[1]); function showSlides(n ,parentContainer) { var i; // نحتاج تحديد الصور الكبيرة الخاصة بهذا المنتج فقط var slides = parentContainer.getElementsByClassName("Slides"); ... إلى اخر الشيفرة سيكون هذا كفيلا بحل المشكلتين معا لديك، تأكد فقط من تعميم هذا التعديل بإضافة this على كامل العناصر المشابهة: <div class="Slides"> <img src="./img/1.png" onclick="openModal();currentSlide(1 ,this)" alt="img-1"> </div>
  4. هل تقصد أن لديك صفين من المنتجات؟ الصف الأول الحاوي للمنتج الأول وثلاث صور مصغرة يتم التحكم عن طريقها في الصورة المعروضة من الصف الأول ، ثم الصف الثاني الحاوي للمنتج الثاني وثلاث صور مصغرة أخى يتم التحكم عن طريقها في الصورة المعروضة من الصف الثاني ؟
  5. لحل هذا المشكل قمت بدل البحث عن الصورة التي تم الضغط عليها عن طريق الشريحة النشطة بتمرير كائن الصورة التي تم الضغط عليها في الدالة currentSlide كمعامل ثانٍ: <div class="Slides"> <img src="./img/1.png" onclick="openModal();currentSlide(1 ,this)" alt="img-1"> </div> حيث يشير this إلى الصورة التي هي العنصر نفسه (يجب تعميم هذا في كامل العناصر). ستقوم الدالة currentSlide بإلتقاط هاته الصورة، ثم حذف الصنف active عن كامل الصور وتطبيقها على هذا العنصر: function currentSlide(n ,activeImg) { showSlides(slideIndex = n); var imgs = document.getElementsByClassName("demo"); for(i=0; i < imgs.length ;i++){ imgs[i].classList.remove('active'); } activeImg.classList.add('active'); } سيمكن بهذا التخلص من هاته الأسطر: function showSlides(n) { var i; var slides = document.getElementsByClassName("Slides"); //var dots = document.getElementsByClassName("demo"); هذا if (n > slides.length) {slideIndex = 1} if (n < 1) { slideIndex = slides.length } for (i = 0; i < slides.length; i++) { slides[i].style.display = "none"; } /* for (i = 0; i < dots.length; i++) { dots[i].className = dots[i].className.replace(" active", ""); } هذا */ slides[slideIndex-1].style.display = "block"; // dots[slideIndex-1].className += " active"; هذا } سيجعلك هذا تتجاوز المشكلة الثانية وستحتاج فقط إعطاء الصنف active للصورة النشطة يدويا كإعداد إفتراضي. لم أستطع إلتماس هاته المشكلة، هل يمكنك توضيحها أكثر؟
  6. يتم كل ذلك عن طريق قراءة محركات البحث لمخططات البيانات أو البيانات المُهَيكَلة الخاصة بصفحة ما، تعرف هاته المخططات بـStructured Data . تستخدم العديد من التطبيقات من Google و Microsoft و Pinterest وغيرها هاته البيانات لتوفير تجربة مستخدم أفضل. حسب تعريف Google فإن: تستخدم Google البيانات المنظمة التي تجدها على صفحة الويب الخاصة بك، وتقوم بتضمينها في نتائج البحث، حيث يكون ذلك تلقائيا بمجرد هيكلتك للبيانات. ولكن كيف يتم هيكلة البيانات؟ واحدة من الصيغ التي يتم بها كتابة هاته الهياكل هي الصيغة JSON-LD (اختصارا لـ Json For Linked Data أو جيسون للبيانات المربوطة)، تكون كالتالي: { "@context": "https://schema.org/", "@type": "Recipe", "name": "وصفة كعكة قهوة", "author": { "@type": "Person", "name": "اسم شخص ما" }, "datePublished": "2018-03-10", "description": "هاته الكعكة رائعة،يعبر هذا عن وصف سيظهر في قسم الوصف لأي محرك يقوم بقراءة هاته الهيكلة", "prepTime": "PT20M" } يتم تعريف هاته الخواص في قسم head من الصفحة بين وسمي فتح وإغلاق script: <html> <head> <title>وصفة كعكة قهوة</title> <script type="application/ld+json"> { "@context": "https://schema.org/", "@type": "Recipe", "name": "وصفة كعكة قهوة", "author": { "@type": "Person", "name": "اسم شخص ما" }, "datePublished": "2018-03-10", "description": "هاته الكعكة رائعة،يعبر هذا عن وصف سيظهر في قسم الوصف لأي محرك يقوم بقراءة هاته الهيكلة", "prepTime": "PT20M" } </script> </head> يمكنك التعرف على كامل الخواص في الموقع الرسمي لـ Schema.org. أين يمكنك هيكلة بيانات صفحتك وفق الخواص المتوفرة، يتوفر من بينها خاصية النجوم أو غلاف فيديو للصفحة أو غيرها. يمكن هيكلة البيانات أيضا وفق صيغ microdata مثل الصيغة التي تتبعها أكاديمية حسوب أو صيغ RDFa. وبما أن Google تقوم بإستخدام هاته البيانات المهيكلة في تحسين عملية الفهرسة والبحث، فإنها تقوم بعرضها وفق أنساق معينة. تعرف أكثر عن البيانات الوصفية (microdata) في HTML5 (تتفرع عن هاته المقالة سلسلة مقالات تخص نفس الموضوع من مثل كيف توصيف وهيكلة الأشخاص والمنظمات عن طريق microdata، توصيف وهيكلة الأحداث والمراجعات ..الخ).
  7. يمكنك تحديد النص المظلل عن طريق الجافاسكربت بإستعمال التابع getSelection للكائن العام window كالتالي : window.getSelection() مثال عملي : لتكن هيكلية الـ HTML التالية : <p> هذا النتص هو مجرد لملئ الفراغ حيث ان هناك حقيقة مثبتة ان الناس لا تهتم بالنص المكتوب اكثر من الشكل الخارجي هذا النتص هو مجرد لملئ الفراغ حيث ان هناك حقيقة مثبتة ان الناس لا تهتم بالنص المكتوب اكثر من الشكل الخارجي هذا النتص هو مجرد لملئ الفراغ حيث ان هناك حقيقة مثبتة ان الناس لا تهتم بالنص المكتوب اكثر من الشكل الخارجي </p> <input type="button" value="جلب المحدد" onclick="getSelectedText()"> <form name="testform"> <textarea name="selectedtext"></textarea> </form> حيث تقوم الدالة getSelectedText بطباعة النص المظلل في صندوق النص selectedtext : function getSelectedText() { // جلب النص المظلل var selectedText = window.getSelection(); // كتابة النص المحدد في الحقل النصي document.testform .selectedtext .value = selectedText; } تفحص المثال العملي .
  8. ليس شرطا أن تعرف أن مصفوفة ما تم إرسالها عن طريق متصفح ما رغم أنه يمكنك ذلك، وسيكون الإكتفاء بتوليد رمز في كل طلب تسجيل دخول كافيا جدا ، فالعملية لن تتعلق بالمتصفح بشكل وثيق . لاحظ : وصحيح أن عمود إنتهاء الصلاحية أيضا يخزن مصفوفات JSON أيضا، قد أحسنت في تنبيهي إلى ذلك. ولكن كون الأمر يمتد هكذا لما لا نقول بإنشاء جدول رموز token؟ أين يتم تخزين كل رمز مفردا بشكل مستقل بدل مصفوفة . وليكن هذا الجدول tokens مثلا، حيث يحمل الأعمدة التالية: user_id يمثل عمود id من جدول المستخدمين token يمثل رمز التوكين token_expires_at يمثل تاريخ إنتهاء صلاحية هذا التوكين ثم بدل التحقق من إمتلاك المستخدم لرمز token في عمود المستخدمين يتم ربط العملية بالجدول المنشئ حديثا. هذا ليس إلا مثالا عن تطويرٍ للفكرة إبتداءا من الفكرة الأساسية، يمكن بذات المنطق الذهاب بالفكرة إلى أبعد من ذلك وإضافة العديد من الميزات الأخرى. يحتمل أن يكون ذلك ناتجا عن تحديثات رمز التوكين عن طريق رمز منتهي الصلاحية، حيث يحدث هذا في الكواليس بعد كل طلبية HTTP مرفقة بـرمز token منتهي الصلاحية. يمكن أن تخصص الشيفرة التي لديك بطريقة تعمل على إنشاء رمز توكين جديد إنطلاقا من اخر منتهي الصلاحية .
  9. لن يعمل هذا الزر لأن الحدث الإفتراضي المسند إليه هو تقديم النموذج form submission ، أي إرسال البيانات المدخلة في الحقول ما بين وسم فتح form ووسم إغلاقه إلى نقطة الوصول الموضحة في الخاصية action الخاصة بالعنصر form . وفي حالة عدم تعريف هاته الخاصية سيتم إسناد القيمة "" لها مما يشير إلى نفس الصفحة . وبالتالي فإن أي إسناد لأي حدث اخر لن يتم إعتباره , وببساطة : لن يعمل الزر وسيكون الضغط عليه إرسالا للبيانات في نفس الصفحة . أفهم من طريقتك في كتابة الشيفرة أنك تحاول الذهاب إلى صفحة البحث search.html عند ضغطك للزر الكائن داخل النموذج . المكان الصحيح لتعريف هاته العلاقة هو بإستعمال الخاصية action لوسم النموذج form ، أين يتم إرفاق رابط الصفحة المستهدفة: <form action="search.html" class="d-flex my-2"> <input class="form-control me-sm-2" type="search" placeholder="Search"> <button class="btn btn-success" type="submit">click</button> </form> تعرف أكثر على العنصر form > الخاصيات .
  10. عموما ، يشترط أن يكون رمز التوكين الذي تحاول توليده امنا من الناحية التشفيرية cryptographically secure . إذ لا يميل الكثير إلى توليد سلسلة نصية عشوائية عن طريق دوال من مثل rand أو uniqid أو غيرها كونها لم توجد لعمليات التوثيق التي تتطلب مستوى أعلى من الحماية والأمان ، لأن هاته نفسها مرتكزة على مفاهيم أخرى من مثل وقت إستدعاءها ، مما يجعل عملية فكرة التركيز عليها هشة. راجع قسم الوصف من توثيق الدالة uniqid()‎ في PHP : فضلا عن الإنطلاق من سلسلة نصية معلومة مثل تلك التي تخزنها في المتغير whoami . وكحلول أكثر أمانا توفر PHP بدائل تصفها بأنها " آمنة تشفيريا cryptographically secure " . فمكتبة PHP 7 القياسية مثلا توفر وظيفة random_bytes التي تقوم بتوليد وحدات بايت عشوائية آمنة. ستحتاج بعد ذلك تحويل وحدات البايت هاته إلى hexadecimal عن طريق الوظيفة bintohex . مثال : <?php $bytes = random_bytes(60); $token = bin2hex($bytes); echo $token; /* 8063741bbb1dd099aa059e3ee1851bdb8a27a7d1 b22e962801c76b10dc0107828ec679fe93fac698 6c93d6e863542e69e029f5db08bf367ac6de66ab */ يمكنك أيضا الإستعانة بمكتبات أكثر أمانا وأكثر إلتفاتا لهذا الجانب ، من مثل مكتبات OAuth في PHP التي توفر التابع generateToken عن طريق مزود خدمتها OAuthProvider كالتالي : $p = new OAuthProvider(); $t = $p->generateToken(60); أو ربما مكتبات وحزما أخف حجما من مثل الغنية عن التعريف jwt .
  11. تأكد من عدم إرفاق أية مساحات بيضاء قبل إرفاق اسم ملف الصورة ، في : images/ Penguins.png لكن كون العملية مُتحكمٌ فيها عن طريق الـ PHP فيحتمل أنك لسبب ما تضيف فراغا عند إدراجك للعمود img في الجدول الذي تحاول الإستعلام منه . ورغم أنه يُفضّل تتبع شيفرة الإدراج إلا أنه يمكنك حذف الفراغات في بداية ونهاية إسم الصورة عن طريق الوظيفة trim . إذ تقوم هاته الوظيفة بإزالة المسافات البيضاء (whitespace) (محارف الفراغات) أو أي محرف آخر من بداية السلسلة النصيَّة المررَّة إليها ونهايتها. لتكون الشيفرة التي لديك كالتالي : src="images/<?php echo trim($cours['img']); ?>" الناتج : images/Penguins.png توثيق الدالة trim .
  12. لما لا تقوم ببساطة بربط المشروع بمستودع GIT واحد و ربط هذا المستودع بالعديد من البيئات الأخرى . ثم عند تحديثك لمستودع الـ GIT هذا سيتم تلقائيا إلتقاط مختلف التعديلات التي قمت بها من المستودع عن طريق هاته البيئات وبالتالي تحديثها كلها . يمكنك بهذا خدمة فكرة الـ multi server deployment وتحقيق نفس الغرض .
  13. مبدئيا لن يمكن ذلك ، لأن هاته الطريقة تفرض أن يتم تحديث قيم token و token_expires_at في كل عملية تسجيل دخول . ولذلك فإن الرمز المخزن في المتصفح الأول سيختلف عن الثاني ولن يمكن إلا المطابقة عن طريق أحدهما . كفكرة يمكنك تخزين أكثر من توكن واحد في مصفوفة JSON بداخل حقل token ، أين يمكنك التحقق من مطابقة التوكن اللذي يرسله المستخدم عن طريق متصفح ما مع أحد الرموز المخزنة بحقل token . بالطبع فإن هذا هو الشكل الأبسط للعملية ، يمكن إنطلاقا منها تطويرها أو إضافة أي مميزات أخرى تخدم غرضا ما لديك . الاحتفاظ بتسجيل الدخول سيفرض تمديد المهلة الزمنية التي تنتهي فيها صلاحية التوكن في الخطوة الثالثة : أما عن الوقوع في الثغرات الأمنية بهذا الخصوص فلا مشكلة في تخزين رمز المصادقة في الواجهة الأمامية ، لأن العملية مُتحكّمٌ بها من الواجهة الخلفية . راجع إجابة المدرب سامح في سؤالك السابق :
  14. في العادة يتم إستعمال التوكين لتوثيق طلبات الـ HTTP أو التحقق من صلاحياتها في طلب مورد ما . كطريقة عامة في إستعماله ،لنقل أنه يتبع المنطق التالي : يتم إنشاء العمودين بجدول المستخدمين : token VARCHAR(255) token_expires_at TIMESTAMP حيث أن تخزين السلسلة النصية اللتي يتم توليدها في العمود token ، في حين أن العمود token_expires_at سيحمل تاريخ إنتهاء صلاحية هذا الرمز . عند طلب المصادقة و تسجيل الدخول يتم إستقبال طلب العميل من الخادم . سيتم أولا التحقق من بيانات هذا المستخدم ، ثم سيتم توليد سلسلة نصية . سيتم تخزين هاته السلسلة النصية في عمود token الخاص بهذا العضو المستهدف ، كما سيتم تحديث عمود token_expires_at وإرفاق تاريخ جديد . يقوم الخادم بمصادقة الطلب وإعادة هذا الـ token في رد إلى العميل . يقوم العميل بإستقبال رد الخادم وتخزين هذا الـtoken ، يمكن تخزينه في التخزين المحلي LocalStorage أو عن طريق ملفات تعريف الإرتباط Cookies . في الطلبات القادمة سيتم قراءة الـ token من التخزين المحلي و إرساله مع الطلب . يقوم الخادم بالتحقق من وجود token مماثل مخزن وغير منتهي الصلاحية . يكون ذلك عن طريق التحقق من وجود السلسلة النصية التي يرسلها المستخدم بجدول المستخدمين ، وبمقارنة تاريخ إرسال الطلب بتاريخ إنتهاء صلاحية التوكين . سيمكن بناءا على ذلك توثيق الطلب ومصادقته ، أو رفض الطلب وإعلام المستخدم بإنتهاء صلاحية رمزه وطلب إعادة تسجيل الدخول مثلا .
  15. واجهة البرنامج سهلة عموما ولا تحمل أية تعقيدات . في حالة مواجهتك لأي مشكلة يمكنك بأي وقت طرح أي استفسار بخصوص البرنامج بقسم الأسئلة العامة في أكاديمية حسوب و سيتم تقديم العون لك وتوجيهك.
  16. نعم ، يمكنك تطبيق العديد من لغات البرمجة وأطر العمل عمليا من على جهاز الهاتف الخاص بك عن طريق إستعمال محررات أو بيئات تطوير IDE خاصة بالهاتف . أحب عادة إستعمال تطبيق Dcoder ، وهو بيئة تطوير كاملة تدعم البرمجة بالعديد من اللغات وأطر العمل . يتيح أيضا إمكانية إرفاق لوحة المفاتيح بالهاتف ، هذا بجانب العديد من المميزات الأخرى من مثل : دعم تعدد اللغات . يمكنك إيجاده في متجر play store لتطبيقات الأندرويد بإسمه الكامل كالتالي :
  17. React Native هو إطار عمل يساعد على إنشاء تطبيقات جوال باستخدام لغة JavaScript ومكتبة React . التطبيقات التي تبنى بإطار React Native أصيلة، ما يعني أنّ شيفرة JavaScript تُترجَم إلى الشيفرة الأصلية للجهاز حسب المنصّة (Android أو iOS)، بخلاف التطبيقات الهجينة التي يُمكن إنشاؤها بأطرٍ مثل Cordova. Cordova هو إطار عمل مفتوح المصدر يساعد على إنشاء تطبيقات جوال .يسمح باستخدام تقنيات الويب القياسية مثل HTML5 و CSS3 و JavaScript لتطوير تطبيق للجوال يعمل على جميع المنصات. يمكنك مراجعة توثيق كل منهما في : توثيق ReactNative . توثيق Cordova . كما يمكنك الإطلاع على مقالات الأكاديمية في قسم Cordova .
  18. يحددث هذا بسبب أن لديك خطأ في السياق العام لإضافة إستعلام قيد CHECK ، فالشكل العام لإستعماله يكون كالتالي : ALTER TABLE [table_name] ADD CONSTRAINT [check_name] CHECK ([column_name] IN ('check1', 'check2', 'check3' ... )); حيث أن : table_name : يعبر عن اسم الجدول الحاوي للعمود المستهدف . check_name : يعبر عن اسم القيد الذي تحاول إضافته . column_name : يعبر عن اسم العمود المستهدف . ما داخل القوسين يعبر عن القيد و شرطه . ففي المثال الذي لديك يجب أن يوجد كالتالي : ALTER TABLE orders ADD CONSTRAINT size_check CHECK (size IN ("s", "e", "l", "xl")); ليصبح كامل الإستعلام كالتالي : ALTER TABLE ADD COLUMN size varchar(255); ALTER TABLE posts ADD CONSTRAINT size_check CHECK (size IN ("s", "e", "l", "xl"));
  19. لا يأخذ أي وقت فعملية التسجيل بسيطة مثلها كأي عملية تسجيل أخرى . فبمجرد شرائك للدورة سترسل لك التفاصيل عبر البريد الالكتروني و ستلاحظ ظهور زر " دوراتي " في قائمة التصفح العلوية و سيصبح محتوى الدورة متاحا لك بشكل طبيعي . تأكد أن تقوم بمراجعة صندوق رسائل البريد الإلكتروني ، كما يمكنك مراسلة الدعم لأي استفسارات أخرى.
  20. بالطبع يمكنك ذلك ، فبوتستراب يوفر إمكانية تحسين اداءه و يتجاوز مشكلة بطئ تحميله أو تحميل مكونات لا نحتاجه . و يتيح إمكانية تضمين كل مكون على حدة ، مثل : badge ، alert ، containers ، grid أو غيرها . و لكن يكون كل ذلك بإستعمال Sass ، فهو يوفر إمكانية استيراد المكونات التي تحتاجها فقط دون الأخرى . توفر حزمة bootstarp الملف bootstrap.scss ، أين يتم تضمين قائمة المكونات : // الإعداد و التهيئة @import "functions"; @import "variables"; @import "mixins"; @import "utilities"; // المكونات @import "root"; @import "reboot"; @import "type"; @import "images"; @import "containers"; @import "grid"; @import "tables"; @import "forms"; @import "buttons"; @import "transitions"; @import "dropdown"; @import "button-group"; @import "nav"; @import "navbar"; @import "card"; @import "accordion"; @import "breadcrumb"; @import "pagination"; @import "badge"; @import "alert"; @import "progress"; @import "list-group"; @import "close"; @import "toasts"; @import "modal"; @import "tooltip"; @import "popover"; @import "carousel"; @import "spinners"; @import "offcanvas"; // Helpers @import "helpers"; // Utilities @import "utilities/api"; فإذا كنت لا تستخدم أحد المكونات فيمكنك ببساطة تعليق سطره أو حذف تماما من الملف . ثم سيمكنك عن طريق خوادم و أدوات مثل webpack إخراج ملف جامع . قد تكون هاته المعلومات متقدمة بعض الشيء إذ يعتبر هذا تعديلا على الملف الأم لبوتسراب بطريقة مخصصة غرض التحسين ، ولكن هذا لا يمنع من طرح الفكرة أو البحث فيها أكثر .
  21. بشكل عام ، إستعمال بوتستراب ليس به أي عيوب إن كنت تحبذ نمطا معينا للتصميم فيه و لكنك ستواجه أحد هاته العيوب في حالات أخرى : ستكون هناك حاجة إلى الكثير من تجاوز الشيفرات و إعادة كتابة الملفات أو إعادة تعيين بعض التنسيقات التي يمكن أن تؤدي إلى قضاء الكثير من الوقت في تصميم موقع الويب وترميزه إذا كان التصميم يميل إلى الانحراف عن التصميم المعتاد المستخدم في Bootstrap ، أي أنه سيتعين عليك بذل جهد إضافي أثناء إنشاء تصميم وإلا ستبدو جميع مواقع الويب التي تقوم بهاا متشابهة إذا لم تقم بإجراء عمليات تخصيص كبيرة. الأصناف التي يوفرها بوتستراب كثير ويمكن أن تؤدي إلى الكثير من العبث في HTML وهو أمر غير مطلوب دوما و قد يتعارض مع مفاهيم الشيفرة النظيفة في بعض الأحيان . نسخ متأخرة من بوتستراب معتمدة كليا على jQuery و Pooper ، مما يترك معظم الشيفرات الإضافية غير مستخدمة ، وهو أمر اخر يتعارض مع مفاهيم الشيفرة النظيفة بجانب أنه قد يؤخر تحميل الصفحات إن كانت سرعات التحميل لدى عملائك أو أغلبهم بطيئة . لكن هذا لا يمنع بالطبع من إمتلاك الكثير من الإيجابيات التي يمكن أن تجعلك تغفل أو تتقبل هاته السلبيات ، نذكر من بينها : كونه يساعدك على تجنب العديد من الأخطاء التي يمكن أن تظهر أثناء تعميم الخواص على المتصفحات . فعلى سبيل المثال : لا نقوم بتخصيص صنف لـ google chrome و اخر لـ IE ، بل نجد أن بوتستراب يوفر صنفا واحدا جامعا يتعامل به بوتستراب مع كامل التغيرات بين المتصفحات . بجانب أنه يعتمد على jQuery فهو أيضا يجنبك إستعمال الكثير من إضافات الجيكويري أو تضمين المكتبات المعتمدة عليها لخدمة أغراض معينة . يساعدك في الحصول على عمل و يضمن لك مكانا في سوق العمل ، إذ أن بوتستراب واحد من أكثر الأدوات المطلوبة في سوق العمل . يقدم Bootstrap نظام تخطيط شبكي Grid system رائع ، يختصر عليك هذا الكثير من الجهد و الشيفرات الإضافية . التجاوبية ، فأغلب حاويات بوتستراب تجاوبية و مرنة مع كل الشاشات ، هذا بجانب أنه يوفر أصنافا خاصة بكل نوع من الشاشات . يوفر الوقت ، فبوتستراب يحرص على توفير أغلب -إن لم نقل كل- ما تحتاجه لتصميم موقع الويب الخاص بك . أما عن تفضيلك لنظام التخطيط الشبكي grid system عن نمط الصندوق المرن flexbox فهو شيء طبيعي جدا ، ولا مشكلة بذلك إن كان إستخدامه أفضل و أكثر مرونة بالنسبة لك . قد تحتاج الإطلاع على العلاقة بين الخطاطة الشبكية Grid Layout وبين طرق التخطيط الأخرى .
  22. يمكنك مراسلة مركز مساعدة أكاديمية حسوب و اقتراح الفكرة . كما قد تحتاج الإطلاع على صفحة درب معنا للاستزادة .
  23. يمكنك إستعمال حزمة barryvdh/laravel-dompdf لذلك ، إذ توفر هاته الحزمة إمكانية تحويل ملف عرض view بسيط إلى ملف PDF و تحميله . نحتاج في ذلك تطبيق الخطوات التالية : تثبيت الحزمة و إعدادها . تثبيت الحزمة يتم عن طريق تشغيل الأمر : composer require barryvdh/laravel-dompdf سنحتاج بعد ذلك إضافة مزود خدمة الحزمة إلى مصفوفة providers في ملف config/app.php : 'providers' => [ Barryvdh\DomPDF\ServiceProvider::class, ], يفضل أيضا تعريف اختصار للوصول السهل إلى واجهة الحزمة : 'aliases' => [ 'PDF' => Barryvdh\DomPDF\Facade::class, ] توفير رابط لطباعة ملف العرض بشكل PDF : في ملف العرض ، نحتاج توفير زر تصدير للصفحة المعروضة بشكل PDF . يكون ذلك بشكل مشابه : <div class="d-flex justify-content-end mb-4"> <a class="btn btn-primary" href="{{ route('pdf_export') }}">PDF تصدير إلى </a> </div> و بالطبع سنحتاج تعريف هذا المسار في ملف routes/web.php : <? use App\Http\Controllers\PDFController; Route::get('/pdf_export' ,[PDFController::class , 'export'])->name('pdf_export'); إستعمال توابع الحزمة لتصدير الملف . ليكن التابع export للمتحكم PDFController كالتالي : namespace App\Http\Controllers; use Illuminate\Http\Request; use PDF; class PDFController extends Controller { public function export() { $pdf = PDF::loadView('target_view', $someData); return $pdf->download('file_name.pdf'); } } بحيث أن : target_view : يعبر عن ملف العرض المستهدف ، يمكنك إستبداله باسم ملف العرض المناسب الذي تريد تصديره . file_name.pdf : يعبر عن اسم الملف المصدر ، يمكنك تغييره بحسب حاجتك أو حاجة عميلك .
  24. طبقا للتوثيق الرسمي لمرجع أخطاء مكتبة libcurl المشار إليه في نص الخطأ فإن الخطأ cURL error 60 يعني أنه قد تم اعتبار شهادة SSL للخادم الذي تحاول إرسال الطلب من عليه غير مقبولة . قد تتعدد أسباب رفضها ، و لكن إشارتك للتالي : توضح أنه لا يمكنك إرسال طلب موثق بشهادة SSL لأنك في الغالب تستعمل localhost ، و ليكن في العلم أنه لا يحتوي على هاته الشهادة افتراضا . لا أظن أن بالأمر مشكلة كونك تقوم بتجربة الواجهة التي تستهدفها عن طريق خادمك المضيف . و لكن يقترح كحل لهاته المشكلة إضافة SSL صالح للمضيف المحلي لـ XAMPP كونك تقوم بإرسال هاته الطلبات بإستخدام أو بوساطة cURL .
×
×
  • أضف...