-
المساهمات
5196 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
52
إجابات الأسئلة
-
إجابة Adnane Kadri سؤال في ظهور محتوى وسم meta الوصف في رأس الصفحة كنص في المتصفح كانت الإجابة المقبولة
قد أحسنت , هاته الطريقة عملية جدا . وذلك لكون هاته المعلومات معلومات وصفية . أي أنها لا يجدر أن تظهر في الصفحة و إنما لأغراض أخرى مثل تحسين محركات البحث أو تحسين الظهور .
فعوضا عن طباعة HTML يقترح فلترة المحتوى و استخراج النصوص من محتوى الـ html فقط .
خصوصا في حالات من مثل الحاجة إلى هذا الحقل في أغراض أخرى , مثال :
وجود حقل واحد للمقالة و لوصف صفحة المقالة في جدول المقالات في قواعد البيانات . أي أن كل محتوى كالتالي :
<p style="text-align:center;"> هاته فقرة تخص وصف الصفحة </p> <h2> هذا عنوان يخص وصف الصفحة أيضا</h2> يصبح :
هاته فقرة تخص وصف الصفحة هذا عنوان يخص وصف الصفحة أيضا ليمكن إستيعابها في الخاصية content كالتالي :
<meta name="description" content=" هاته فقرة تخص وصف الصفحة هذا عنوان يخص وصف الصفحة أيضا" > مما يعني أنه هذا لن يسبب المشكلة السابقة .
يمكنك إنشاء دالة للفلترة و تحويل كل محتوى html إلى محتوى نصي بمنطق مشابه :
$text = '<p style="text-align"> هاته فقرة </p> <h2> هذا عنوان </h2>'; $cleaner_input = strip_tags($text); echo $cleaner_input; وهو نفس ما اقترحته سابقا .
-
إجابة Adnane Kadri سؤال في خطأ 403 Forbidden في التعامل مع LARAVEL API كانت الإجابة المقبولة
في الغالب و بشكل عام , يعني هذا الخطأ أنه قد تم حظر عنوان IP الذي تتصل منه بواسطة إحدى خدمات الأمان للخادم الذي ترسل إليه طلبات الـ Http . و ليس المقصود بحظر عنوان IP الخاص بك حظره هو ذاته بالضرورة , بل قد يكون الحظر شمل عناوين ذات البلد مثلا .
مثال : إذا كنت تتصل من شبكة مشتركة ، تكون فيها البنية التحتية للإنترنت أقل تطورًا ، فإن عناوين IP نادرة (من المرجح أن يشاركها الكثير من الأشخاص) ، فهذا يمكن أن يزيد من احتمالية رؤية هذا الخطأ .
في هاته الحالة ، كإقتراح على ما يمكنك فعله هو محاولة الاتصال من شبكة أخرى مؤقتًا .
أما و بشكل خاص , فستحتاج البحث في توثيق الواجهة البرمجية التي تتصل بها على دلالية كود الخطأ 1003 و إصلاح المشكلة بعد تحديدها , فقد يحتمل مثلا أن بيانات المصادقة التي تستعملها قد استهلكت .
-
إجابة Adnane Kadri سؤال في حذف الصور التي ليس لها اسم مخزن في قاعدة البيانات بواسطة php كانت الإجابة المقبولة
يمكنك جعل العملية ديناميكية و منطقية أكثر كالتالي :
يتم حذف الصورة القديمة لكل مستخدم قبل تغيير صورته في حالة ارساله لطلب . فلو كانت شيفرة تحديث صورة مستخدم ما كالتالي : $target_dir = "uploads/profile"; $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); $imageFileType = pathinfo($target_file,PATHINFO_EXTENSION); if(isset($_POST["change_pic"])) { move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file); $sql = "UPDATE users SET image_profile_path = '".$_FILES['fileToUpload']['name']."' WHERE id = '" .$targetUser. "'"; $check = $conn->query($sql); } سيجب إضافة شيفرة الحذف كالتالي : $target_dir = "uploads/profile"; $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); $imageFileType = pathinfo($target_file,PATHINFO_EXTENSION); $oldImgPath = "SELECT image_profile_path from users WHERE id = '".$targetUser."'"; if(isset($_POST["change_pic"])) { move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file); $sql = "UPDATE users SET image_profile_path = '".$_FILES['fileToUpload']['name']."' WHERE id = '" .$targetUser. "'"; $check = $conn->query($sql); if($check){ unlink($oldImgPath); } } و بالطبع يمكنك تخصيص الشيفرة أكثر , سيحل هذا مشكلة الإحتفاظ بالصور في حالة تعديلها .
لكن سيبقى مشكل توفر صور لا فائدة منها . و لتفادي هذا المشكل يمكننا إنشاء شيفرة تنفذ مرة واحدة و تحذف بعد ذلك ( one-time excutable code ) , ستتبع الشيفرة المنطق التالي :
تحديد كامل مسارات الصور من قواعد البيانات من الجدول المستهدف و تخزينها في مصفوفة . تحديد كامل مسارات الصور داخل المجلد المستهدف و تخزينها في مصفوفة . تحديد العناصر الغير متوفرة في كلتا المصفوفتين . حذفها هاته العناصر . يترجم إلى :
// تحديد كامل مسارات الصور من قواعد البيانات من الجدول المستهدف و تخزينها في مصفوفة . $res = mysql_query('SELECT img_profile_path from users'); $db_imgs = []; while($row = mysql_fetch_array($res)) { $db_imgs[] = $row['img_profile_path']; } // تحديد كامل مسارات الصور داخل المجلد المستهدف و تخزينها في مصفوفة . $stored_imgs = glob($targetDirectory . "*.jpg"); // تحديد العناصر الغير متوفرة في كلتا المصفوفتين . $targetImages = array_merge(array_diff($db_imgs, $stored_imgs), array_diff($stored_imgs, $db_imgs)); // حذفها هاته العناصر foreach($targetImages as $image) { unlink($image); } يجب التأكد من تمليك الملف الحاوي لهاته الشيفرة الأذونات اللازمة لذلك , كما أنه يجب حذفها نهائيا بعد تنفيذها .
-
إجابة Adnane Kadri سؤال في لماذا نستخدم CROSS JOIN في SQL؟ كانت الإجابة المقبولة
يستعمل الـ CROSS JOIN عادة لإنشاء ,إنطلاقا من جدولين, توليفة مزدوجة من كل صف من الجدول الأول مع كل صف من الجدول الثاني .
أي إن كان الجدول الأول يحوي المعلومات :
+++++++++++ |STUDENTS | |---------| |AHMED | |OMAR | |YOUNESS | +++++++++++ و الجدول الثاني المعلومات :
+++++++++++ |CARS | |---------| |BMW | |MERCEDES | |HONDA | +++++++++++ فإن إستعمال الـ CROSS JOIN الذي سيقوم بتشكيل :
سطر لأحمد بمحاذاة سطر BMW . // // // // MERCEDES . // // // // HONDA . و أيضا :
سطر لعمر بمحاذاة سطر BMW . // // // // MERCEDES . // // // // HONDA . و أيضا :
سطر ليونس بمحاذاة سطر BMW . // // // // MERCEDES . // // // // HONDA . بمعنى أنه سيتبع منطقا كالتالي :
/ BMW / |OMAR ---- MERCEDES \ \ HONDA / BMW / |AHMED --- MERCEDES \ \ HONDA / BMW / |YOUNESS --- MERCEDES \ \ HONDA لينتج لنا مجموعة النتائج التالية :
++++++++++++++++++++++ |STUDENTS | CARS | |---------|----------| |AHMED |BMW | |AHMED |MERCEDES | |AHMED |HONDA | | | | |OMAR |BMW | |OMAR |MERCEDES | |OMAR |HONDA | | | | |YOUNESS |BMW | |YOUNESS |MERCEDES | |YOUNESS |HONDA | ++++++++++++++++++++++ يشبه هذا جداء مجموع في الجبر , إذ يتم إستعمال النشر المزدوج كطريقة لتحليل عبارة جبرية تتضمن جداء مجموع , مثال :
(a + c )( b + d ) = ab + ad + cb + cd سوى أن النتائج في الـ CROSS JOIN يتم نشرها كصفوف بنتيجة الإستعلام .
السياق العام لها هو ما كالتالي :
SELECT ColumnName_1, ColumnName_2, ColumnName_N FROM [Table_1] CROSS JOIN [Table_2] أو يكفي :
SELECT ColumnName_1, ColumnName_2, ColumnName_N FROM [Table_1],[Table_2] و يتم استخدامه بغرض إنشاء مجموعة من كافة مجموعات العناصر بجدول ما بقاعدة البيانات ، مثل تشكيل مجموعات منازل ذات ألوان و أحجام معينة , هذا مع إمكانية التحكم في عناصر هاته المجموعات لونا أو حجما :
select size, color from sizes CROSS JOIN colors ++++++++++++++++++++++ |SIZE | COLOR | |---------|----------| |XS |RED | |XS |BLUE | |XS |GREY | | | | |XM |RED | |XM |BLUE | |XM |GREY | | | | |XL |RED | |XL |GREY | |XL |BLUE | ++++++++++++++++++++++ فلو أردنا مثلا إستثناء المنازل الحمراء , فسنتثني اللون الأحمر فقط ليتم إستثناء كل التوليفات المشكلة من حجم X و لون أحمر .. : و هكذا .
أو ربما تريد جدولاً يحتوي على صف لكل دقيقة في اليوم ، وتريد استخدامه للتحقق من تنفيذ إجراء ما كل دقيقة ، لذلك يمكنك تجاوز ثلاثة جداول :
select hour, minute from hours CROSS JOIN minutes ++++++++++++++++++++++ |HOUR | MINUTE | |---------|----------| |13:00 |00 | |13:00 |01 | |13:00 |02 | |13:00 |03 | . . . . . . |21:00 |55 | |21:00 |56 | |21:00 |57 | |21:00 |58 | . . . . . . ++++++++++++++++++++++ فهو يخلق مجموعة إحتمالات غير مكررة ,بإعتبار أن الأعمدة تحمل قيما فريدة, إبتداءا من مجموعات محدودة من العناصر . يمكن أن يكون هذا عمليا جدا في عمليات مثل إختبار التطبيق أو بذر قواعد البيانات ببيانات تجريبية .
-
إجابة Adnane Kadri سؤال في ال views أو العروض في SQL كانت الإجابة المقبولة
الـ views أو العروض في SQL هي نوع من الجداول الافتراضية . تحتوي على صفوف وأعمدة مثلها مثل الجداول الحقيقية في SQL . بحيث يمكننا إنشاء العروض عن طريق تحديد حقول معينة من جدول واحد أو أكثر موجود في قاعدة البيانات الخاصة بنا .
و لفهمها أكثر لنقم بفهم المثال التالي :
ليكن لدينا جدول تفاصيل الطلاب students_details التالي :
و ليكن لدينا جدول علامات الطلاب students_marks كالتالي :
و لنقل أننا نريد إنشاء طريقة نقوم من خلالها بقراءة علامات الطلبة Mark و عناوينهم Address .
واحدة من السبل لذلك هي في إنشاء العروض أو الـ Views .بحيث توفر تلخيصا لذلك في جدول افتراضي و لنقل أنه جدول بإسم students_extra_details .
يمكننا إنشاء عرض ما باستخدام التعليمة CREATE VIEW مباشرة .بحيث يمكن إنشاء طريقة عرض إما من جدول واحد أو من عدة جداول بسياق عام كالتالي :
CREATE VIEW view_name AS SELECT column1, column2..... FROM table1_name,table2_name , table3_name.... WHERE condition;
أي :
CREATE VIEW students_extra_details AS SELECT student_details.NAME, student_details.ADDRESS, student_marks.MARKS FROM student_details, student_marks WHERE student_details.NAME = student_marks.NAME; في ذاكرة الـ SQL قد تم إنشاء هاته الـ view كجدول افتراضي , يمكن معاملته كأي جدول SQL اخر . بشكل يبدوا كالتالي :
الان لن نحتاج إلا لمعاملتها كجدول عادي تماما , فإستعلام القراءة SELECT مثلا يكون كالتالي :
SELECT * FROM students_extra_details; و هكذا ..
وراء ما يخفيه هذا الإستعمال المميزات و الفوائد التالية :
الأمان و التغليف : بحيث يمكن إتاحة العروض للمستخدمين بينما لا يمكن الوصول إلى الجداول الأساسية بشكل مباشر . مما يعطي المستخدمين البيانات التي يحتاجون إليها فقط ، مع حماية البيانات الأخرى في نفس الجدول , لإستعمالها كشروط أو أغراض أخرى . كما أنها تعتبر طبقة تجريدية أو abstraction layer ، وهي تفعل ما تفعله أي طبقة تجريد جيدة ، بما في ذلك تغليف مخطط قاعدة البيانات وحمايتك من أية عواقب تنتج عن كون هيكلية قواعد البيانات مكشوفة . البساطة و الدلالية: يمكن استخدام العروض لإخفاء الاستعلامات المعقدة مثل إستعلامات الـ JOIN , فما الذي يبدوا أبسط برأيك , إنشاء طريقة عرض شاملة لكامل إستعمالاتك في التطبيق أم كتابة إستعلام JOIN كل مرة تحتاج القراءة من جدولين وفق شرط ما ؟ .. كما يمكن استخدامها لتوفير أسماء مستعارة بسيطة لأسماء الأعمدة لجعلها أكثر قابلية للتذكر أو دلالية ذات مغزى . مساحة تخزين بسيطة : بحيث تأخذ مساحة صغيرة جدًا للتخزين , فقاعدة البيانات تحتوي على تعريف العرض فقط ، وليس نسخة من جميع البيانات التي تقدمها و هذا شيء يقوم بإختصار الكثير . يمكنك القراءة أكثر عن العروض في سلسلة sql للمحترفين - مواضيع متفرقة في SQL .
-
إجابة Adnane Kadri سؤال في كيف احصل على ملفات PSD لتصميمات جاهزة كانت الإجابة المقبولة
أقوم عادة بإستعمال واحد من هاته المواقع :
موقع 365psd : بوصول وطريقة تحميل سهلة سريعة . موقع dribbble : القوالب التي يحتويها أحسن جودة ,و تحتاج فيه فتح حساب , و نادرا ما تجد المجاني منها . فأغلب القوالب المتوفرة مدفوعة . موقع freepik : يقوم بدمج الاثنين السابقين معا , إذ أن الوصول و التحميل سهل و سريع , يتوفر على المجاني و المدفوع بنظام فلترة . بجانب :
موقعي pngtree و unsplash الغنيين عن التعريف . موقع freepsdfiles . -
إجابة Adnane Kadri سؤال في مقارنة بين إستخدام قواعد بيانات sql وقواعد بيانات nosql كانت الإجابة المقبولة
لنقم أولا بفهم كل منهما كالتالي :
NoSQL هو نظام قواعد بيانات غير علائقي يقوم بتوفير آلية لتخزين واسترجاع البيانات التي تم تصميمها بتقنيات أو طرق غير العلاقات المجدولة المستخدمة في قواعد البيانات العلائقية مثل الشائع استعمالها في SQL .
SQL , ترجمة عن Structured Query Language , لغة الاستعلامات البنائية (أو البنيوية) . هي لغة برمجة غير اجرائية تستخدم في مضمونها مفاهيم مثل العلاقات و الفهرسة .
فكلاهما لغتان برمجيتان غير إجرائيتين ، أي أنهما يختلفان عن لغات البرمجة المعتادة مثل C ، فهي لغات متخصصة للتعامل والتحكم مع قواعد البيانات المترابطة من خلال التعامل مع تراكيب البيانات وإجراء عمليات إدخال البيانات والحذف والفرز والبحث والتصفية والتعديل و غيره .
و نلقم بتلخيص الفروقات التالية بينهما كالتالي :
من حيث نموذج تخزين البيانات Data storage model : فـ SQL تعتمد جداول بأعمدة و صفوف ثابتة و مرنة , على عكس NoSql التي تستعمل مفاهيم أخرى مثل مفتاح - قيمة (Key - Value NoSQL Database) , الجدول الكبير (Big table) و غيرها .. من حيث الهدف من إنشاء كل منهما . فـ SQL أنشئت للغرض العام , في حين أن NoSql تستوعب كميات كبيرة من البيانات مع استعلامات بحث بسيطة ،أو مع أنماط استعلام يمكن التنبؤ بها . من حيث السهولة و السرعة : تعتبر NoSql أسهل منطقا و تجريدا و تعاملا و أسرع مقارنة بـ SQL . من حيث التوسع : تتطلب منك معظم قواعد بيانات SQL التوسع عموديًا ( مثل الإضطرار إلى الانتقال إلى خادم أكبر وأكثر تكلفة) عندما تتجاوز متطلبات السعة لخادمك الحالي . على العكس من ذلك ، تسمح لك معظم قواعد بيانات NoSQL بالتوسع أفقيًا ، مما يعني أنه يمكنك إضافة خوادم سلعة أرخص كلما احتجت إلى ذلك .
من حيث الإستعمال : تعتبر SQL أفضل بكثير في جانب تنظيم البيانات ,فلو كانت بياناتك منظمة للغاية ، ولا تتغير بنية أو تركيبا بشكل متكرر فـ SQL أفضل بكثير . على عكس NoSql التي يكون استعمالها شائع من حيث التعامل مع البيانات غير المهيكلة أو شبه المنظمة التي لا تتناسب مع النموذج العلائقي الذي تستعمله SQL .
من ناحية الأمان : يعتبر الكثير SQL أكثر أمانا , و أفضل حلا عندما يتطلب الأمر درجة عالية من سلامة البيانات وأمانها .
يمكنك القراءة أكثر عن شرح الفروقات بين قواعد بيانات SQL ونظيراتها NoSQL .
كما قد تحتاج الإطلاع أكثر عن NoSQL مقابل SQL و حالات إستخدام كل واحد منهما .
-
إجابة Adnane Kadri سؤال في ربط جدولين في SQL مع عمل استعلام فرعي كانت الإجابة المقبولة
لنقم بتفكيك الإستعلام لفهمه أولا :
نحتاج تحديد معرف الشركة التي لها أكبر عدد موظفين سابق , و ذلك عن طريق قراءة أكثر قيمة معروفة أو مكررة في جدول الموظفين people . يترجم إلى : SELECT PREV_COMPANY_ID FROM people GROUP BY PREV_COMPANY_ID ORDER BY COUNT(PREV_COMPANY_ID) DESC LIMIT 1;
بناء على نتيجة الإستعلام السابق , نحتاج تحديد وجلب معلومات هاته الشركة , و يكون ذلك عن طريق القراءة من جدول الشركات companies :
SELECT * FROM companies WHERE id = TARGET_RESULTED_ID حيث أن القيمة TARGET_RESULTED_ID هي القيمة الناتجة عن الإستعلام السابق .
ثم بمساعدة الإستعلام الفرعي أو الـ sub Query لنقم بدمجهما معا ليكونا على النحو التالي :
SELECT * FROM companies WHERE id = ( SELECT company_id FROM people GROUP BY company_id ORDER BY COUNT(company_id) DESC LIMIT 1 )
و ما سيقوم به هذا الإستعلام هو ببساطة كالتالي :
جلب معلومات الشركة التي معرفها يساوي ( أكثر معرف شركة مكرر في جدول الموظفين ) . و بعبارة أخرى :
-
إجابة Adnane Kadri سؤال في مفهوم التغليف Encapsulation في البرمجة الشيئية OOP في PHP كانت الإجابة المقبولة
و عليكم السلام و رحمة الله تعالى و بركاته .
لنقم بفهم التغليف كالتالي :
التغليف ترجمة عن encapsulation هو ميكانيزمة و طريقة لحماية الخواص و التوابع التابعة لصنف ما من التعديل المباشر عليها مع إمكانية إستعمال تابع معين للصنف لتعديل ذلك . و لكن ما الذي يعنيه ذلك ؟ لنأخذ التالي لفهم الحاجة من التغليف أساسا :
تقوم شركات صنع سيارات بتوفير مقود في سياراتها كآلة للتحكم في إتجاهات سير السيارة , و من جانب اخر تقوم بإخفاء التعقيد وراء هاته العملية . أي أنها تقوم بتغليف و تغطية كل ما يتعلق بكيفية سيرها و توفير طريقة بسيطة لتغيير خاصية الإتجاه في السيارة . فهل يبدوا من المنطقي أن نقوم بتوصيل سلك بسلك أو تطبيق قوة ميكانيكية كل مرة نريد فيها تغيير اتجاه سيارة ؟
نفس الشيء ينطبق على التغليف في البرمجة الشيئية , فتغيير الخاصية مباشرة لا يكون سليما أحيانا , و قد يتعلق بمنطق عمل توابع أخرى تتأثر بتغير قيمة هاته الخاصية . و لكن تغييرها عن طريق توفير تابع يقوم بتحمل و اعتبار تبعات هذا التعديل حل نهائي للمشكلة .
مثال عملي :
ليكن الصنف DBInteract , المسؤول عن التفاعل مع قاعدة البيانات عن طريق عمليات CRUD العادية كالتالي :
class DBInteract{ public $db_password = '68426123'; public $db_username = 'root'; public $db_name = 'my-db'; public function insert(string $table ,array $data) { } public function update(string $table ,array $data) { } public function delete(string $table) { } public function select(string $table ,array $rows) { } } و لنفرض أن كل من التوابع المعرفة تحمل شيفرات يمكن فهم وظيفتها عن طريق اسماءها الدلالية .
و لنقل أننا نحتاج إدراج مهمة جديدة بجدول tasks في قاعدة البيانات بإسم my-db .
أي أن العملية ستكون كالتالي :
$db_class = new DBInteract(); $db_class->insert('tasks' ,$data); و منطقي هو أن التابع insert المسؤول عن عملية الإنشاء سيقوم بإستعمال الخواص التالية لمصادقة إتصاله مع قواعد البيانات :
public $db_password = '68426123'; public $db_username = 'root'; public $db_name = 'my-db'; المشكلة هنا , هي أن هاته الخواص قابلة للوصول بشكل عادي عن طريق إستدعاء مباشر من أي كائن عن الصنف DBInteract . فلو أن مستخدما ما لصنفنا الجاهز DBInteract قام بتغيير الخاصية db_name بعد عشرات من إستعلامات الإنشاء و القراءة و الحذف و التعديل بمجرد سطر واحد :
$db_class->db_name = 'new-db-name'; و لنقل أن بيانات المصادقة تحتاج فحصا قبل إعادة التعيين مثل أن يكون اسم قاعدة بياناتنا سلسلة نصية , و اسم مستخدمنا ليس قيمة فارغة , و كلمة سرنا تشكيلة أرقام .
في حالة تعطل ذلك سيخل هذا بعمل كل من التوابع insert , update , delete , select . و هو ما لا نريده طبعا .
و لحل المشكل لن نقوم إلا بتغليف هاته الخواص بإستعمال الكلمة المفتاحية private و إنشاء تابع جديد يمكننا من تغيير بيانات المصادقة هاته بطريقة سليمة لا تؤثر على عمل باقي التوابع . و ليكن مثلا :
class DBInteract{ private $db_password = '68426123'; private $db_username = 'root'; private $db_name = 'my-db'; public function changeCreds($pass , $un , $db) { if(is_string($db) && is_numeric($pass) && !is_null($un)){ $this->db_password = $pass; $this->db_username = $un; $this->db_name = $db; } } public function insert(string $table ,array $data) { } public function update(string $table ,array $data) { } public function delete(string $table) { } public function select(string $table ,array $rows) { } } الان لو حاول شخص ما تغيير أحد بيانات المصادقة عن طريق مباشرة فهو لن يستطيع , و ستظهر له رسالة تخبره بذلك :
cannot access private property و قس على ذلك العديد من الأمثلة و الوضعيات الأخرى التي تكون فكرة التغليف حلا فيها .
-
إجابة Adnane Kadri سؤال في لما يستخدم بعض الناس flex-grow مع flex-basis في CSS؟ كانت الإجابة المقبولة
لنقم بإقتباس التعريفين التالين من ويكي حسوب كالتالي :
و لنفترض أن حجم حاوية ما لدينا هو 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 . -
إجابة Adnane Kadri سؤال في ما الذي يعنيه transform-style: preserve-3d في CSS كانت الإجابة المقبولة
و عليكم السلام .
قبل التعرض للقيم التي تأخذها الخاصية ينبغي أولا معرفة ما الذي تقوم به الخاصية , فالخاصية tranfrom-style أو نمط التحويل تحدد ما إذا كانت العناصر الفرعية أو الأبناء لعنصر ما موضوعة في مساحة ثلاثية الأبعاد أو إذا تم وضعها في مستوى العنصر الأب نفسه .
أي أن الخاصية ممكن لها أن تأخذ أحد القيمتين :
flat : يعني هذا أن العناصر الأبناء لعنصر ما يمتلك هاته الخاصية سيتم وضعها في نفس مستوى العنصر .
preserve-3d : ترجمة للـحفاظ على البعد الثلاثي , و تجعل هاته القيمة الأبناء موضوعة في مساحة ثلاثية الأبعاد خاصة بها .
و لإتضاح الفرق جيدا لاحظ الفرق بين الصورتين :
الصورة رقم 1 :
الصورة رقم 2 :
لاحظ في كلتا الصورة أن العنصر الأب parent باللون البرتقالي يمتلك تحويلا معينا يعطيه الإنحناءة ثلاثية الأبعاد التي هو عليها , و مثل ما هو الحال مع محاور ذات العنصر , أي أن المحاور أيضا أعيد تعيينها بعد تطبيق التحويل الذي عليه .
في الصورة الأولى : نلاحظ إنتماء العنصر الابن باللون الزهري إلى مستوى عنصر الأب , أي أن العنصر يظهر بشكل وكأنه مواز له , و لكنه في الحقيقة على ذات المستوى , كأن الأمر يجرد هكذا : في الصورة الثانية : نلاحظ تداخل العنصر الاابن باللون الزهري مع العنصر الأب , يظهر ذلك و كأن كل منهما مرسوم ومعبر عنه في مستوى خاص به , هذا المستوى هو مساحة ثلاثية الأبعاد خاصة به . و كأن الأمر هكذا : ففي الأولى : العناصر الأبناء للعنصر الحالي ستكون مسطحةً (flattened) في مستوى العنصر الأب . أي أن العنصر الأب يمتلك القيمة flat في خاصية نمط العنصر .
و في الثانية : العناصر الأبناء للعنصر الحالي ستكون موجودةً في الفضاء ثلاثي الأبعاد الخاص بها . أي أن العنصر الأب يمتلك القيمة preserve-3d في خاصية نمط التحويل . و هو ما سؤالك حوله بالضبط .
يمكن تلخيص قواعد الـ css لكل من المثالين كالتالي :
صورة 1 :
transform-style: flat; صورة 2 :
transform-style: preserve-3d; تعرف أكثر على الخاصية transform-style من هنا .
كما يمكنك الإطلاع على المثال الذي تم طرحه و التلاعب بقيم الخاصية من هنا .
-
إجابة Adnane Kadri سؤال في تشغيل برنامج xampp في لينكس كانت الإجابة المقبولة
يمكنك تشغيل الأمر التالي مباشرة :
/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 # عمل اختبار تحقق سريع
-
إجابة Adnane Kadri سؤال في ما الفرق بين الـ websocket و الـ ajax و أيهما أفضل ؟ كانت الإجابة المقبولة
و عليكم السلام و رحمة الله
لا أظن أن يجب عليك تعلم إحداها فقط دون الأخرى , بل كلاهما . و هذا لأن لكل منها مجاله التخصصي و إستعمالاته و حاجته التي دعت إلى إنشاءه من الأساس , فالمقارنة بينهما غير منطقية .
و لنأخذ كل منهما على حدة كالتالي :
يستخدم Ajax بروتوكول HTTP ويمكنه إرسال طلبات باستخدام طرق POST و GET بين العميل والخادم. WebSocket هو بروتوكول اتصال بين العميل والخادم ، وهو يختلف عن HTTP . ففي Ajax ، عندما ترسل طلبًا ، يرسل الخادم استجابة لهذا الطلب ويتم إنهاء الاتصال , و هذا ما يجعله مناسبا لإستعمالات من مثل : التواصل مع واجهات تطبيق برمجية . أي أنه يسمح لتطبيق ما ,من جانب العميل, بطلب الوصول إلى مورد من جانب الخادم (مثلا : طلب صفحة أو صورة أو ملف أو بيانات) .
في حين أن باستخدام WebSockets عند إنشاء اتصال بالخادم ، يمكنك التواصل بقدر ما تريد بين العميل والخادم والحفاظ على الاتصال نشطًا في كل لحظة , و هذا يجعله مناسبا للإستعمالات من مثل : تلقي إشعارات الوقت الفعلي أو الدردشة الحية , مثل الإشعار الذي تلقيته بشأن إجابة عن سؤالك هذا .
يمكن تلخيص الأمر بشكل بسيط كالتالي :
ما وراء الـ AJAX يعتمد إتصالا يتم إغلاقه مباشرة بعد الرد . ما وراء الـ WebSocket يعتمد إتصالا متواصلا . أمثلة توضيحية :
يحتاج العميل " أحمد " تفحص صورة من على الخادم , فيقوم بإرسال طلب GET إلى الخادم . يستقبل الخادم الطلب و يقوم بإعادة رد برابط الصورة ليقوم أحمد برؤيتها , و ينتهي الإتصال و يتوقف الخادم عن تبادل أية بيانات بينه و بين أحمد , و سيحتاج أحمد اتصالا جديدا كل مرة يريد فيها طلب شيء من على الخادم .
الان , العميل " أحمد " على موقع دردشة , ينتظر أي رسائل تصله . في مقابل أن العميل " عماد " يريد مراسلة " أحمد " . يقوم أحمد بإنشاء إتصال عن طريق بروتوكول ويب سوكيت بينه و بين الخادم , و ما إن وصلت أي رسائل جديدة لأحمد للخادم سيتم تنبيهه فورا . بعد أن يكتب عماد الرسالة و يرسلها , سيلتقط الخادم طلبه و يخزن الرسالة و يقوم فورا بتنبيه أحمد بذلك , فيكتب ردا و هكذا .
أي أن من غير المعقول أن يشغل دور أحد الثاني , فلكل منهما منطقه الذي يتعامل به , فكل إستعمال لأحدهما في مجاله ميزة , و أي إستعمال له في غير تخصصه و مجاله عيب و هكذا .
أما كاقتراح و تفضيل , فأفضل أن تتعلم Ajax أولا , كونه ما ستحتاج إليه طوال مسارك . ثم في وقت لاحق , قد تدعوك الحاجة إلى تعلم websocket لتحقيق أغراض أو حالات إستعمال معينة . و هو في الغالب ما كان مسار أي مطور .
يمكنك تصفح إجابات مختلفة لتعاريف حول ما هو الـ websocket و لما قد نحتاجه هنا .
كما قد تحتاج الإطلاع على كيفية التعامل مع ajax في الـ jQuery هنا .
-
إجابة Adnane Kadri سؤال في سؤال عن store في vuex وحمايته كانت الإجابة المقبولة
المستخدم الذي قام بالتلاعب بقيمة المتغير المؤثرة في شروط عرض مكونات معينة لن يكون تعديل شيفرة المراقبة و إعادة التحميل مشكلة بالنسبة له .
كما أن هاته الحالات خاصة جدا , فعوام المستخدمين لا يفكرون بنفس الطريقة . و حتى إن كان و تم الوصول لذلك بأية طريقة كانت , لن يكون من عرض قالب فارغ جدوى من الأساس .
أي أن الأهم من كل ذلك : مصادقة طلبات جلب البيانات قبل عرضها , و يكون كل هذا في الواجهة الخلفية بعيدا عن المستخدم .
كما أن هذا لا يمنعك من ضبط طريقة التصفح و منع عوام المستخدمين من الوصول إلى صفحات ليست لهم صلاحية الوصول إلى البيانات التي تعرض بهاته المكونات , و يكون ذلك بالتوجيه إلى صفحات عامة أو قابلة للوصول من أي كان في حالة إرسال طلب من مكون خاص لا يمكن لمستخدم عام تصفحه .
-
إجابة Adnane Kadri سؤال في مشكلة في استدعاء قيمة من قاعدة البيانات كانت الإجابة المقبولة
المشكلة الوحيدة لديك هي أن قاعدة البيانات التي تحاول القراءة من عليها فارغة , فمن المنطقي أن لا يتم الإنطلاق في الدور 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 .
-
إجابة Adnane Kadri سؤال في حل مشكلة عدم إرسال رسالة إلى بريد إلكتروني من خلال الدالة mail في php كانت الإجابة المقبولة
هلا تأكدت من أن مزود الاستضافة الخاص بك يسمح لك بإرسال رسائل البريد الإلكتروني ولا يحد من إرسال رسائل البريد الإلكتروني ؟ و ذلك لأن العديد من مضيفات الويب المشتركة ، وخاصة موفري الاستضافة المجانية ، إما لا تسمح بإرسال رسائل البريد الإلكتروني من خوادمها أو تحد من العدد الذي يمكن إرساله خلال أي فترة زمنية معينة .
و قد تحتاج إلى التواصل مع فريق دعمهم للتحقق مما إذا كانت هناك أي قيود مفروضة على إرسال رسائل البريد الإلكتروني أو لا . في مثل هاته الحالات يلحظ سلوك مشابه لدالة 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 .
-
إجابة Adnane Kadri سؤال في كيف تحول laravel public channel ل private channel كانت الإجابة المقبولة
يجب أولا فهم الغرض من القنوات الخاصة أساسا , فالقنوات الخاصة في الويب سوكيت وجدت للتحقق ما ان كان سيسمح للمستخدمين بالاستماع إلى هاته القنوات الخاصة أو لا , و ذلك بالإعتماد على شروط تتوفر فيمن يقوم بطلب الإستماع مثلا أو أية شروط أخرى .
يتم تحديد قواعد ترخيص القناة الخاصة هاته بنا في ملف :
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() }}', } } }); بعد ذلك ستعمل القنوات الخاصة وفق المطلوب .
-
إجابة Adnane Kadri سؤال في بعد ما اتخرج من دورة تطوير واجهات المستخدم هل سأصبح (مبرمج او مطور او مصمم) مواقع وما الفرق بينهما؟ كانت الإجابة المقبولة
بإنهائك لدورة تطوير واجهات المستخدم ستصبح مطور واجهات مستخدم , و هذا لأنك ستتعرف على كل من :
مفهوم الواجهة الأماميّة للموقع front-end وكيفية عملها . أساسيات لغات تطوير واجهات المستخدم: HTML و CSS و JavaScript .
استخدام أحدث أدوات التطوير: Bootstrap 4 و jQuery و Sass .
التعامل مع خدمة استضافة المشاريع البرمجية GitHub و GitLab .
نشر صفحات الموقع على الإنترنت .
إعداد هيكل الموقع ووضع خطة العمل .
التصميم المتجاوب مع مختلف الأجهزة والشاشات .
و مطور واجهة المستخدم هو المسمى الوظيفي لمن يكون مسؤولا عن بناء الموقع من الجانب الشكلي العام من هيكلية و تصميم و تفاعلية . يشمل هذا المسمى الوظيفي الفروع التالية : البرمجة بإستخدام الجافاسكربت و أدواتها , و تصميم الويب بإستخدام الـ css و أدواتها .
أي أن التعبير مطور واجهات مستخدم وفق المقدم في دورة واجهات المستخدم يتضمن صفتي " مبرمج " و " مصمم " معا .
و للتفصيل أكثر يمكن تعريف كل منهم وفق التعريفات التالية :
مصمم الويب : يهتم بالتصميم الخارجي للموقع . مبرمج الويب : الشخص المفوض إليه عمليات التكويد و كتابة الشيفرة , له إمكانية كتابة أكواد و خوارزميات أكثر تعقيدا , لا يعير إهتمام لشخص المستخدم أو تجربته . مطور الويب : إهتمامه أكثر بتجربة المستخدم نحو التطبيق المفوض إليه , معرفته بالمستخدم أكثر و بالتكويد و التعقيد أقل عادة .
-
إجابة Adnane Kadri سؤال في كيف يمكن حجب مستخدمي IE من تصفح الموقع كانت الإجابة المقبولة
يمكنك إستخدام ما يعرف بالتعليقات الشرطية لحجب المحتوى أو عرض رسالة معينة بناءا على متصفح المستخدم في أي صفحة أو مكون , و كونك تستخدم تطبيق 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>
-
إجابة Adnane Kadri سؤال في متى نستخدم وسم <div> ؟ كانت الإجابة المقبولة
قبل التحدث عن وسم 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 : هنا .
-
إجابة Adnane Kadri سؤال في ما الفرق بين devDependencies و peerDependencies في node.js كانت الإجابة المقبولة
لنقم بتناول الأمر بشكل عام على هذا النحو :
الـ 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) . و لكن يبقى منطقها و تقسيمها سواءا مهما اختلف كل ذلك .
-
إجابة Adnane Kadri سؤال في أريد إستعمال دوال جافاسكربت أو الـ Regex لتحويل تواريخ من مثل "Tue Aug 31 2021 14:29:37 GMT+0200 (EET)” إلى “2021-08-31” كانت الإجابة المقبولة
يمكنك إستخدام الكائن 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 في جافاسكربت هنا و هنا .
-
إجابة Adnane Kadri سؤال في تفريغ المحتوى بعد الارسال الى قاعدة البيانات javascript كانت الإجابة المقبولة
عذرا , قد ورد خطأ في الكود هنا بالضبط :
$('#messages_form_groups').insertBefore(newEmptyImg); فالمفروض أن يقوم هذا بـ تضمين العنصر الجديد قبل العنصر بالمعرف messages_form_groups , و هو ما نحتاجه و صوابه :
$(newEmptyImg).insertBefore('#messages_form_groups'); قم باستبدال الخطأ بصوابه و أخبرني بالنتيجة
-
إجابة Adnane Kadri سؤال في مجاوره شكل لنص (تصميم الويب) كانت الإجابة المقبولة
لتوسيط الصورة يمكنك تعديل محاذاة العنصر الحاوي لعنصر الصورة ليحمل قيمة المحاذاة إلى الوسط :
.img-container{ text-align: center; } و لعمل عرض شرائح سنحتاج إنشاء حاوي لعناصر الشرائح و أزرار جانبية لكل من التالي و السابق و بعض عناصر التصفح تكون على شكل نقط و دوائر , ستكون بنية الـ html على نحو مشابه :
<!-- حاوي عرض الشرائح --> <div class="slideshow-container"> <!-- الشرائح --> <div class="mySlides fade"> <img src="img1.jpg" style="width:100%"> </div> <div class="mySlides fade"> <img src="img2.jpg" style="width:100%"> </div> <div class="mySlides fade"> <img src="img3.jpg" style="width:100%"> </div> <!-- أزرار التالي و السسابق --> <a class="prev" onclick="plusSlides(-1)">❮</a> <a class="next" onclick="plusSlides(1)">❯</a> </div> <br> <!-- دوائر التصفح --> <div style="text-align:center"> <span class="dot" onclick="currentSlide(1)"></span> <span class="dot" onclick="currentSlide(2)"></span> <span class="dot" onclick="currentSlide(3)"></span> </div> سنحتاج لإضافة بعض الـتنسيقات :
/* حاوي عرض الشرائح */ .slideshow-container { max-width: 1000px; position: relative; margin: auto; } /* نححتاج إخفاء الصور في الحالة الافتراضية */ .mySlides { display: none; } /* أزرار التالي و السابق */ .prev, .next { cursor: pointer; position: absolute; top: 50%; width: auto; margin-top: -22px; padding: 16px; color: white; font-weight: bold; font-size: 18px; transition: 0.6s ease; border-radius: 0 3px 3px 0; user-select: none; } /* تحديد زر التالي ليظهر بيمين الصفحة */ .next { right: 0; border-radius: 3px 0 0 3px; } /* المؤشرات */ .dot { cursor: pointer; height: 15px; width: 15px; margin: 0 2px; background-color: #bbb; border-radius: 50%; display: inline-block; transition: background-color 0.6s ease; } /* انيميشن */ .fade { -webkit-animation-name: fade; -webkit-animation-duration: 1.5s; animation-name: fade; animation-duration: 1.5s; } @-webkit-keyframes fade { from {opacity: .4} to {opacity: 1} } @keyframes fade { from {opacity: .4} to {opacity: 1} } الان لن يظهر أي شيء لأن كل الشرائح مخفية افتراضا , و لعمل التفاعلية سنحتاج تطبيق المنطق التالي وفق الجافاسكربت :
عند الضغط عن زر التالي سنقوم بتحديد الشريحة الما بعد الشريحة الحالية و إظهارها . عند الضغط عن زر السابق سنقوم بتحديد الشريحة الما قبل الشريحة الحالية و إظهارها . و سنستعمل فيهما دالة plusSlide لنقوم بتمرير رقم 1 معبرا عن التالي , و 1- معبرا عن السابق .
عند الضغط عن دائرة سنقوم بتحديد الشريحة المرافقة لها و إظهارها . و سنستعمل في هذا دالة currentSlide لنقوم بتمرير الرقم الترتيبي للشريحة المراد تفعيلها .
و لإظهار الشريحة لن نحتاج إلا لـ :
تحديد الرقم الترتيبي للشريحة المراد تفعيلها . إخفاء كامل الشرائح عن طريق إعطاءهم القيمة none في الخاصية display . إظهار الشريحة المفعلة عن طريق إعطاءها القيمة block في الخاصية display . فيكون كود الجافاسكربت كالتالي :
var slideIndex = 1; // الشريحة الحالية showSlides(slideIndex); // إستدعاء الدالة المسؤولة عن عرض الشرائح // الدالة الخاصة بأزرار التالي و السابق function plusSlides(n) { showSlides(slideIndex += n); } // الدالة الخاصة برموز الاتجاهات function currentSlide(n) { showSlides(slideIndex = n); } // الدالة المسؤولة عن عرض الشرائح function showSlides(n) { var i; var slides = document.getElementsByClassName("mySlides"); // تحديد كامل الشرائح var dots = document.getElementsByClassName("dot"); // تحديد كامل الدوائر if (n > slides.length) {slideIndex = 1} // تحديد الشريحة الاولى كمفعلة if (n < 1) {slideIndex = slides.length} // تحديد الشريحة الأخيرة كمفعلة for (i = 0; i < slides.length; i++) { slides[i].style.display = "none"; // إخفاء كامل الشرائح } slides[slideIndex-1].style.display = "block"; // تعديل تنسيق الشريحة المفعلة } و بالطبع فإن هذا هو المنطق البسيط للعملية , يمكنك تخصيص بنية الـ html و تنسيقها و تفاعليتها بكل حرية .
-
إجابة Adnane Kadri سؤال في اريد طريقة جلب الصفحة في ال controller بإستخدام Auth::user كانت الإجابة المقبولة
يمكنك إستعمال التابع where لتحديد شرط التساوي بين الرقم الوزاري للمستخدم الحالي و الموظفين من جدول الموظفين :
$no_ministry = Auth::user()->no_ministry; $selectemployees = Employee::select('id' , 'id_no' , 'name' , 'no_ministry' , 'staff' , 'phone') ->where('no_ministry' ,$no_ministry) ->get();