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

Adnane Kadri

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

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

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

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

    51

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

  1. الكود خاصتك غير منظم جيدا و لذلك هو غير واضح أو غير قابل للقراءة بشكل عادي . و لكن لتنفيذ الفكرة التي تصفها يمكنك عمل تحديث للصفحة و التحريك التلقائي لشريط التمرير بعد نجاح اظهار الرسائل . و لنتأكد من إتباع مبدأ فصل الاهتمامات لتنظيم العملية أكثر , سيتبع الكود المنطق الموصوف سابقا على نحو مشابه : function adjustScroll() {} function loadUnseenNotifications() { // بعد ارسال طلب الاجاكس لتحميل اشعار بالرسائل الغير مقروءة if (data.unseen_notification > 0) { $j('.count').html(data.unseen_notification); // تحميل الرسائل و عرضها ضمن الشاشة ان كانت الرسائل أكثر من 1 loadMessages(); } } function loadMessages() { // بعد تحميل الرسائل نحتاج تحديث الصفحة و عمل الاسكرول التلقايئ adjustScroll(); } setInterval(function() { loadUnseenNotifications(); }, 1000); أي : يتم التحقق كل ثانية إن كان هنالك إشعارات رسائل غير مقروءة . ان كان نعم سيتم تحديث عد الاشعارات غير المقروءة + تحميل رسائل جديدة . سيقوم تحميل رسائل جديدة تلقائيا بعد انتهاء طلب الأجاكس بتحديث الصفحة و عمل اسكرول تلقائي للأسفل لاخر رسالة تم تحميلها . و رغم أن تطبيقات الدردشة تستعمل تقنيات أحدث إلا أنه يعتبر تطبيقا عمليا جيدا . بالطبع فإن العملية وصفية , لكن يمكنك صياغة الكود الخاص بك وفق الخطوات السابقة .
  2. قد يختلف الأمر قليلا خصوصا لو كنت قادم من نظام تشغيل ويندوز , فلن تجد واجهة تفاعلية تخبرك بما عليك فعله . و سيتم كل ذلك عن طريق التارمنل . عن طريق ما يعرف بمدراء الحزم . و بالطبع فإن الأمر ليس دستورا ثابتا , فهو يختلف من توزيعة لينكس إلى أخرى , و من مدير حزم إلى مدير اخر . و لنأخذ على سبيل المثال توزيعة ubuntu الغنية عن التعريف . في ubuntu يمكننا تثبيت البرنامج بـ 3 طرق مختلفة : عن طريق مركز برمجيات أوبونتو أو Ubuntu Software Center : وهو عبارة عن برنامج يوفر واجهة تفاعلية يسهل من عليها استعراض البرامج المتوفرة و تثبيتها عن طريق ضغطة زر . قد توفر توزيعات أخرى نفس الفكرة . عن طريق snap : وهو مدير حزم يقوم بتحميل الحزم و تحميلها من متجر snap , يتوفر snap في عديد من توزيعات لينكس من مثل فيدوار و لينكس مينت . و سنحتاج للتارمنل في التعامل معه لأن snap لا يوفر واجهة تفاعلية . يتم تثبيت البرامج عن طريقه بأوامر مشابهة : sudo snap install <app-name> عن طريق مدير الحزم apt : sudo apt install <app-name> و كوننا قد قمنا بثتبيت البرنامج لن يجعل من المنطقي ان نقوم بتثبيته كل مرة غرض تشغيله , و بالتالي فإنك لن تحتاج ذلك و يكفي تثبيته مرة واحدة . و لتشغيل البرنامج نقوم إما بطباعة اسمه في التارمنل أو بالتصفح إليه في قائمة البرامج . كما يمكنك إنشاء أيقونة سطح المكتب للوصول السهل إليها .
  3. يحاول الخطأ إخبارك أن المشروع الذي تحاول تطبيق الأمر فيه ليس مستودع git , و لذلك سنحتاج تحويله لذلك قبل عمل أي أوامر git عليه . يمكنك ذلك عن طريق الأمر : git init قد تحتاج أيضا ربط ملفات مشروعك مع مستودعك البعيد عن طريق الأمرين : git remote add origin https://your_gitrepo/some_repo ثم : git branch -M main بعد ذلك يمكنك تطبيق الأوامر : git add -A git commit -m "init commit" git push -u origin main
  4. هلا قمت بطباعة الأمور التالية على التوالي : git checkout -b myBranch git checkout master git merge myBranch git branch -d myBranch سيقوم هذا بتبديل الفروع أولا ثم استعادة ملفات المستودع الحالي و دمجها مع ملفات مشروعك , ثم إنشاء فرع جديد للدفع إليه . يمكنك بعد هذا إنشاء commit بطريقة عادية : git commit -m "my commit" ثم الدفع إلى الفرع الجديد في مستودعك : git push -u origin myBranch
  5. ينغبي الفهم أولا أن قاعدة البيانات ، ليست هي إلا مجموعة بيانات أو معلومات يتم تنظيمها لتسهيل تخزينها , استرجاعها , تعديلها وحذفها بالتزامن مع عمليات معالجة البيانات المختلفة . عادة ما يتم ذلك عن طريق نظم إدارة قواعد البيانات , و يشار إلى النظام نفسه مع البيانات بقواعد البيانات . أي أن الهدف واحد و السبل تختلف . عادةً ما يتم نمذجة هاته البيانات الموجودة ضمن الأنواع الأكثر شيوعًا من قواعد البيانات الشغالة اليوم في : صفوف وأعمدة في سلسلة من الجداول لجعل المعالجة والاستعلام عن البيانات فعالا و أبعد قليلا عن التجريد . بحيث يمكن بعد ذلك الوصول إلى البيانات وإدارتها وتعديلها وتحديثها والتحكم فيها وتنظيمها بسهولة . تستخدم معظم قواعد البيانات لغة الاستعلام المهيكلة (SQL) لكتابة البيانات والاستعلام عنها أو إدارتها . يوجد العديد من أنواع قواعد البيانات المختلفة التي يمكن لمؤسسة أو برنامج ما إتباعها نذكر منها : قواعد بيانات علائقية Relational databases : يمكن اعتبارها الأكثر شيوعا الان . بحيث يتم تنظيم العناصر الموجودة في قاعدة البيانات العلائقية كمجموعة من الجداول ذات الأعمدة والصفوف التي يمكن لها أن تحمل علاقات فيما بينها . قواعد بيانات كائنية التوجه Object-oriented databases : بحيث يتم تنظيم البيانات بشكل كائنات يسهل التعامل معها بمنطق مشابه لمنطق البرمجة الكائنية . قواعد بيانات موزعة Distributed databases : يتم تنظيم البيانات بشكل ملفات تكون موزعة على مكانين أو أكثر . قواعد بيانات غير علائقية NoSql: تعتبر الأفضل من ناحية تخزين البيانات غير المهيكلة unstructured و شبه المنظمة semistructured . واحدة من الأكثر شيوعا الان . طبعا ليست هاته الأنواع الوحيدة فقط بل يوجد الكثير غيرها .. كل منها ينفرد بمنطقه و طريقة معالجته للبيانات و تخزينها . و مثلما تم الإشارة فإنه يتم إدارتها عن طريق نظم إدارة قواعد البيانات (database management system) اختصارا : DBMS .بحيث يعمل كواجهة بين قاعدة البيانات والمستخدمين النهائيين أو البرامج ، مما يسمح للمستخدمين باسترداد وتحديث وإدارة كيفية تنظيم المعلومات وتحسينها . و أيضا الإشراف والتحكم في قواعد البيانات ، يوفر هذا مجموعة متنوعة من العمليات الإدارية مثل مراقبة الأداء والضبط والنسخ الاحتياطي والاسترداد و غيرها . و لنأخذ MySql كمثال : MySQL هو نظام إدارة قواعد بيانات علائقية مفتوح المصدر يعتمد على SQL . تم تصميمه وتحسينه لتطبيقات الويب . كانت وراء بعض أفضل مواقع الويب و تطبيقات الويب في العالم ، أمثلة : Airbnb و Uber , LinkedIn , Facebook , Twitter , YouTube . و رغم أنها بالفعل خسرت بعض شعبيتها في الأعوام الأخيرة إلا أنه لا بأس في تعلمها و التعرف عليها و العمل بها , خصوصا في سوقنا العربي فهي : سهلة التعلم. ما تزال شائعة ومهيمنة نوعا ما . توثيقها السهل و وفرة المعلومات حولها . متوفرة بشكل افتراضي في أغلب الاستضافات . مجانية . يمكنك القراءة عن Mysql أكثر هنا . يمكنك أيضا التعرف أكثر على قواعد البيانات على بعض من نظم إدارة قواعد البيانات هنا . كما يمكنك الاستزادة بقراءة بعض من مقالات الأكاديمية بهذا الشأن : الأنواع السبعة لروابط الجداول في SQL مقارنة بين أنظمة إدارة قواعد البيانات العلاقية: SQLite مع MySQL مع PostgreSQL شرح الفروقات بين قواعد بيانات SQL ونظيراتها NoSQL
  6. يمكنك إضافة الخاصيتين data-toggle و data-target لوسم الصورة أو العمود : data-toggle="modal" data-target="#mymodal" سيقوم هذا بفتح المودل بعد الصغط على الصورة أو العمود .
  7. تأكد أن تقوم بحذف ملف index.lock داخل مجلد git. , يمكنك ذلك عن طريق الأمر : rm -f .git/index.lock و في حال ظهر معك خطأ على هذا النحو : 'rm' is not recognized as an internal or external command يمكنك طباعة الأمر : del -f .git/index.lock .. قد نتسبب في هذا المشكل عندما نحاول تطبيق أمري أو عمليتي git في نفس الوقت , و في الغالب تكون واحد عن طريق المحرر vsCode و الاخر عن طريق موجه الأوامر أو التارمنل . و حذف ملف index.lock سيقوم بإلغاء أي عمليات أخرى معدا الحالية و بالتالي حل المشكل.
  8. يمكنك معاملة الصور و أيقونات كزر فتح المودل , سيتبع الكود منطقا مشابها : <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img1.png" /> </button> <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img2.png" /> </button> <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img3.png" /> </button> <button type="button" class="btn" data-toggle="modal" data-target="#mymodal"> <img src="img4.png" /> </button> <!-- المودل يبدأ هنا --> و بالطبع ستحتاج إرسال طلب الأجاكس بشكل منفصل . سنحتاج أولا تعريف النموذج و إضافة حدث عن طريق الجافاسكربت : var myForm = document.querySelector('#myform'); myForm.addEventListener('submit' ,function(e){ e.preventDefault(); // منع تحديث الصفحة sendAjaxRequest(); }); function sendAjaxRequest() { // سيتم إرسال طلب الاجاكس هنا } حيث أن الدالة sendAjaxRequest ستكون المسؤولة عن إرسال هذا الطلب . function sendAjaxRequest() { // XMLHttpRequest تعريف نموذج عن الكائن var xhttp = new XMLHttpRequest(); // جلب البيانات من النموذج var formData = new FormData(document.querySelector('#myForm')) xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { alert('تم إرسال الطلب'); } }; xhttp.open("POST", "http://path.to/endPoint/example", true); // فتح طلب xhttp.send(formData); // إرسال طلب }
  9. تعبر الخطوة السادسة عن طريقة القراءة بإستعمال هاته العلاقة فقط , ففي المثالين تم على الترتيب جلب : المنتجات التي تخص الفئة X . الفئات التي تخص المنتج Y . مثال : المنتجات التي تخص الفئة "ملابس رجالية" . الفئات التي تخص المنتج "تيشرت أزرق" .
  10. يمكن تلخيص الية إنشاءها وفق الخطوات التالية , سنقوم بتعريف العلاقة كمثال بين النموذجين Category و Product : بداية نحتاج إنشاء الجداول و النماذج المراد إنشاء العلاقة بينهما : php artisan make:model Category -m php artisan make:model Product -m سنحتاج أيضا إنشاء جدول وسيط لتحقيق منطق العملية . بحيث يجب أن يتكون اسم الجدول الوسيط من أسماء فردية لكلا الجدولين ، مفصولة برموز شرطة سفلية ، ويجب ترتيب هذه الأسماء بترتيب أبجدي ، لذلك يجب أن يكون لدينا category_product ، وليس product_category : php artisan make:migration create_category_product_table بعد ذلك سنحتاج التأكد من تعريف الحقول اللازمة في ملف تهجير هذا الجدول الوسيط , بحيث يجب أن يمتلك حقلا أجنبيا يعبر عن عمود المعرف id في كلا الجدولين : products و categories : public function up() { Schema::create('category_product', function (Blueprint $table) { $table->increments('id'); $table->integer('category_id')->unsigned(); $table->integer('product_id')->unsigned(); }); } 4. تنفيذ أمر التهجير : php artisan migrate 5. تعريف العلاقات في ملفات النماذج : بداخل ملف النموذج Product.php : class Product extends Model { public function categories() { return $this->belongsToMany(Category::class); } } و أيضا بداخل ملف النموذج Category.php : class Category extends Model { public function products() { return $this->belongsToMany(Product::class); } } 6. ثم كخطوة أخيرة لن يكون علينا إلا احترام العلاقة عند إنشاء أي صفوف بقواعد البيانات و القراءة عن طريق العلاقتين products و categories . $productsOfXCategory = Category::find($ID)->products; $categoriesOfXProduct = Product::find($ID)->categories;
  11. يبدوا أنك تقوم بإخراج الملفات إلى ملف واحد . بالطبع ستحتاج تعديل المخرج أيضا , سنحتاج إخراج الملفات منفصلة بحسب إسم الملف . فعوضا عن مثل هذا : output:{ path:path.join(__dirname,"/dist"), filename:"main.js" }, نحتاج إخراج الملفات على هذا النحو : output:{ path:path.join(__dirname,"/dist"), filename:"[name].js" }, حتى لا يحدث خطأ التعارض الذي ظهر معك , ثم يمكنك بعد ذلك تشغيل أمر البناء بشكل طبيعي : npm run build
  12. تأكد أنك تقوم بإعداد webpack ليقوم بعمل المطلوب على نحو صحيح , ففي الأرجح يتم بناء الملف الأصلي index.js لأنك تقوم بهذا في ملف webpack.config.js : entry: { main: path.resolve(__dirname, './src/index.js'), }, ثم تقوم بتضمينه في ملف الـ html : <script type="text/html" src="{required('index.js')}"></script> في حين أنك تحتاج تمرير عدة نقاط وصول لكائن المدخلات entry : entry: { main: path.resolve(__dirname, './src/scripts/index.js'), about: path.resolve(__dirname, './src/scripts/about.js'), contact: path.resolve(__dirname, './src/scripts/contact.js'), }, ثم يمكنك تضمين كل ملف على حدة في ملفات الـ html التي تقوم ببناءها . يمكنك القراءة أكثر عن الخاصية entry في دليل Webpack الشامل .
  13. في المتصفح , الإسم name لو تم تعريفه كمتغير بشكل عام globally يكون ذا معنى و قيمة خاصة , و مثلما أشار المدرب @عبدالباسط ابراهيم ينتهي الأمر بأي تعريف له إلى إكتشافه على أنه المتغير name الخاص بالكائن window . و كما هو شائع في توابع و متغيرات الكائن window , لا يجب إستدعاءها أو إستعمالها دوما عن طريق الكائن على هذا النحو : window.document.getElementById('#someID') بل يكفي قراءتها مباشرة . و ليكن في العلم أن المتغير window.name يحتوي على غرض خاص ، ويفترض أن يكون سلسلة نصية , لذلك فإن أية تعريفات على هذا النحو : var name = {}؛ ينتهي الأمر بها فعليًا بإعطاء اسم المتغير العام (أي window.name) قيمة . و هنا يحاول المدقق الخاص ببرنامج VsCode توضيح هذا الشأن عن طريق شطب أي إسناد قيمة للمتغير name بشكل عام global . و كما يمكنك رؤية أن الشطب يختفي إذا وضعت نفس الشيفرة داخل دالة و هذا دليل على أن هذا الأمر يقتصر على تعريف المتغير name بشكل عام فقط . و لذلك للتخلص من المشكل بشكل نهائي يمكن الإستعانة بأحد الحلين : تعريف المتغير و إسناد قيمة له داخل دالة , أي بشكل محلي locally . إختيار إسم اخر للمتغير عوضا عن name , و ليكن customerName مثلا .
  14. يجدر الإشارة أن الـ Greedy Algorithms أو الخوارزميات الجشعة ليست خوارزمية Algorithm و إنما هي أسلوب خوارزميات Algorithm Paradigm وهو الشكل العام لتصميم الخوارزمية و منطقها دون التوغل في تفاصيلها . و أصل التسمية نفسه يعود إلى أسلوبها , فهي الأسلوب الذي يفرض أن تجد حلول مثلى محلية localized optimum solution, والتي من الممكن فيما بعد أن تتحول الى حلول مثلى عامة globally optimized solutions. و لذلك سميت بالخوارزميات الجشعة, لأنها تختار الحلول المحلية المثلى , أي أنها تؤمن حلا للخطوة الحالية من الخوارزمية من دون الأخذ بالحسبان تأثير هذه الخطوة على تكملة الحل , فهي جشعة لا تنتظر أو تؤمن حلولا مثلى عامة . و يستعمل لشرحها عادة مسألة الرحالة التاجر الذي يريد أن يمر بعدد من الأحياء لبيع بضاعته. هدف هذا التاجر هو إيجاد المسار الأقصر الذي يمر بكل الأحياء , فيستهدف بذلك كل القرية أو المدينة . وفق طريقة الخوارزمية الجشعة، على التاجر أن ينظر كل مرة إلى خريطته ويسافر إلى أقرب حي لم يزره بعد . أي أن الهدف هنا هو الحل الأمثل المحلي و الخاص بالخطوة الحالية أي الـ localized optimum solution , و ذلك بغض النظر عن تأثير هاته الخطوة على تكملة الحل , فبتطبيق منطق الخوارزميات الجشعة لن نهتم إن كان التاجر سيضطر في نهاية الأمر إلى العودة إلى هذا الحي بنهاية المسار ويسلك طريقاً أطول . أي أننا لا نهتم بالدرجة الأولى بتوفير حلول مثلى عامة globally optimized solutions. يمكنك القراءة عن الكثير من الخوارزميات و المسائل التي تقوم بإستعمال هذا النهج من مثل : مسألة عد العملات counting coins . كما يمكنك التعرف أكثر على الخوارزميات الجشعة طبقا لويكي حسوب . و قد تحتاج أيضا التعرف أكثر الفرق بين الخوارزمية Algorithm و أسلوب الخوارزميات Algorithm Paradigm.
  15. طريقة طرحك للسؤال تقتضي الفصل و توضيح الفرق بينهما . عن جافاسكربت : هي لغة برمجة نصية و تعتبر أفضل أداة لإنشاء صفحات ويب تفاعلية وسهلة الاستخدام. نظرًا لأنه يتم تنفيذ إستعلاماتها في المتصفح . فمن جانب العميل ، تتيح Javascript استجابة سريعة وتحميل أقل على الخادم . وقد اعتادت أن تكون لغة الواجهة الأمامية , و لكن تغير الأمر بعد ظهور Node.js , إذ أصبح يتم إستعمالها لتطوير كل من الواجهتين الخلفية و الأمامية . تعد أيضا جافاسكربت خيارًا مثاليًا لإنشاء أحدث الأنماط من تطبيقات الويب , و هي تطبيقات SPA ديناميكي (تطبيق صفحة واحدة) (يمكنك القراءة أكثر عن الـ SSR , SPA , PWA) . و تجعل أطر عملها و منصاتها الأمر سهلا من مثل AngularJS و ReactJS . و كذلك مع الكثير من تقنيات الخادم من مثل MongoDB و CouchDB و NoSQL. عن PHP : تمامًا مثل جافاسكربت ، تعد PHP لغة برمجة نصية . تم إنشاؤها لتطوير الويب و واجهته الخلفية , و تقوم بالتعامل مع قواعد البيانات و نظم إدارتها . و يتمثل الاختلاف الرئيسي عن جافاسكربت في أن PHP هي لغة من جانب الخادم تُستخدم للواجهة الخلفية فقط و يتم تنفيذ كل إستعلاماتها على الخادم . و يجدر القول أنها تحتوي مميزات و مكتبات الأكثر ثراءً وأمانًا أفضل مقارنةً بـجافاسكربت في هاته النقطة . كما أن أغلب نظم إدارة العمل المشهورة في الساحة تم بناءها عليها , وطبعا لا يجب إغفال حجم المجتمع الخاص بها مقارنة بحجم مجتمع NodeJS . و بالتالي فإن PHP أفضل خيار عندما تكون هناك حاجة للعمل مع نظم إدارة CMS (WordPress و Drupal و Joomla) أو LAMP stack أو تقنيات مثل MariaDB و MySQL و PostgreSQL . و على الرغم من أنه يمكن استخدام جافاسكربت لتطوير كل من الواجهة الأمامية والخلفية بمساعدة منصات مثل Node.js ، لا تزال PHP أداة أفضل للواجهة الخلفية . و لكن ,بحسب رأيي الشخصي, الأفضل تماما ، سيكون فكرة الجمع بينهما من أجل بناء تطبيق ويب ديناميكي قوي , يستعمل مفاهيم تطوير الويب وواجهاته الحديثة . و بغض النظر عن اللغة التي تختارها ، PHP أو جافاسكربت ، لمشروعك . فإنه لا يوجد الأسهل أو الأسرع تعلما . يتحكم في هذا العديد من العوامل و النقاط , قد يكون من بينها حتى إنطباعك و تعودك على سياق الإثنين مثلا ! يمكنك التعرف أكثر على اللغتين في ويكي حسوب : عن PHP عن جافاسكربت كما يمكنك تصفح المقالات الخاصة بكل منهما في الأكاديمية : مقالات في جافاسكربت مقالات في PHP
  16. لا يمكن قراءة خاصية من التابع where مباشرة على هذا النحو : return sections::where("section_name","==","البنوك")->bank; و في حالة المحاولة سيتم إظهار خطأ يتم فيه إخبارك أن الخاصية bank غير موجودة . قبل ذلك نحتاج تنفيذ الإستعلام الذي قمنا للتو ببناءه عن طريق أحد التوابع get أو first : $first = sections::where("section_name","==","البنوك")->get(); $second = sections::where("section_name","==","البنوك")->first(); الأولى ستقوم بإعادة مجموعة كائنات كل منها يمتلك الخاصية bank و بالتالي و للقراءة منها نحتاج عمل دور على عناصر المجموعة على هذا النحو : foreach($first as $item){ echo $item->bank; } أما بالنسبة للثانية فهي سوف تقوم بإعادة أول كائن يحقق الإستعلام و يمكن قراءة الخاصية مباشرة منه : $second->bank أو : return sections::where("section_name","==","البنوك")->first()->bank;
  17. سنحتاج تحضير مصفوفة تحمل عدد مرات ظهور كل عنصر , ثم سيكون علينا تحديد الفهرس بالقيمة الأكبر أو الأصغر . مثال عملي : يمكننا الإستعانة بالدالة array_count_values لحساب عدد المرات التي ظهر فيها كل عنصر سلسلة نصية أو رقم من المصفوفة . $arr = array('محمد','رضا','أبراهيم','محمد','محمد','رضا','محمد'); $ordered = array_count_values($arr); ثم سيكون علينا قراءة العنصر بالقيمة الأكبر , يمكن ذلك عن طريق الدالة max , أو الأصغر عن طريق الدالة min , التان تقومان بجلب العنصر ذي القيمة الأكبر و الأصغر على التوالي في مصفوفة أعداد . $ordered = array_count_values($arr); $max = max($ordered); $min = min($ordered); و كخطوة أخيرة سنحتاج البحث عن المفتاح المرافق للقيمة الأكبر أو الأصغر المعادة في مصفوفة التي يتم إعادتها من الخطوة 1 . $maxVal = array_search($max, $ordered); $minVal = array_search($min, $ordered); فيكون الكود كاملا : $arr = array('محمد','رضا','أبراهيم','محمد','محمد','رضا','محمد'); $ordered = array_count_values($arr); $maxVal = array_search(max($ordered), $ordered); $minVal = array_search(min($ordered), $ordered); يمكنك الإطلاع على توثيق كل دالة مما تم إستعماله : الدالة array_count_values في PHP . الدالة array_search في PHP. الدالة max في PHP. الدالة min في PHP .
  18. ليس تماما . سيتم إظهار الخطأ في حالة صحة العبارة المنطقية . على عكس abort_unless التي سيتم فيها إظهار الخطأ في حالة خطأ العبارة المنطقية . أي أنه في abort_if سيتم إظهار الخطأ إذا كان : Gate::denies('user_access') يساوي صحيح .
  19. يقوم المساعد abort_if بطرح خطأ HTTP معين إذا تم تحقيق عبارة منطقية معين . مثال : abort_if(!$user->is_admin ,403); هنا سيتم عرض أو إعادة خطأ 403 ممنوع في حالة ما كانت العبارة المنطقية : !$user->is_admin صحيحة . و بنفس المنطق : abort_if(Gate::denies('user_access'), Response::HTTP_FORBIDDEN, '403 Forbidden'); أو يكفي : abort_if(Gate::denies('user_access'), 403); سيتم طرح أو إعادة خطأ 403 في حالة ما كانت العبارة المنطقية التالية : Gate::denies('user_access') صحيحة . و في حالة الخطأ سيتم تجاوز الخطأ و إكمال قراءة الشيفرة البرمجية التالية بشكل عادي . يمكنك التعرف أيضا على المساعدين abort_unless و abort .
  20. ستكون العملية معقدة بعض الشيء , بحيث أنه سيكون عليك تطبيق العملية بالإستعانة بالواجهة البرمجية المقدمة من يوتيوب . سيكون عليك إرسال طلبات HTTP إلى نقاط وصول معينة تقوم فيها بالتحقق من أن مستخدم X مشترك بالقناة X أو لا . و بناء عليه ستقوم إما بعرض المحتوى أو حجب المحتوى و إظهار زر الإشتراك . و طبعا ستعتمد في كتابة الشيفرة البرمجية الخاصة بهاته العملية على اللغة التي تم كتابة الواجهة الخلفية ,يفضل, للموقع بها . يمكنك إرسال الطلب إلى نقطة الوصول هاته : HTTP GET https://www.googleapis.com/youtube/v3/subscriptions?part=id&mine=true&key={YOUR_API_KEY} و ستحتاج إستبدال YOUR_API_KEY بالمفتاح الخاص بك عند فتح حساب مطور . سيتم جلب قائمة بأسماء كل المشتركين , ستحتاج فيها التحقق من إسم مشترك معين . و من ثم عرض الصفحة أو حجبها . كما يمكنك جلب إسم المشترك من ملفات تعريف الإرتباط في متصفح العميل .
  21. يمكنك إستعمال هاته الأداة المقدمة من مطوري غوغل لإنشاء و تضمين شيفرة زر الإشتراك في القناة , يمكنك ذلك عن طريق : التصفح إلى صفحة الأداة هنا . قم بطباعة المعرف الخاص بالقناة أو يكفي مجرد إسمها . يمكنك تخصيص نسق العرض و والوضع , كما يمكنك التحكم في عرض عدد المشتركين أو لا. و أخيرا قم بنسخ الكود الذي يتم توليده في مربع النص أسفل الشاشة و لسقه في الكود المصدري لموقعك .
  22. أظن أن من الخطأ إستعمال نفس قواعد البيانات للتحقق Testing و حل المشاكل Debugging , بهاته الطريقة ستكون البيانات الحقيقية عرضة للفقدان كليا . الطريق الأقصر : و هي الإستعانة بالكثير من الحلول البديلة من مثل : تحضير نسخ إحتياطية Backups لقواعد البيانات قبل تجربة التطبيق أو قبل تحديث التهجير لقواعد البيانات , ثم إعادة التهجير بعد التحقق . تحضير نسخة إحتياطية تجريبية للتطبيق , يمكن إستعمال حزم من مثل laravel-backup من مجموعة spatie لعمل ذلك و التجربة عليه . لكن الأفضل ,و الطريق الأطول, يكون بفصل عملية التحقق Testing بشكل كامل عن نفس إتصال قواعد البيانات الذي يستخدمه تطبيقك . و لارافيل تجعل ذلك سهلا مع phpunit . فعلى سبيل المثال : إن كان تطبيقك يستخدم Mysql فعمليات التحقق يجب أن تستخدم ذاكرة مؤقتة و إتصال sqlite . و إن لم يتم كتابة الاختبارات Tests بشكل إما مواز أو مسبق للأكواد فسيجب لتحقيق هذا كتابة الإختبارات اللازمة لكل أجزاء التطبيق حتى يتم تحقيق هذا الأخير و إختبار التطبيق نفسه , لا نسخة إحتياطية منه ,في بيئة التطوير أو الإنتاج و بدون أي فقد لأية بيانات .
  23. Adnane Kadri

    laravel Gate

    ليس تماما . ففي الشيفرة الأولى : abort_if(Gate::denies('user_create'), Response::HTTP_FORBIDDEN, '403 Forbidden'); أو يكفي : abort_if(Gate::denies('user_create'), 403); أو أيضا : abort_unless( !Gate::denies('user_create'), 403); نحن نقوم بمنع المستخدم من الوصول إلى حدث معين في حالة رفض البوابة Gate ذلك . لكن ما نقوم به هنا : Gate::define('create-post', function (User $user, Category $category, $pinned) { if (! $user->canPublishToGroup($category->group)) { return false; } elseif ($pinned && ! $user->canPinPosts()) { return false; } return true; }); ضمن التابع boot في ملف App\Providers\AuthServiceProvider هو تعريف للترخيص create-post . و لتوضيح العلاقة أكثر بين الشيفرتين ينبغي ذكر أنه : يتم التحكم في صلاحيات و تراخصي المستخدمين عن طريق البوابات Gates , بحيث يتم تعريف البوابة بإستعمال الواجهة Gate ضمن ملف AuthServiceProvider.php في التابع boot على هذا النحو : <?php use App\Models\User; use Illuminate\Support\Facades\Gate; /** * تسجيل أية خدمات ترخيص * * @return void */ public function boot() { $this->registerPolicies(); # تعريف البوابة Gate::define('access-db', function () { # إعادة القيمة البوليانية المسجلة في العمود المستهدف return auth()->user()->is_admin; }); } بعد ذلك يأتي إستعمالها في ترخيص الأحداث بإستعمال التابعين allows و denies على هذا النحو : public function index() { if (! Gate::allows('access-db')) { abort(403); } return view('admin_db); } أو إختصارا : public function index() { abort_if (! Gate::allows('access-db') ,403); return view('admin_db); }
  24. جميل أنك اخترت واحدة من حزم مجموعة spatie . تقوم هاته الحزمة بتنفيذ الأمر بوساطة الأدوار عوضا عن مجموعات الصلاحيات , وتختصر بذلك الكثير . قبل الإستعمال تأكدي أنك قد قمت بالخطوات التالية على نحو صحيح : تثبيت الحزمة : composer require spatie/laravel-permission نشر ملفات التهجير و الإعداد : php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" تنفيذ أمر التهجير : php artisan migrate بعد ذلك نحتاج إستعمالها و ضمها للتطبيق على نحو صحيح . سنحتاج إضافة السمة HasRoles لنموذج المستخدم User.php للإستفادة من التوابع التي توفرها هاته السمة : <?php use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Permission\Traits\HasRoles; // تضمين السمة class User extends Authenticatable { use HasRoles; // إستعمال السمة // ... } 2. الان ما علينا إلا إنشاء أدوار Roles و أذونات Permissions , بحيث تتم العملية كالتالي : يتم نسب صلاحية معينة إلى دور معين . يتم نسب دور معين إلى مستخدم معين . مثال : نقوم بإنشاء الأذونات التالية : الحذف . الإضافة . التعديل . => نقوم بنسب الأذونات إلى الدور "Manager" . => نقوم بإعطاء المستخدم A الدور Manager . و بالطبع فإنه يمكن كتابة الشيفرة الخاصة بنسب الأذونات للدور و الدور للمستخدم في أي مكان من التطبيق , وليكن متحكما خاصا نسميه AssignRolesController : <?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Spatie\Permission\Models\Role; use Spatie\Permission\Models\Permission; class AssignRolesController extends Controller { public function init() { # إنشاء دور $role = Role::create(['name' => 'writer']); # إنشاء صلاحية $permission = Permission::create(['name' => 'edit articles']); # عن طريق التابعين التاليين يمكن إعطاء الدور صلاحية معينة أو إعطاء الصلاحية إلى دور # ملاحظة : يكفي إستعمال أحدهما $role->givePermissionTo($permission); $permission->assignRole($role); # إعطاء مستخدم معين الدور $user = App\Models\User::first(); $user->assignRole('writer'); } } الان ما علينا إلا الوصول للتابع init لتنفيذ الأمر و إنشاء الأدوار و الأذونات . بعد ذلك و كخطوة أخيرة سنحتاج لحماية المسارات و المتحكمات . مثال : يجب علينا عدم السماح لمن ليس له صلاحية تعديل المقالات للوصول إلى المتحكم الخاص بتعديل المقالات . سنتسعمل في ذلك مفهوم الطبقات الوسيطة Middlewares , بحيث تتولى عملية التحقق من إمتلاك المستخدم لدور أو صلاحية معينة . و أبسط طريقة لعمل ذلك هي عن طريق المثال التالي : Route::group(['middleware' => ['can:edit articles']], function () { # كل المسارات التي يتم تمريرها هنا ستكون غير قابلة للوصول إلا لمن يمتلك صلاحية تعديل المقالات }); و متى ما حاول المستخدم اللوصول إلى المتحكمات الخاصة بعملية تعديل المقالات سيتم التحقق إن كان يمتلك صلاحية التعديل , و بشكل اخر : سيتم التحقق من أن المستخدم يمتلك دورا من ضمن صلاحياته تعديل المقالات .
  25. يمكنك التعامل مع الصلاحيات في لارافل عن طريق واحدة من الحزم : laravel-permission من مجموعة spatie . bouncer من JosephSilber . entrust من Zizaco . roles من romanbican . laravel-acl من kodeine . laratrust من santigarcor . تتشابه طريقة عمل هاته الحزم في الفكرة الأساسية و تختلف من حيث بعض المميزات الإضافية . و رغم كل ذلك يمكنك التعامل مع الصلاحيات دون الإستعانة بأي حزمة عن طريق مميزات مبنية ضمن اللارافل نفسه من مثل البوابات Gates و السياسات Policies . كما أحب التعامل مع هذا المفهوم بشكل منفصل و مرن أكثر عن طريق معاملة مجموعات الصلاحيات كنموذج Model و كجدول بقواعد البيانات , ثم إنشاء طبقات وسيطة Middlewares , بناءا على هذا الأخير , تقوم بالتحقق من إمتلاك المستخدم الموثق الحالي لمجموعة صلاحيات أو لا , ثم التحقق إن كانت هاته المجموعة تمتلك صلاحية ما و هكذا .. أي أن الأمر ممكن بكل الطرق , فكلها تشترك في المفهوم الأساسي و تتفاوت فيما بينها من ناحية بعض المميزات الإضافية .
×
×
  • أضف...