لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 05/17/21 في كل الموقع
-
2 نقاط
-
السلام عليكم، بنفترض أن البيانات المرجعة من الapi الخاصة بي هي json: { "name": "Mahmoud Reda", "age": 17, "type": 1 } ولنفترض أنني لا أريد إرجاع البيانات هكذا بل أريد التعديل على type حيث إذا كان type = 0 أرجع له كلمة admin وإذا كان type = 1 أرجع له كلمة user فهل من طريقة حل؟2 نقاط
-
نعم يمكنك ذلك عن طريق الإستعانة بمفهوم المسترجعات والمعدلات (Accessors & Mutators) في لارافال . مثال عملي عن ذلك : نقوم بتعريف معدل جديد بملف مودل المستخدمين على هذا النحو : <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * Get the user's type. * * @param string $value * @return void */ public function getTypeAttribute($value) { if($value == 0 ) return 'admin'; return 'user'; } } لاحظ كيفية تعريف المعدل : get | {attr} | Attribute attr => capitialized يمكنك القراءة أكثر عن الموضوع من هنا .2 نقاط
-
تصميم واجهة المستخدم من أهم المهن المطلوبة حاليًا في سوق العمل، ولكن ما هي واجهة المستخدم؟ واجهة المستخدم هي ما نراه ونتفاعل معه على شاشات الحواسيب والأجهزة المحمولة، مثل موقع الإنترنت وتطبيقات الهاتف المحمول وتطبيقات الويب. لذلك فإن الشخص الذي يختار مواقع العناصر على الشاشة وتخطيط مختلف الصفحات والشاشات ومن يخطط أنماط ألوانها ورسوماتها، هو مصمم الواجهات، ويرتبط عمله مباشرة مع مطوّر الويب والتطبيقات كما يرتبط من جهة أخرى مع مصمم تجربة المستخدم. كيف يعمل مصمم واجهة المستخدم؟ من الصعب جدًّا على مصمم الرسوميات العمل على تصميم الواجهات منفردًا، لأن عمله مرتبط كليًا بالتنسيق مع مطوّر التطبيقات والويب، لذلك فإن الغالبية العظمى من مصممي الواجهات يعملون في فرق تضم مصمم رسوميات ومطوّر تطبيقات ومدير فريق الذي يجب أن يكون لديه إلمام بالتصميم والتطوير معًا، وقد يتضمن الفريق أفرادًا أكثر إن لزم الأمر مثل كاتب المحتوى وغيره. دورة تطوير واجهات المستخدم ابدأ عملك الحر بتطوير واجهات المواقع والمتاجر الإلكترونية فور انتهائك من الدورة اشترك الآن مراحل تصميم واجهة المستخدم يمر مشروع تصميم الواجهة بعدة مراحل وهي: يتلقى المدير طلبًا لتنفيذ مشروع واجهة تطبيق أو ويب ويحصل على كافة المعطيات والمعلومات اللازمة لبدء المشروع. يجتمع المدير بأعضاء الفريق ويطلعهم على المعطيات التي بين يديه ثم يوزع المهام على المصمم والمطور وعادة ما يبدأ المصممم العمل. يعمل المصمم على إنشاء رسومات نماذج أولية باستخدام القلم والورقة إلى أن يصل إلى نماذج مرضية لرؤيته الخاصة بالمشروع. ينقل المصمم هذه النماذج من الأوراق إلى الحاسوب ليرسم هذه النماذج بطريقة احترافية ومنسقة بأسلوب الإطار الشبكي Wireframe ثم يسلم هذه النماذج إلى المدير. ملاحظة: إن كان فريق العمل يعمل معًا في نفس المكتب فإنه يسلم هذه المخططات مباشرة، أو عن طريق إرسالها بالبريد الإلكتروني أو أية وسيلة اتصال أخرى، أو قد يلجأ الفريق للعمل معًا على أحد أدوات وتطبيقات سطح المكتب أو تطبيقات الويب المخصّصة لعمل الفرق في هذا المجال، حيث يتشارك الجميع الأفكار والتصاميم والنماذج ويعلّقون عليها ويتباحثون بأمرها، سنذكر بعضًا من هذه الأدوات والتطبيقات في الجزء الأخير من المقال. يتبادل المدير والمصمم الآراء والأفكار وتُنفّذ التعديلات ثم يرسل المدير النماذج إلى العميل ليبدي رأيه فيها ويطلب تعديلاته. يبدأ المصمم العمل على استخدام العناصر الرسومية والصور والألوان لإنشاء تصاميم رسومية أولية ثم يشاركها مع المدير الذي يرسلها بدوره للعميل لإبداء الرأي وطلب التعديلات. يعمل المصمم على التعديلات المطلوبة ويسلم التصاميم النهائية للمدير الذي يسلمها بدوره للمطور ليعمل على تطوير التطبيق أو الموقع ومن ثم يسلم المشروع إلى العميل. قواعد تصميم واجهة المستخدم لتصميم واجهات جيدة ومتميزة واحترافية نحتاج إلى اتباع قواعد معينة تضمن تألق وتميز التصميم كما تضمن سهولة استخدامه وقبوله من قبل المستخدمين. التناسق يجب استخدام نفس أنماط التصميم ونفس تسلسل الإجراءات للحالات المتماثلة، يتضمن ذلك الاستخدام الصحيح للألوان والطباعة والمصطلحات في الشاشات والأوامر والقوائم الفورية خلال رحلة المستخدم، حيث تسمح الواجهة المتسقة للمستخدمين بإكمال مهامهم وأهدافهم بسهولة أكبر. يجب أن يكون المستخدم مرتاحًا في استخدامه للواجهة ولا يشعر بالارتباك، مثلًا لا يجب وضع زر القائمة المنبثقة أسفل الواجهة بينما اعتاد المستخدمون على وجودها أعلى الواجهة، وكذلك لايجب أن يوضع زر شراء المنتج أعلى صفحة المنتج وفوق صورته والمعلومات حوله بينما اعتاد المستخدمون وجود هذا الزر أسفل هذه الواجهة، وهكذا. كما يُفضّل على الدوام استخدام الأشكال المألوفة والأزرار المألوفة أكثر من الأشكال الجديدة التي قد تشعر المستخدمين بالغرابة وتجعلهم يفكرون مرتين قبل استخدام العنصر أو النقر على الزر ، فهذا التردد ليس جيدًا بمقاييس تجربة المستخدم والتصميم السليم والصحيح لواجهة المستخدم. البساطة في جميع القواعد الخاصة بتصميم أي شيء تجد مبدأ البساطة دائمًا، لأن التصميم البسيط مريح أكثر للنظر ويساعد على إيصال الرسالة بسلاسة ووضوح وسهولة دون عناء وهو الهدف من التصميم، فلا أحد يحب الواجهات المزدحمة وغير المنتظمة التي تسبب الإرباك عند محاولة التعامل معها لعدم وضوح الرسالة المفروض إيصالها أو الهدف من التطبيق أو الموقع. فإضافة المزيد من العناصر المختلفة في التصميم سيقلل التركيز على العناصر المهمة والتي يجب أن يركّز عليها المصمم. لذلك يجب التخفيف من ازدحام العناصر وتأمين تصميم بسيط يتضمن أهم العناصر فقط والابتعاد عن العناصر الأقل أهمية والتي يمكن إبرازها في واجهات أخرى يمكن التنقل إليها من الواجهة الرئيسية. مثال: أهم ما يركز عليه موقعا ياهو وجوجل هو محرك البحث وعملية البحث، وبفضل التصميم البسيط والمختصر لجوجل فإن التركيز منصب على محرك البحث فحسب، بينما يسبب ازدحام العناصر المختلفة في واجهة ياهو تشتيت الانتباه عن العنصر الرئيسي الأهم وهو خانة البحث. تناسق الخطوط من المهم التمييز بين أنواع الخطوط الواجب استخدامها عند تصميم واجهات المستخدم، حيث أن هناك خطوطًا يمكن عرضها بوضوح ضمن واجهات الويب لسطح المكتب ولكنها صعبة القراءة وقليلة الوضوح عند استخدامها في الأحجام الصغيرة ضمن الشاشات الصغيرة للأجهزة المحمولة. لذلك يجب الانتباه واستخدام خطوط ثخينة نسبيًا في الواجهات المصممة للشاشات الكبيرة والخطوط النحيفة نسبيًا عند التصميم للشاشات الصغيرة. من أهم القواعد المتبعة في هذا السياق تجنب استخدام أكثر من نوعين من الخطوط ضمن أي واجهة لضمان تناسق وأناقة التصميم. مراعاة التصميم المتجاوب تساعد بعض برامج تصميم الواجهات على إنشاء تصاميم متجاوبة تتمتع بقابلية تغيير حجم العناصر والأجزاء الأساسية بحسب حجم الشاشة المعروض عليها التصميم، مثل حجم الشعار والقوائم والفقرات النصية وغيرها، بينما لا تتمتع برامج أخرى بهذه الميزة مثل برنامج الفوتوشوب والإليستريتور، لذلك يجب أن يخصص المصمم إما عناصر بأحجام متوسطة تراعي كافة الأحجام المحتملة أو يجب عليه أن ينشئ عدة نسخ من العناصر بأحجام مختلفة ليستخدمها المطور في برمجة الواجهة حتى تكون متجاوبة وقابلة للتكبير أو التصغير بحسب حجم شاشة العرض. التباين كثيرًا ما نرى واجهات لمواقع أو لتطبيقات لا تراعي مبدأ التباين على الاطلاق بحيث تكون الألوان بين العناصر المختلفة ولاسيما بين العناصر والخطوط ذات تباين متدني بحيث يكون من الصعب تمييز العناصر أو قراءة النصوص، وعلى العكس أيضًا أحيانا يكون التباين مبالغًا فيه ما يجعل النظر ومتابعة العناصر أو القراءة مزعجة للعين وغير مريحة، لذلك يجب أن يكون التباين متوسطًا ومدروسًا حتى يحقق تجربة مستخدم مريحة وجيدة. أحد أبرز أساليب تطبيق مبدأ التباين هو تصميم واجهة بلون واحد مع التدرجات القريبة وبالأخص اللون الرمادي وتدرجاته، ومع استخدام لون حيوي مميز للعنصر أو العناصر الأهم لتأمين بروزها مع تحقيق جمالية وأناقة في التصميم. الهرمية هو من المبادئ المهمة في التصميم عامة وكذلك تصميم الواجهات خاصة، نستطيع من خلاله توجيه عين المستخدم واهتمامه بطريقة تدريجية في الاتجاه الذي نريد، ويكون تطبيق هذا المبدأ عبر تعزيز خصائص مميزة إضافية تُبرز العنصر الأهم في الواجهة مع تخفيف نسبة التعزيز للعنصر التالي في الأهمية وهكذا، وبذلك يعلم تمامًا المستخدم كيفية التوجّه ضمن الواجهة. المحاذاة يجب تطبيق هذا المبدأ على جميع محاور وأطراف التصميم، وعلى عكس تصاميم أخرى حيث يطبق هذا المبدأ على محور واحد ويكون ذلك كافيًا، إلا أن ذلك غير كاف في تصميم الواجهات نظرًا لأن هذه الواجهات عادة ما تكون مكتظة بالعناصر بالموازنة مع تصاميم فنية أخرى، ما يستوجب تطبيق المحاذاة على مختلف المحاور والأطراف ليكون المنظر العام للتصميم متوازنًا ومتناسقًا. انظر للشكل التوضيحي السابق وستلاحظ مبدأ المحاذاة بكل وضوح. التقارب وهو أحد مبادئ التصميم العامة، حيث أن تطبيقه يحسّن تجربة المستخدم لأن تناثر العناصر ضمن الواجهة وتباعدها يؤدي لتجربة مزعجة للمستخدمين وغير فعّالة لذلك يجب تنظيم العناصر بقرب بعضها وبتسلسل مرتب حتى نؤمن تجربة سلسلة ومريحة للمستخدمين. الوضوح ويقصد هنا تأمين الوضوح في الخيارات والقرارات والمتطلبات التي يجب أن ينفذها المستخدم، فعلى سبيل المثال عندما تتواجد في صفحة التسجيل حقول إدخال عدة ويتطلب كل حقل نوعية إدخال مختلفة، يجب أن يكون واضحًا ومفهومًا للمستخدم ما يجب عليه إدخاله ضمن هذه الحقول وما هي الأخطاء التي ارتكبها أثناء عملية الإدخال حتى يتداركها ويصححها بطريقة سلسلة ومفهومة وواضحة. الصورة بواسطة Antonin Kus من موقع dribbble المساحة البيضاء حافظ على المساحات البيضاء قدر الإمكان وأكثر منها دون تردد، لأنها أثبتت فعاليتها في اجتذاب المستخدمين فهي تسبب الشعور بالراحة والرقي والأناقة وبها تتحقق مبادئ التناسق والبساطة بسهولة، لذلك تجنب استخدام المربعات والمستطيلات والخطوط التي تفصل بين العناصر قدر الإمكان واسمح للمساحات البيضاء بالسيطرة على مساحة التصميم العامة. مصدر الصورة أدوات تصميم واجهة المستخدم تقدم بعض هذه الأدوات والبرامج إمكانات متكاملة في تصميم الواجهات وبعضها يسمح بمشاركتها مباشرة مع باقي أعضاء الفريق لمناقشتها وتحديثها مباشرة، بينما البعض الآخر تقليدي للغاية حيث يجب أن تصمم الواجهات يدويًا من البداية ومن ثم إرسال النماذج إلى باقي أعضاء الفريق، وفي أحيان كثيرة يحتاج المصمم إلى استخدام أكثر من برنامج وتطبيق ومنصة لإتمام المهمة على أكمل وجه. أدوبي فوتوشوب أشهر برنامج للتصميم ومعالجة الصور وأكثرها شيوعًا، يمكن استخدامه لتصميم واجهات مواقع الويب أو حتى التطبيقات حيث يحتوي على أدوات الشرائح الخاصة بتقسيم وتقطيع التصميم إلى شرائح بحسب العناصر المرسومة، ومن ثم تصدّر هذه الشرائح إلى ملفات صور مستقلة لكل عنصر بتنسيق PNG لضمان خاصية الشفافية في حال تواجدها ضمن الشريحة المصدّرة، ليتمكن المطور من استخدام هذه العناصر معًا وتركيبها لإنشاء الواجهة أو التطبيق. ويمكن استخدامه لمعالجة الصور المستخدمة في التصميم أو لإنشاء عناصر أخرى كالأزرار أو الخلفيات أو أشكال القوائم وغيرها. أدوبي إليستريتور بسبب تخصصه في إنشاء الرسومات الشعاعية، فإنه البرنامج الأقوى والأنسب لإنشاء عناصر مميزة شعاعية متجاوبة التصميم لكل أجزاء وأنواع التصاميم مثل القوائم والأزرار والنماذج والرسوميات والأيقونات وغيرها. كما يمكن استخدامه لإنشاء تصاميم النماذج الأولية للمشاريع بتقنية الإطار الشبكي (Wireframe)، حيث تساعد أدواته القوية على إنشاء هذه التصاميم بسهولة وسرعة. Sketch سكتش برنامج مميز ومتخصص في إنشاء وتصميم الواجهات عالية الدقة بكل أنواعها ويعد من أقوى البرامج في هذا المجال، حيث يتضمن قوالب جاهزة للمساعدة في إنشاء هذه التصاميم، كما يتضمن إعدادات مخصصة جاهزة بحسب قياسات مختلف الأجهزة لتصميم التطبيقات والويب. لعل أبرز عيوبه هو أنه برنامج مخصص للعمل على نظام واحد فقط وهو ماكنتوش العامل على حواسيب آبل بينما لا تتوفر منه نسخ تعمل على ويندوز أو لينكس. Adobe X D يوفر أدوبي إكس دي أفضل بيئة للمشاريع الرقمية ضمن مجموعة Adobe Creative Cloud لأدوات تصميم الواجهات. لا تشبه واجهة هذا البرنامج واجهات بقية برامج أدوبي مثل الفوتوشوب والإليستريتور وغيرها، إلا أنك ستعتاد العمل عليه بسرعة لسهولة استخدامه ووفرة أدواته الخاصة بهذا النوع من التصاميم. Figma تمكنك فيجما من إنشاء واجهات وتصميمها بسرعة. حيث تفخر منصة Figma بكونها أداة تصميم تعاونية حيث يمكن لعدة مستخدمين العمل في وقت واحد على المشروع نفسه وهذا فعّال للغاية عندما يكون لديك العديد من أصحاب العلاقة في المشروع ذاته يشاركون في تشكيل النتيجة مثل المصممين والمطورين والمدراء، ولذلك هي أداة مثالية عندما تعمل على مشروع واحد بالاشتراك مع مصمم ومطور وكاتب محتوى في نفس الوقت. Balsamiq بالساميق أداة مميزة وقوية إنشاء نماذج الإطار الشبكي Wireframe حيث يمكنك تطوير البنية والتخطيطات لمشاريعك بسهولة، وتعمل عناصر السحب والإفلات على تسهيل الاستخدام ويمكنك ربط الأزرار بصفحات أخرى. هذا يعني أنه يمكنك البدء بسرعة في تخطيط واجهاتك ومن ثم مشاركتها مع فريقك أو عملائك. Zeplin مع أن زيبلن أداة جيدة لإنتاج النماذج الأولية، إلا أنه يناسب إلى حد كبير مرحلة ما بعد التصميم وما قبل التطوير جنبًا إلى جنب مع النماذج الأولية. يمكّنك تسليم التصميم والنماذج الأولية للمطورين والتأكد من تنفيذ أفكارك بطريقة جيدة. وتستطيع مشاركة ملفات سكتش Sketch و فوتوشوب Photoshop وملفات X D و فيجما Figma إلى زيبلن لاستحداث بيئة للمطورين والمصممين للعمل على المشروع معًا ومن ثم تسليمه دون الحاجة إلى إنشاء الإرشادات واستعمال وسائل التواصل المختلفة. InVision إن فيجين هو أداة تساعد في إنشاء واجهات تفاعلية جميلة مع مجموعة كبيرة من الميزات حيث يمكنك إنشاء حركات وانتقالات مخصصة من عدد من الإيماءات والتفاعلات. وبفضل هذه الأداة يمكنك التوقف عن التفكير في إنشاء العديد من النماذج لأجهزة متعددة لأنه يمكن تحقيق التصميم سريع الاستجابة داخل لوح رسم واحد. خاتمة على الرغم من أنه يجب عليك دائمًا اتخاذ قرارات قائمة على رؤيتك وخبرتك وذوقك الفني، إلا أن اتباع مجموعة من القواعد والإرشادات سيوجهك في الاتجاه الصحيح ويسمح لك باكتشاف مشاكل الاستخدام الرئيسية في وقت مبكر من عملية التصميم. تنطبق هذه القواعد على معظم واجهات المستخدم، كما تكفي مجموعة الأدوات التي ذكرناها لإنشاء تصاميم متكاملة على الرغم من وجود المزيد من التطبيقات والأدوات خارج هذه القائمة إلا أن ما ذكرناه في هذا المقال أكثر من كافٍ. والأهم هو التعاون بين أعضاء الفريق واتباع خطوات العمل لإتمام عملية التصميم وتسليم المشروع إلى العميل.1 نقطة
-
سلام عليكم و كل عام و انتم بخير الان انا عندي هذا الملف للاستعراض <?php session_start(); if ($_SESSION['permission'] != 1) header("location: login"); include("includes/db.php"); $title = "تعديل مورد"; $id = $_GET['id']; $q = "SELECT * FROM supplier WHERE id =".$id.";"; $res = array(); if (mysqli_multi_query($conn, $q)) { $i = 0; do { $res[$i] = array(); if ($result = mysqli_store_result($conn)) { while ($row = mysqli_fetch_assoc($result)) { array_push($res[$i], $row); } mysqli_free_result($result); } $i = $i +1; } while (mysqli_next_result($conn)); } $user = $res[0][0]; ?> <!doctype html> <html lang="ar"> <head> <?php include("includes/head.php"); ?> <body> <?php include("includes/loader.php"); ?> <div class="app-container app-theme-white body-tabs-shadow fixed-sidebar fixed-header"> <?php include("includes/app-header.php"); ?> <?php include("includes/ui-theme-settings.php"); ?> <div class="app-main"> <?php include("includes/sidebar.php"); ?> <div class="app-main__outer"> <div class="app-main__inner"> <div class="app-page-title"> <div class="page-title-wrapper"> <div class="page-title-heading"> <div> <img src="https://gtms.tk/img/supplier.png" alt="" width="90" height="80"> </div> <div>تعديل مورد</div> </div> <div class="page-title-actions"> </div> </div> </div> <form class="needs-validation" action="functions/updateSuppliers.php" novalidate> <div class="main-card mb-3 card"> <div class="card-body"> <h3 class="card-title">بيانات الشركة و المالك</h3> <div class="form-row"> <div class="col-12"> <label>إسم الشركة/المورد</label><label style="font-size: 11px; color:red;">*</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-user"></i></span> </div> <input type="text" class="form-control text-1" value="<?php echo $user['facory']; ?>" required> <div class="invalid-feedback"> الرجاء التفضل بادخال اسم الشركة/المورد </div> </div> </div> <div class="col-12"> <label>إسم صاحب الشركة</label><label style="font-size: 11px; color:red;">*</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-user"></i></span> </div> <input type="text" class="form-control text-2" value="<?php echo $user['oName']; ?>" required> <div class="invalid-feedback"> الرجاء التفضل بادخال اسم صاحب الشركة </div> </div> </div> <div class="col-12"> <label>العنوان</label><label style="font-size: 11px; color:red;">*</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-user"></i></span> </div> <textarea type="text" class="form-control text-3" required><?php echo $user['address']; ?></textarea> <div class="invalid-feedback"> الرجاء ادخال العنوان </div> </div> </div> </div> </div> </div> <div class="main-card mb-3 card"> <div class="card-body"> <h3 class="card-title">بيانات التواصل</h3> <div class="form-row"> <div class="col-6"> <label>رقم التليفون</label><label style="font-size: 11px; color:red;">*</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="tel" class="form-control text-4" value="<?= $user['phone'] ?>" required> </div> </div> <div class="col-6"> <label>رقم الواتساب</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="tel" class="form-control text-5" value="<?= $user['whatsapp'] ?>" > </div> </div> <div class="col-6"> <label>البريد الإلكترونى</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="email" class="form-control text-6" value="<?= $user['email'] ?>"> </div> </div> <div class="col-6"> <label>الويب سايت</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="url" class="form-control text-7" value="<?= $user['website'] ?>"> </div> </div> <div class="col-6"> <label>صفحة الفيسبوك</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="url" class="form-control text-8" value="<?= $user['facebook'] ?>"> </div> </div> <div class="col-6"> <label>تيليجرام</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-9" value="<?= $user['telegram'] ?>"> </div> </div> <div class="col-6"> <label>تويتر</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-10" value="<?= $user['twitter'] ?>"> </div> </div> <div class="col-6"> <label>انستجرام</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-11" value="<?= $user['instagram'] ?>"> <div class="invalid-feedback"> يرجى كتابة إسم </div> </div> </div> <div class="col-6 mt-4"> <input type="checkbox" class="a-contt" style="width: 24px;height: 24px;cursor: pointer;"> إضافة مسؤل تواصل غير المالك </div> </div> </div> </div> <div class="main-card mb-3 card acott" <?php if(!isset($user['phone2']) || $user['phone2'] == '') echo 'style="display: none;"'?> > <div class="card-body"> <h3 class="card-title">بيانات مسؤل التواصل</h3> <div class="form-row"> <div class="col-6"> <label>رقم التليفون</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-12" value="<?= $user['phone2'] ?>" > </div> </div> <div class="col-6"> <label>رقم الواتساب</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-13" value="<?= $user['whatsapp2'] ?>" > </div> </div> <div class="col-6"> <label>البريد الإلكترونى</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-14" value="<?= $user['email2'] ?>"> </div> </div> <div class="col-6"> <label>الويب سايت</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-15" value="<?= $user['website2'] ?>"> </div> </div> <div class="col-6"> <label>صفحة الفيسبوك</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-16" value="<?= $user['facebook2'] ?>"> </div> </div> <div class="col-6"> <label>تيليجرام</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-17" value="<?= $user['telegram2'] ?>" > </div> </div> <div class="col-6"> <label>تويتر</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-18" value="<?= $user['twitter2'] ?>" > </div> </div> <div class="col-6"> <label>انستجرام</label> <div class="input-group"> <div class="input-group-prepend"> <span class="input-group-text"><i class="pe-7s-map"></i></span> </div> <input type="text" class="form-control text-19" value="<?= $user['instagram2'] ?>"> <div class="invalid-feedback"> يرجى كتابة إسم </div> </div> </div> </div> </div> </div> <!-- Mohamad --> <div class="main-card mb-3 card"> <div class="card-body"> <h3 class="card-title">بنود التوريد</h3><br> <div class="form-row"> <div class="col"> <input type="checkbox" class="check-1" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sFabric'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">قماش</span> </div> <div class="col"> <input type="checkbox" class="check-2" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sAcc'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">اكسسوارات</span> </div> <div class="col"> <input type="checkbox" class="check-3" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sCarton'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">كرتون</span> </div> <div class="col"> <input type="checkbox" class="check-4" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sLine'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">خيوط</span> </div> <div class="col"> <input type="checkbox" class="check-5" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sNeedle'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">إبر حياكة</span> </div> <div class="col"> <input type="checkbox" class="check-6" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sMac'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">ماكينات</span> </div> <div class="col"> <input type="checkbox" class="check-7" style="width: 24px;height: 24px;cursor: pointer;" <?php if( $user['sBag'] == "true" ) echo 'checked'?> > <span style="vertical-align: super;">اكياس</span> </div> </div> </div> </div> <!-- Mohamad --> <div class="main-card mb-3 card"> <div class="card-body"> <h3 class="card-title">QR CODE</h3> <div class="form-row"> <div class="col text-center"> <button class="btn btn-outline-primary generate" type="button">توليد QR CODE</button> </div> <div class="col text-center"> <button class="btn btn-outline-primary file-button" type="button">إستيراد QR CODE</button> </div> <div class="col-12 text-center" id="qrcode"> <i class="fa fa-spinner fa-spin loaderQr" aria-hidden="true" style="display:none;font-size: 80px;margin-top: 41px;color: blueviolet;"></i> <img src="#" id="qr1" alt="" style="max-width: 100%;max-height: 200px;" /> </div> </div> </div> </div> <div class="form-row"> <button class="btn btn-primary center-submit" type="submit">تأكيد</button> </div> </form> </div> </div> </div> <?php include("includes/footer.php"); ?> </div> </div> </div> <input type="file" style="display: none;" class="hide-input"> <?php include("includes/js.php"); ?> <script src="./assets/scripts/jquery.classyqr.min.js"></script> <script type="text/javascript"> </script> <script> (function() { 'use strict'; window.addEventListener('load', function() { var forms = document.getElementsByClassName('needs-validation'); var validation = Array.prototype.filter.call(forms, function(form) { form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } else { var text1 = $(".text-1").val(), text2 = $(".text-2").val(), text3 = $(".text-3").val(), text4 = $(".text-4").val(), text5 = $(".text-5").val(), text6 = $(".text-6").val(), text7 = $(".text-7").val(), text8 = $(".text-8").val(), text9 = $(".text-9").val(), text10 = $(".text-10").val(), text11 = $(".text-11").val(), text12 = $(".text-12").val(), text13 = $(".text-13").val(), text14 = $(".text-14").val(), text15 = $(".text-15").val(), text16 = $(".text-16").val(), text17 = $(".text-17").val(), text18 = $(".text-18").val(), text19 = $(".text-19").val(), check1 = $(".check-1").prop("checked"), check2 = $(".check-2").prop("checked"), check3 = $(".check-3").prop("checked"), check4 = $(".check-4").prop("checked"), check5 = $(".check-5").prop("checked"), check6 = $(".check-6").prop("checked"), check7 = $(".check-7").prop("checked"), qr = $("#qr1").attr("src"); $.ajax({ url: "functions/updateSuppliers.php", dataType: 'text', data: { "type": "supp", "text1": text1, "text2": text2, "text3": text3, "text4": text4, "text5": text5, "text6": text6, "text7": text7, "text8": text8, "text9": text9, "text10": text10, "text11": text11, "text12": text12, "text13": text13, "text14": text14, "text15": text15, "text16": text16, "text17": text17, "text18": text18, "text19": text19, "check1": check1, "check2": check2, "check3": check3, "check4": check4, "check5": check5, "check6": check6, "check7": check7, "qr": qr }, type: 'post', success: function(data) { if (data == "done") { deleteCookie("text1"); deleteCookie("text2"); deleteCookie("text3"); deleteCookie("text4"); deleteCookie("text5"); deleteCookie("text6"); deleteCookie("text7"); deleteCookie("text8"); deleteCookie("text9"); deleteCookie("text10"); deleteCookie("text11"); deleteCookie("text12"); deleteCookie("text13"); deleteCookie("text14"); deleteCookie("text15"); deleteCookie("text16"); deleteCookie("text17"); deleteCookie("text18"); deleteCookie("text19"); deleteCookie("check1"); deleteCookie("check2"); deleteCookie("check3"); deleteCookie("check4"); deleteCookie("check5"); deleteCookie("check5"); deleteCookie("check6"); Swal.fire({ icon: 'success', title: 'عمل جيد ، تم التعديل بنجاح', confirmButtonText: 'اغلاق', showCloseButton: true }).then((result) => { if (result.isConfirmed) { location.reload(); } }) } else { Swal.fire({ icon: 'error', title: 'حدث خطأ حاول مجددا', confirmButtonText: 'حسنا', showCloseButton: true }); console.log(data); } } }); } form.classList.add('was-validated'); }, false); }); }, false); })(); function added() {} $(".hide-input").change(function() { if (this.files && this.files[0]) { var FR = new FileReader(); FR.addEventListener("load", function(e) { $("#qr1").attr("src", e.target.result); }); FR.readAsDataURL(this.files[0]); } }); $(".file-button").click(function() { $(".hide-input").click(); }); $(".a-contt").click(function() { if ($(this).prop("checked") == true) { $(".acott").show(); } else { $(".acott").hide(); } }); $(".generate").click(function() { var text1 = $(".text-1").val(), text2 = $(".text-2").val(), text3 = $(".text-3").val(), text4 = $(".text-4").val(), text5 = $(".text-5").val(), text6 = $(".text-6").val(), text7 = $(".text-7").val(), text8 = $(".text-8").val(), text9 = $(".text-9").val(), text10 = $(".text-10").val(), text11 = $(".text-11").val(), text12 = $(".text-12").val(), text13 = $(".text-13").val(), text14 = $(".text-14").val(), text15 = $(".text-15").val(), text16 = $(".text-16").val(), text17 = $(".text-17").val(), text18 = $(".text-18").val(), text19 = $(".text-19").val(), check1 = $(".check-1").prop("checked"), check2 = $(".check-2").prop("checked"), check3 = $(".check-3").prop("checked"), check4 = $(".check-4").prop("checked"), check5 = $(".check-5").prop("checked"), check6 = $(".check-6").prop("checked"); coname = "اسم الشركة"; owner = "إسم صاحب الشركة"; owner_contact = "✪بيانات صاحب الشركة ✪"; address = "العنوان"; owner_tel = "☏ رقم التليفون ☏"; owner_whatsapp = "رقم الواتس آب"; owner_email = "البريد الإلكتروني "; owner_website = "الويب سايت"; owner_fb = "صفحة الفيس بوك"; owner_telegtam = "التيليجرام"; owner_twitter = "تويتر"; owner_insta = "انستجرام"; /* بيانات مسئول تواصل غير المالك */ contact_contact = "✪بيانات مسئول التواصل✪"; contact_tel = "☏ رقم التليفون ☏"; contact_whatsapp = "رقم الواتس آب"; contact_email = "البريد الإلكتروني "; contact_website = "الويب سايت"; contact_fb = "صفحة الفيس بوك"; contact_telegtam = "التيليجرام"; contact_twitter = "تويتر"; contact_insta = "انستجرام"; supplier_items = "بنود التوريد"; fabric_sub = "توريد القماش"; accsessories_sub = "توريد إكسسوارات"; carton_sub = "توريد كارتون "; thread_sub = "توريد خيوط حياكة"; Needles_sub = "توريد إبر حياكة"; machines_sub = "توريد ماكينات خياطة"; $("#qr1").show(); $(".loaderQr").show(); $("#qr1").ClassyQR({ type: 'text', text: coname+ "%0A" + text1 + "%0A" + owner + "%0A" + text2 + "%0A" + address + "%0A" + text3 + "%0A" + owner_contact + "%0A" + owner_tel + "%0A" + text4 + "%0A" + owner_whatsapp + "%0A" + text5 + "%0A" + owner_email + "%0A" + text6 + "%0A" + owner_website + "%0A" + text7 + "%0A" + owner_fb + "%0A" + text8 + "%0A" + owner_telegtam + "%0A" + text9 + "%0A" + owner_twitter + "%0A" + text10 + "%0A" + owner_insta + "%0A" + text11 + "%0A" + contact_contact + "%0A" + "%0A" + contact_tel + "%0A" + text12 + "%0A" + contact_whatsapp + "%0A" + text13 + "%0A" + contact_email + "%0A" + text14 + "%0A" + contact_website + "%0A" + text15 + "%0A" + contact_fb + "%0A" + text16 + "%0A" + contact_telegtam + "%0A" + text17 + "%0A" + contact_twitter + "%0A" + text18 + "%0A" + contact_insta + "%0A" + text19 + "%0A" + supplier_items + "%0A" + fabric_sub + check1 + "%0A" + accsessories_sub + check2 + "%0A" + carton_sub + check3 + "%0A" + thread_sub + check4 + "%0A" + Needles_sub + check5 + "%0A" + machines_sub + check6 + "%0A" }); $("#qr1").show(); $(".loaderQr").hide(); }); $("input, select").on("keyup change click", function() { var text1 = $(".text-1").val(), text2 = $(".text-2").val(), text3 = $(".text-3").val(), text4 = $(".text-4").val(), text5 = $(".text-5").val(), text6 = $(".text-6").val(), text7 = $(".text-7").val(), text8 = $(".text-8").val(), text9 = $(".text-9").val(), text10 = $(".text-10").val(), text11 = $(".text-11").val(), text12 = $(".text-12").val(), text13 = $(".text-13").val(), text14 = $(".text-14").val(), text15 = $(".text-15").val(), text16 = $(".text-16").val(), text17 = $(".text-17").val(), text18 = $(".text-18").val(), text19 = $(".text-19").val(), check1 = $(".check-1").prop("checked"), check2 = $(".check-2").prop("checked"), check3 = $(".check-3").prop("checked"), check4 = $(".check-4").prop("checked"), check5 = $(".check-5").prop("checked"), check6 = $(".check-6").prop("checked"); document.cookie = "text1=" + text1 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text2=" + text2 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text3=" + text3 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text4=" + text4 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text5=" + text5 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text6=" + text6 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text7=" + text7 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text8=" + text8 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text9=" + text9 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text10=" + text10 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text11=" + text11 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text12=" + text12 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text13=" + text13 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text14=" + text14 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text15=" + text15 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text16=" + text16 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text17=" + text17 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text18=" + text18 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "text19=" + text19 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "check1=" + check1 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "check2=" + check2 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "check3=" + check3 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "check4=" + check4 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "check5=" + check5 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; document.cookie = "check6=" + check6 + ";expires=Thu, 18 Dec 2023 12:00:00 UTC;"; }); function getCookie(cname) { var name = cname + "="; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') { c = c.substring(1); } if (c.indexOf(name) == 0) { return c.substring(name.length, c.length); } } return ""; } </script> </body> </html> و ده الكود اللي المفروض اني حاطط تعليمات التحديث <?php include("../includes/db.php"); $id = $_POST['id']; $type = $_POST['type']; if ($type == "supp") { $text1 = $_POST['text1']; $text2 = $_POST['text2']; $text3 = $_POST['text3']; $text4 = $_POST['text4']; $text5 = $_POST['text5']; $text6 = $_POST['text6']; $text7 = $_POST['text7']; $text8 = $_POST['text8']; $text9 = $_POST['text9']; $text10 = $_POST['text10']; $text11 = $_POST['text11']; $text12 = $_POST['text12']; $text13 = $_POST['text13']; $text14 = $_POST['text14']; $text15 = $_POST['text15']; $text16 = $_POST['text16']; $text17 = $_POST['text17']; $text18 = $_POST['text18']; $text19 = $_POST['text19']; $check1 = $_POST['check1']; $check2 = $_POST['check2']; $check3 = $_POST['check3']; $check4 = $_POST['check4']; $check5 = $_POST['check5']; $check6 = $_POST['check6']; $check7 = $_POST['check7']; $qr = $_POST['qr']; $result = $conn->query("UPDATE supplier SET facory='$text1',oName='$text2',address='$text3',phone='$text4',whatsapp='$text5',email='$text6',website='$text7',facebook='$text8',telegram='$text9',twitter='$text10',instagram='$text11',phone2='$text12',whatsapp2='$text13',email2='$text14',website2='$text15',facebook2='$text16',telegram2='$text17',twitter2='$text18',instagram2='$text19',sFabric='$check1',sAcc='$check2',sCarton='$check3',sLine='$check4',sNeedle='$check5',sMac='$check6',sBag='$check7',qr='$qr' WHERE id='$id'"); // $result = $conn->query("INSERT INTO supplier(facory, oName, address, phone, whatsapp, email, website, facebook, telegram, twitter, instagram, phone2, whatsapp2, email2, website2, facebook2, telegram2, twitter2, instagram2, sFabric, sAcc, sCarton, sLine, sNeedle, sMac, sBag, qr) VALUES ('$text1','$text2','$text3','$text4','$text5','$text6','$text7','$text8','$text9','$text10','$text11','$text12','$text13','$text14','$text15','$text16','$text17','$text18','$text19','$check1','$check2','$check3','$check4','$check5','$check6','$check7','$qr')"); if ($result) { echo "done"; } else { echo $conn->error; } } elseif ($type == "none") { } else { echo $type; } لكني اواجه الاخطاء التالية Notice: Undefined index: id in C:\xampp\htdocs\gtms\functions\updateSuppliers.php on line 5 Notice: Undefined index: type in C:\xampp\htdocs\gtms\functions\updateSuppliers.php on line 7 الرجاء افادتي بما هو الخطأ الذي وقعت فيه مع الشكر1 نقطة
-
لقد تعلمت كل أساسيات البرمجة واساسيات البرمجة بلغة جافا وايضا جمع المكاتب المهمه فيها مثل Fx swing وioوURL ووتعلمت جميع أيضا المواضيع المتقدمه أمثلة Thread ووالوراثه وصممت بعض التطبيقات الصغيره مثل اله حاسبه علميه وبعض المشاريع الصغيره مثل برنامج تنزيل المقاطع من على المواقع واليوتيوب لكن احس اني هذا ليس بكافي لكي ابدا في تصميم برامج سطح المكتب مثلا كبرنامج إدارة الصيدليات ماذا احتاج أيضا لكي ابدا وبماذا تنصحوني1 نقطة
-
نعم الامر افضل فيه مشقه قليلا بسبب حجم التطبيق وكثرت المكتبات المستعمله ولكن الامر جيد في النهايه ويقدم تجربه ممتازه للمستخدم1 نقطة
-
هو من فتره انا ارغب بالانتقال الى فلاتر 2 ولكن متردد علشان توافق الحزم ولكن لما رغبت ارفع المشروع لك الثاني الذي في السوال المختلف وجدت الفرصه للقيام بذلك لنني سوف اكون مجبور بعد فتره على الانتقال الامر الان نجح على ما يبدو ان المشكله في حزمة ايقونة التطبيق فقط قمت بايقافها الى اشعار لاحق لا توجد مشكله واصبح المكاتب متوافقه جميعها مع العلم انني قمت بتجربة وضع any1 نقطة
-
أريد أن أنشىء زر وأعمل شرط معين داخل onPress في حالة معينة أن يصبح الزر غير قابل للضغط عليه ( يعني عند الضغط عليه لا يحدث شيء )1 نقطة
-
1 نقطة
-
1 نقطة
-
هل يوجد حل لهذا المشكلة اخي؟ Because no versions of flutter_launcher_name match >0.0.1 <0.1.0 and flutter_launcher_name 0.0.1 depends on yaml ^2.1.16, flutter_launcher_name ^0.0.1 requires yaml ^2.1.16. And because flutter_launcher_icons >=0.9.0 depends on yaml ^3.0.0-nullsafety.0, flutter_launcher_name ^0.0.1 is incompatible with flutter_launcher_icons >=0.9.0. And because flutter_launcher_icons <0.4.0 requires SDK version >=1.20.1 <2.0.0 and flutter_launcher_icons >=0.4.0 <0.7.1 depends on image ^2.0.0, if flutter_launcher_name ^0.0.1 and flutter_launcher_icons <0.7.1-∞ or >=0.9.0 then image ^2.0.0. And because image >=1.1.31 <2.0.4 depends on archive >=1.0.16 <1.1.0 and image >=2.1.14 <3.0.0-nullsafety.0 depends on archive ^2.0.0, if flutter_launcher_name ^0.0.1 and flutter_launcher_icons <0.7.1-∞ or >=0.9.0 then archive >=1.0.16 <1.1.0 or ^2.0.0 or image >=2.0.4 <2.1.14. And because image >=2.0.4 <2.1.14 depends on archive >=1.0.16 <3.0.0 and archive ^1.0.2 requires SDK version <2.0.0, if flutter_launcher_name ^0.0.1 and flutter_launcher_icons <0.7.1-∞ or >=0.9.0 then archive ^2.0.0. And because flutter_launcher_icons >=0.7.0 <0.9.0 depends on args ^1.5.0 and archive >=2.0.0 <3.0.0-nullsafety.0 depends on args ^1.4.0, if flutter_launcher_name ^0.0.1 and flutter_launcher_icons any then args ^1.4.0. And because flutter_appifjoie depends on easy_localization ^3.0.0 which depends on args ^2.0.0, flutter_launcher_name ^0.0.1 is incompatible with flutter_launcher_icons. So, because flutter_appifjoie depends on both flutter_launcher_name ^0.0.1 and flutter_launcher_icons any, version solving failed. pub get failed (1; So, because flutter_appifjoie depends on both flutter_launcher_name ^0.0.1 and flutter_launcher_icons any, version solving failed.)1 نقطة
-
هل يمكنك تجربة وضع flutter_launcher_name: git: url: https://github.com/ride4sun/flutter_launcher_name ref: "0.9.1" أو flutter_launcher_icons: any1 نقطة
-
1 نقطة
-
@بلال زيادة شاهد الان اخي اصدارات مكتبات flutter_launcher_icons flutter_launcher_name اخر اصدار ولكن غير متوافقات1 نقطة
-
1 نقطة
-
يمكنك اولا ضغط اكواد css واكواد html و اكواد جافا سكريبت و ايضا وضع كود lazy load للصور وجعل محتوى يظهر الاول بدلا من اعلانات او اي شيئ اخر ووضع اكواد جافا سكريت في اخير فوق وسم <head\> لان في من قواعد تصميم المواقع هو وضع اكواد جافا في الاخير و ايضا ضع كود معرف فايسبوك في الاخير فوق الوسم /head كما يمكنك ضغط الصور عبر موقع tinypng بدون انقاص من جودة الصورة كما يمكنك تحويل الصورة الى webp التي ينصح بها جوجل لانها جيدة في محركات البحث و سريعة التحميل.1 نقطة
-
هل يمكنك الذهاب إلى موقع pub.dev والبحث عن مكتبة flutter_launcher_icons ومن ثم تقوم بتحديثها عن طريق وضع أخر إصدار ومن ثم إخباري بالنتيجة, أو يمكنك تنفيذ الأمر التالي flutter pub upgrade1 نقطة
-
يمكنك وضع بداخل أقواس onPressed التالي onPressed: (){ if(i == 1){ return null; } return true; } أو يمكنك إنشاء متغير من نوع bool بهذا الشكل bool isButtonDisabled; وفي دالة initState نضع قيمة لهذا المتغير بهذا الشكل initState(){ isButtonDisabled = false; } وفي دالة onPressed onPressed: isButtonDisabled ? null : _myfunction(),1 نقطة
-
يمكنك اضافة كود ميتا خاصة باليكسا اعلامهم بموقع الخاص بك عبر ذهاب الى لوحة التحكم في موقع اليكسا لكن انا انصحك بعدم وضع الكود لأنهم يستعملون الكود للحصول على كيوورد الناجحة التي تجلب ترافيك لموقعك و يمكن لاشخاص اخرين يستعملونها ضدك. اليكسا تضيف ايضا موقعك بطريقة اتوماتكية وهي التي انصحك بها بمجرد حصول على زوار حوالي 5 زيارات في اليوم قم بتحميل اضافة اليكسا وبعد مرور يومين سوف تجد ترتيب موقعك.1 نقطة
-
مرحبا بك خالد شنوي تصدر محركات البحث يعتمد على عدة معايير سوف الخصها لك في هذه الفقرة القصيرة و بشكل بسيط او اذا كنت تملك دومين جديد لا يمكنك منافسة على كلمات التي لديها عدد كبير من البحث و تملك منافسة عالية في جوجل انا انصحك بالعمل على كلمات فيها زيارات قليلة و منافسة قليلة هذا افضل لك ان كنت تملك موقع جديد و يساعدك على تصدر في محرك البحث بعد مرور اسبوعين او اقل. ان جوجل تحتاج الى فترة 3 اشهر من اجل ظهور موقعك في كلمات مفتاحية التي تريد منافسة عليها . جوجل تعمتد على اثوريتي او مصداقية خاصة للمواقع وهذه يمكنك اكتسابها عبر انشاء محتوي طويل ومفيد للزائر بشكل وليس محشو بكلمات مفتاحية فقط لكي يضل الزائر اطوال مدة في موقعك وربما يشارك مقال الخاص بك في مواقع تواصل الاجتماعي. يمكنك كسب هذه المصداقية ايضا عبر حصول على باك لينك من مواقع ذات مصداقية عالية مثل ويكيبيديا و المواقع الحكومية و المواقع تعليمية التي تختص في نيش الخاص بك. اما بخصوص سيو داخل الموقع on page seo يجب ان يحتوي موقعك وصف قصير و دقيق تضع فيه كلمات المفتاحية خاصة بك. وميتا كيوورد اصبح غير مدعومة من جوجل و ان وضعت كييوورد لا تضع اكثر من 13 كلمة مفتاحية.1 نقطة
-
عذراً أخي , هل تقوم بتحديث ملفات مشروعك لتتناسب مع flutter 2 ومن ثم تقوم برفعها مرة أخرى لأنه يوجد لدي flutter 2 و الملفات ليست متوافقة معها لذلك أرجوا تحديثها لأنه لو قمت بالرجوع إلى الإصدار الغير flutter 2 سأفقد الكثير من مشاريعي لذلك يجرى تحديث مشروعك و إرفاقه مجدداً.1 نقطة
-
1 نقطة
-
يمكن أن تستخدم Laravel API Resource لإنشاء resource ويتم إنشاء ملف ExampleResource داخل مجلد app\Http\Resources php artisan make:resource ExampleResource افتح الملف وقم بعمل التعديل المطلوب <?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class ExampleResource extends JsonResource { /** * Transform the resource into an array. * * @param \Illuminate\Http\Request $request * @return array */ public function toArray($request) { return [ "id": $this->id, "name": $this->name, "age": $this->age, "type": ($this->type == 0) ? "admin" : "user" ]; } } ثم تقوم بتمرير ال object or collection ل resource // في حالة عنصر واحد return new ExampleResource(Example::findOrFail($id)); // في حالة اكتر من عنصر return ExampleResource::collection(Example::all();1 نقطة
-
يشير مصطلح "شبكة توصيل المحتوى" (CDN) إلى مجموعة من الخوادم الموزعة جغرافيًا والتي تعمل معًا لتقديم محتوى الإنترنت بسرعة. تتيح شبكة CDN النقل السريع للموارد اللازمة لتحميل محتوى الإنترنت ، بما في ذلك صفحات HTML وملفات JavaScript وأوراق الأنماط والصور ومقاطع الفيديو. تستمر شعبية خدمات CDN في النمو ، واليوم يتم توجيه غالبية حركة مرور الويب عبر هذا النوع من الشبكات ، بما في ذلك حركة المرور من المواقع الرئيسية ، مثل Facebook و Netflix و Amazon. ما هي مزايا شبكة CDN؟ تختلف فوائد استخدام CDN اعتمادًا على حجم واحتياجات خاصية الإنترنت المعينة ، ولكن يمكن تقسيم الفوائد الرئيسية لمعظم المستخدمين إلى جوانب مختلفة: - تحسين مرات تحميل الموقع : من خلال تقريب المحتوى من زوار الموقع باستخدام خادم CDN قريب (من بين التحسينات الأخرى) ، يمكن لزوار الموقع الاستفادة من أوقات التحميل الأسرع على مستوى الصفحة. نظرًا لأنه من المرجح أن يتجنب الزوار المواقع البطيئة ، فإن استخدام CDN يمكن أن يساعد في تقليل معدل الارتداد وزيادة الوقت الذي يقضونه على الموقع. بمعنى آخر ، يؤدي موقع الويب الأسرع إلى زيادة عدد الزوار ومدة الزيارة. - انخفاض تكاليف النطاق الترددي : استهلاك النطاق الترددي للاستضافة هو عنصر نفقات رئيسي لمواقع الويب. من خلال التخزين المؤقت والتحسينات الأخرى ، تمكنت شبكات CDN من تقليل كمية البيانات التي يتعين على الخادم الأصلي تقديمها ، وبالتالي تقليل تكاليف الاستضافة لمالكي مواقع الويب. زيادة توافر المحتوى : قد تؤدي زيادة عدد الزيارات أو حدوث أعطال في الأجهزة إلى تعطيل الأداء الطبيعي لموقع الويب. نظرًا لطبيعتها الموزعة ، يمكن لـ CDN التعامل مع المزيد من حركة و الضغط على الخادم الرئيسي, ما هي عيوب شبكة CDN؟ - جميع الملفات تتواجد في خادم أخر و بالتالي أي عطل أو عطب في الخادم المضيف فسيؤثر على التطبيق أو الموقع الخاص بك. بإختصار شديد شبكة CDN لا يمكن الإستغناء عنها فهي توفر لك مزايا لا يمكن لخادمك الخاص أن يوفرها لك و ستجعل موقعك أو تطبيقك أكثر سرعة وأمان,1 نقطة
-
إسمه معامل الشرط الثلاثي او ternary operator و هو موجود في معظم لغات البرمجة على ما أعتقد، في المثال الذي أرفقته فإننا نفحص حالة المشروع إن كانت تساوي واحد فإننا نعرض كلمة مكتمل أما في الحالة المعاكسة فإننا لا نعرض شيء. و هذا شرحه في موسوعة حسوب الخاص بلغة جافاسكربت و نفس الشيء في لغة php: المعامل الشرطي في JavaScript كما أنه يوجد له شرح في أحد دروس دورة php في مسار الأساسيات: العامل الثلاثي Ternary Operator1 نقطة
-
هذا الكود عبارة عن شرط if مصغرة يطلق عليها اسم Ternary Operator و تكون على هذه الصيغة (condition) ? (statment1) : (statement2); مثل <?php $i = 50; echo ($i >= 10) ? "YES" : "NO"; ?> بحيث Statement1 تنفذ إذا تحقق الشرط, وStatment2 تحقق إذا كان الشرط خطأ. و إذا أردنا تحويلها إلى if تكون بهذا الشكل <?php $i = 50; if($i >= 10){ echo "YES"; } else { echo "NO"; } ?> ويمكنك استخدامها كما تريد و تكرارها كيفما تشاء.1 نقطة
-
يمكنك أن تبني المشروع بالكامل في نفس مجلد لأن Laravel يأتي مجهزًا للتعامل مع الـ API، ويمكنك أن تقوم بعمل RESTful API من خلال عمل Routes في ملف routes/api.php بنفس الطريقة العادية كم اتقوم بها في ملف routes/web.php ويفضل أن تفصل المتحكمات controllers في مجلد داخلي باسم api ليكون في المسار التاليعلى سبيل المثال: /app/Http/Controllers/Api/UsersController.php ويمكنك تقسم الـ API إلى إصدار (V1, V2 .. إلخ) حتى إذا أردت أن تقوم بعمل تحديثات في المستقبل، تقوم بعمل إصدار جديد لذلك قم بوضع المتحكمات في مجلد باسم الإصدار أيضًا كالتالي: /app/Http/Controllers/Api/V1/UsersController.php ويمكنك أن تستخدم التابع prefix لإستخدام الإصدار في مسارات routes الـ API أيضًا كالتالي: Route::prefix('v1')->group(function () { Route::get('/users', [UsersController::class, 'index']); // http://localhost/api/v1/users Route::get('/posts', [PostsController::class, 'index']); // http://localhost/api/v1/posts });1 نقطة
-
هذا الأمر لا يقتصر على فلاتر أو غيره , فكل بوابات الدفع تقدم إما واجهة تطبيق برمجية جاهزة API أو مكتبة SDK يسهل ربطها , دمجها و التعامل معها بأي إطار عمل أو منصة أو أي لغة كانت . و إختيار بوابة الدفع عموما يكون إنطلاقا من إحتياجات أو إختيار عميلك بالدرجة الأولى , ولأسباب أخرى بدرجة ثانية (من مثل المنطقة و الدول المدعومة و العمولات المخصومة على كل تحويل و العروض المتوفرة .. إلخ ) . أما عن بوابات الدفع التي تقبل إشتراك فردي (أشخاص و شركات) لا تشترط و لا تطلب أي سجل تجاري , رقم ضريبي أو بطاقة ضريبية فنذكر من بين أفضلها : بوابة دفع بيبال Paypal, بحيث توفر SDK سهل الإستخدام و الربط و خصوصا مع لغات و منصات الواجهة الأمامية من مثل فلاتر .أؤمن أنها الأفضل في كثير في الحالات , كما توفر أيضا حساب تجريبي (sandbox account) لتجربة التطبيق على مستوى التطوير . باي فورت PayFort, وهي أحد أحد أبرز بوابات الدفع الإلكتروني الرائدة في الشرق الأوسط تم إنشاءها بالإمارات و استحوذت عليها شركة أمازون الان و قد تم تغيير إسمها إلى Amazon Payment Services, تقوم بتوفير API سهل الربط مع تطبيقك . سكريل Skrill, و هي بوابة غنية عن التعريف توفر أيضا واجهة برمجية سهلة الربط . بوابة تتو تشيك أوت 2checkout , و هي واحدة من أكثر البوابات شيوعا , توفر أيضا API سهل الإستخدام بتوثيق مفصل , (قد كنت اخترتها للعديد من العملاء ممن سبق لي التعامل معهم) . للربط مع فلاتر قد تحتاج القراءة أكثر عن قنوات المنصة .1 نقطة
-
مشكلتك يمكن أن يسببها الكثير من الأخطاء والهفوات وعادة مشكلة كهذه تكون بسبب نسيان تثبيت bootstrap نسيان تثبيت ال loaders التي تتعامل مع css في webpack.config.js نسيان تضمين الrules الخاصة بالloaders في webpack.config.js نسيان تضمين ملفات css في index.js طرق مساعدة لحل المشكلة تشغيل المشروع لرؤية ما ان تواجد خطأ تفحص مجلد dist وبالتحديد main.css ويمكن ان يكون ملف ال css الرئيسي الخاص بك اسمه مغاير لكن الكود داخله سوف يعطيك فكرة عن المشكلة1 نقطة
-
يظهر من الصورة أنك تقومين بفتح مشروع الـ webpack عن طريق ملف الـ index بداخل مجلد dist . و هذا في الغالب سيؤدي بكل مسارات الملفات من الشكل main.css/ التي قد قمت بتضمينها تظهر على هذا النحو بعد البناء : file:///main.css و بالتالي فهي غير قابلة للوصول من الأساس و لو قمت بفتح الـ console ستجدين خطأ يخبرك أن الملفات غير موجودة . فالحل هو فتح المشروع عن طريق طباعة الأمر : npm run serve الذي سيقوم بدوره بطباعة التالي : Project is running at http://localhost:9000/ webpack output is served from / Content not from webpack is served from /path/to/some/path/project/dist wait until bundle finished: / Compiled successfully. بعد البناء بنجاح يمكنك التصفح إلى المسار الموصوف على هذا النحو : http://localhost:9000/ و سيتم إظهار كل الملفات شاملة ملفات التنسيق و السكربتات بشكل صحيح . ملاحظات : في حالة ما لم يعمل الأمر بشكل صحيح و قمت بمواجهة خطأ من هذا النوع : missing script: serve فتأكدي أن تقومي بتسجيل الأمر و إضافته إلى كائن scripts بملف package.json على هذا النحو : "scripts": { "serve": "webpack serve --mode development" }, و الان يمكنك طباعة الأمر و التصفح إلى المسار الموصوف بعد نجاح البناء , و إستعراض مشروعك بشكل عادي .1 نقطة
-
دالة type تقوم بإرجاع نوع كائن ما أو متغير ما : myNumber = 5 myString = "Hello" print(type(myNumber)) # Output: int print(type(myString)) # Output: str بينما الدالة isinstance فهي "تتحقق" من أن المتغير من نوع معين وتقوم بإرجاع True أو False myNumber = 5 myString = "Hello" print(isinstance(myNumber, int)) # Output: True print(isinstance(myString, int)) # Output: False يمكن إستخدام كلا الدالتين في نفس الشيء كالتالي: myNumber = 5 if isinstance(myNumber, int): print("This is a Number") else: print("This is NOT a Number") if type(myNumber) == int: print("This is a Number") else: print("This is NOT a Number")1 نقطة
-
1 نقطة
-
يمكنك أن توقف خاصية CSRF Token على أحد المسارات من خلال الـ Middleware الخاص بذلك وهو VerifyCsrfToken، وتم تجهيزه مسبقًا بالخاصية $except لكي يتم وضع المسارات فيه بالشكل التالي: protected $except = [ '/users/*', // لكل المسارات التي تبدأ بـ users '/test' ]; كما يمكنك أن توقف ميزة CSRF لكل مسارات التطبيق بالشكل التالي: protected $except = [ '*', ]; أو من خلال ملف app/Http/Kernel.php قم بحذف الصنف التالي من web: App\Http\Middleware\VerifyCsrfToken::class تحذير هام: لا تقم أبدًا بتعطيل خاصية CSRF Token لأن هذا الأمر من الممكن أن يسمح لمهاجم إلى القيام بعمليات معينة على حساب مستخدم ما، كتحويل مبلغ مالي من موقع بنكي، أو تعديل اسم المستخدم أو حتى يمكن أن تصل لتغيير كلمة المرور.1 نقطة
-
تدعم Laravel إنشاء استثناءات لـ CSRF Token عن طريق الملف App\Http\Middleware\VerifyCsrfToken فنقوم بإضافة المسارات التي نرغب باستثنائها بشكل مصفوفة بداخل المتغير protected $except = [] //array. فمثلًا لو أردنا إضافة استثناء للمسار 127.0.0.1/demo يكون الاستثناء بهذا الشكل protected $except = [ '/demo', ]1 نقطة
-
أول قم بإنشاء مشروع React إن لم يكن لديك واحد بالفعل: npx create-react-app react-tailwindcss && cd react-tailwindcss لكي تستطيع تثبيت وإستخدام tailwind بشكل جيد وعملي سنقوم بتثبيت كل من tailwindcss و postcss-cli و autoprefixer: npm install tailwindcss postcss-cli autoprefixer -D PostCSS هي أداة لتحويل تنسيقات CSS باستخدام إضافات JS. يمكن لهذه المكونات الإضافات فحص CSS، ودعم المتغيرات وmixins، وتحويل بنية CSS الحديثة، وتصمين الصور، إلخ. بينما autoprefixer تقوم بإضافة prefix لبعض خصائص CSS لكي تدعم بعض الإصدارات القديمة من متصفحات الويب. ثم نقوم بعمل ملف tailwind config من خلال الأمر: npx tailwind init tailwind.js --full ثم سنحتاج إلى ملف postcss.config.js لضبط إعدادات postcss حتى يعمل مع tailwind: touch postcss.config.js وسنقوم بكتابة التالي فيه: const tailwindcss = require('tailwindcss'); module.exports = { plugins: [ tailwindcss('./tailwind.js'), require('autoprefixer') ], }; بعد ذلك عليك عمل ملف tailwind.css ووضعه في أي مكان تريد وضع فيه مكوانات tailwdind: @tailwind base; @tailwind components; @tailwind utilities; وإستدعائه في مكونات React أو في داخل ملف scss بشكل عادي، وستحتاج أيضًا تعديل scripts في ملف package.json: "scripts": { "start": "npm run watch:css && react-scripts start", "build": "npm run watch:css && react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "watch:css": "postcss src/assets/tailwind.css -o src/assets/main.css" } بهذا سيكون tailwind قد تم تثبيته بنجاه ويمكنك أستعمال كل classes الخاصة به. بالتوفيق.1 نقطة
-
لا يوجد عدد محدد للآسف وذلك لأن القدرة الإستعابية تختلف من شخص لآخر، فيمكن لي أنا أن أشاهد 10 فيديوهات يوميًا، ويمكن لغيري أن يشاهد 20 فيديو دون أن يتعب. لكن على العموم، يفضل ألا تغلق الدورة قبل أن تنهي مجموعة من الفيديوهات المترابطة معًا، مثلًا حاول أن تنهي كل الفيديوهات التي تتمحور حول الجمل الشرطية Conditional Statements، وذلك لكي لا تقطع حبل أفكارك وأنت تتعلم، وذلك سيفيدك أيضًا حتى تمنع التشتيت عنك، مما يؤدي إلى تحصيل أكبر للمعلومات وإنجاز الدورة بشكل أسرع. لا أنصحك بفعل هذا أبدًا، لأن حجم الفيديوهات قصير للغاية وقد يستغرق الأمر منك أكثر من سنة لفعل ذلك، حيث أن كل فيديو يكون ما بين 3:5 دقائق فقط ويكون مختص بشرح جزئية معينة. والأفضل هو أن تركز على مجموعة مترابطة من الفيديوهات كما ذكرت سابقًا، وستجد أن الأمر سهل لأن الدورة مقسمة ومنظمة بالفعل. بالتوفيق.1 نقطة
-
ليس هناك وقت محدد لإنهاء لغة أو تقنية ما، فالأمر يعتمد عليك وعلى مقدار المجهود المبذول، لكن إن أخذنا المتوسط في الحسبان فأعتقد أن ستحتاج إلى ما بين شهر إلى 3 أشهر (الوقت هنا نسبي للغاية ويختلف من شخص لآخر بفارق كبير). لكن برأي هناك أشياء أهم للتركيز عليها أكثر: لا تهم أبدًا المدة التي تقضيها في تعلم لغة أو تقنية معينة. لا تقارن نفسك بغيرك، كل منا له ظروفه الخاصة والتي تختلف من شخص لآخر. هنا أنت أشرت إلى عدد من النقاط مهمة للغاية، وهم: عدم الإستعجال والتسرع، والتمهل في فهم الأساسيات جيدًا قبل التقدم في الدورة. التطبيق العملي على ما تتعلمه من الدورة، وهذا شيء أساسي لا مفر منه، فمجرد مشاهدة الفيديوهات وفهمها لن يجعل منك محترفًا وفي الغالب ستنسى ما تعلمته في بداية الدورة عند الوصول إلى نهايتها، لذلك يجب عليك التطبيق العملي وراء المدرب وتجربة كل الإحتمالات التي تخطر على بالك أثناء التطبيق العملي. هذا سيساعدك على أتقان ما تتعلمه بشكل صحيح. التدريب بشكل يومي أمر مهم أيضًا، حيث أن عدد الفيديوهات في الدورة كبير وعليك أن تبذل كل ما بوسعك لفهم كل ما تحتويه الدورة، فمجرد مشاهدة فيديو واحد أو اثنان كل عدة أيام لن يساعدك على إنجاز مهمتك أو فهم محتوى الدورة بشكل جيد. لاحظ أن كل النقاط والنصائح السابقة عبارة عن نصائح عامة يمكن تطبيقها على كل دورة أو تقنية تحاول تعلمها، لذلك حاول أن تطبقها أثناء مرحلة التعلم الخاصة بك. بالتوفيق، تحياتي.1 نقطة
-
في بداية الطريق لا مشكلة في أن تتعلم البرمجة ولغتك الإنجليزية ليست جيدة، ففي الغالب ستجد شروحات بالغة العربية لكل الأساسيات في أي لغة برمجة أو تقنية ما، لكن بعد إتمامك لمرحلة تعلم الأساسيات والدخول في مرحلة متقدمة أكثر فستواجهة صعوبة في فهم المصطلحات (حيث أن أغلب الشروحات للتقنيات المتقدمة تكون باللغة الإنجليزية أو باللغة العربية متضمنة مصطلحات إنجليزية بطريقةٍ أو بأخرى) أو في البحث عن حل مشكلة ما تواجهك وذلك لأن كل التوثيقات documentations لكل التقنيات بلا إستثناء تكون باللغة الإنجليزية وأغلب الأحيان لا يتم دعم اللغة العربية، حتى وإن أردت أن تتواصل مع شخص أجنبي ليحاول مساعدتك في مشروع ما أو في حل مشكلة تقنية، ففي الغالب سيتحدث بالإنجليزية مها كانت دولته أو لغته الأم. والحل يكمن في تعلم الأساسيات التقنية من مصادر عربية (منصة حسوب، يوتيوب، إلخ) بجانب تعلم أساسيات اللغة الإنجليزية معًا وبشكل متوازي، وبهذه الطريقة ستتعلم أساسيات البرمجة وفي نفس الوقت ستكتسب اللغة الإنجليزية التي ستساعدك في مرحلة تعلم التقنيات المتقدمة أو فهم الشروحات الإنجليزية بشكل عام. ومع الوقت ستصل لمرحلة تمكنك من قراءة توثيق أي تقنية مهما كانت بشكل مباشر دون الإستعانة بخدمات مثل ترجمة جوجل أو البحث عن شروحات عربية لها. عليك أن تعلم أيضًا أن مرحلة تعلم اللغة الإنجليزية لن تنتهي مثلها مثل تعلم التقنيات البرمجية، فحتى الذين لديهم اللغة الإنجليزية هي اللغة الأم، يتعلمون مصطلحات تقنية جديدة كل فترة، وتستطيع تعلم مصطلحات جديدة أيضًا من خلال قراءة المقالات والتوثيقات بشكل متواصل كل فترة. بالتوفيق، تحياتي.1 نقطة
-
دالة env لن تعمل في حالة تم تخزين ملفات الـ config في الملفات المؤقتة cache. إذا كنت تستدعي env من داخل التطبيق الخاص بك، فمن المستحسن أن تقوم بإضافة هذه القيم في ملفات config واستدعاء env من هذا المكان بدلاً من ذلك. لذلك لن يعمل الأمر : php artisan config:cache بدلًا من ذلك جرب تشغل الأمر التالي: php artisan config:clear بالتوفيق.1 نقطة
-
عندما كنت اتسجل في دوره تطوير واجهات مستخدم وعندما جئت ادفع قالو لي اذا تتوفر على كوبون ضعه حيث يخفض من نسبه قيمه المشتريات فقط اريد معرفه كيف احصل على كوبون واذا كان لديه ثمن انا مستعد لدفع مقابل الحصول على كوبون1 نقطة
-
يوجد لدى كثيرين خلط بين مصطلحات متقاربة هي التعميّة Encryption، الترميز Encoding، التجزئة Hashing والتشويش Obfuscation. سيتناول هذا المقال ماهية كلّ واحد من هذه المصطلحات. الترميز يهدف الترميز إلى تحويل بياناتٍ ليصبح بإمكان أنظمة مختلفة التعامل معها بطريقة صحيحة وآمنة. على سبيل المثال: إرسال ملفات تنفيذية في بريد إلكتروني أو عرض محارف Characters خاصّة على صفحة ويب. ليس الغرض هنا إبقاءَ المعلومة سريّة بل التأكد من أن التعامل معها سيكون على النحو الأمثل. يحوّل الترميز البيانات من صيغة إلى أخرى بآلية متاحة للعموم ويمكن بالتالي عكسُ التحويل بسهولة. لا تحتاج البيانات بعد ترميزها لمفتاح سري حتى يمكن التعامل معها، إذ أن المطلوب الوحيد ليمكنَ فك الترميز هو الخوارزمية Algorithm المستخدمة فيه. أمثلة: ASCII ،Unicode، ترميز روابط URL و Base64. التعمية تُستخدَم التعميّة لتحويل صيغة البيانات بغرض إبقائها مجهولة للآخرين؛ مثلا عند إرسال رسالة إلى شخص لا تريد أن يتمكن غيره من قراءتها أو لإيصال كلمة مرور بسريّة على الإنترنت. تهدف التعمية، بدلا من التركيز على قابلية استخدام المعلومة، إلى التأكد من أنه لا يمكن لغير المصرّح لهم الاستفادة من البيانات. تحوّل التعميّة البيانات إلى صيغة أخرى لا يمكن سوى لأشخاص محدّدين فهمُها. يُستخدَم لتنفيذ التعمية مفتاح تعمية إضافة إلى خوارزمية والنص المراد تحويله. يتطلب نزعُ التعمية الحصولَ على النص المعمَّى، خوارزمية التعميّة والمفتاح السري (نفس مفتاح التعمية أو مفتاح سري آخر). أمثلة: AES ،Blowfish و RSA. التجزئة تعمل التجزئة على التأكد من سلامة البيانات Integrity، بمعنى إن حدث تعديل عليها فستستطيع معرفة ذلك. تأخذ عمليّة التجزئة مُدخَلا عشوائيا وتُنتِج سلسلة محارف ثابتة الطول لديها الخصائص التالية: نحصُل دائما على نفس النتيجة بتنفيذ العمليّة على نفس المُدخَل. لا يجوز أن تُنتج العملية نفس المُخرَج لمُدخلات متعدّدة. يجب ألا يكون بالإمكان استنتاج المُدخَل من المُخرَج. يؤدي أي تعديل على مُدخَل مّا إلى تغييرات كبيرة في نتيجة تطبيق العملية عليه. تُستخدَم التجزئة مع الاستيثاق Authentication للحصول على دليل قوي أن رسالة مّا لم يُعدَّل عليها. تتم العملية بأخذ مُدخَل معيَّن، تعميّته بمفتاح محدَّد، تجزئته بنفس المفتاح، ثم تعميّة المفتاح بالمفتاح العمومي Public key الخاص بالمرسَل إليه ثم توقيع التجزئة بالمفتاح السريّ الخاص بالمرسِل. يفتح المرسَل إليه الرسالة ثم يفكّ تعمية المفتاح المستخدَم لتعميّة الرسالة باستخدام مفتاحه السّري مما يمكّنه من الحصول على النص الأصلي للرسالة. يمكنها بعدها تجزئة الرسالة ومقارنة نتيجة التجزئة بالتجزئة الموقَّعة من المرسِل فإن حصل تطابق فهذا يعني أن الرسالة لم يُعدَّل عليها وأنها أرسلت من الشخص المُنتظَر. أمثلة: SHA-3 و MD5 (أصبح قديما) التشويش يهدف التشويش إلى جعل المعلومة أصعب فهما، لتصعُب مهاجمتها أو نسخها. من الاستخدامات الشائعة له تشويش الشفرة المصدرية لجعل تكرار منتَج معيَّن أصعب عند تطبيق الهندسة العكسية Reverse engineering عليه. من المهم ملاحظة أن التشويش ليس تحكما قويا مثل التعميّة بل مجرّد عرقلة. يمكن غالبا عكسُه، مثل ما يحدُث مع الترميز، بنفس الطريقة التي يتمّ بها. يقتصر التشويش في حالات أخرى على عمليات يدوية تأخذ الكثير من الوقت لإجرائها. يجب الانتباه أيضا إلى أنه يوجد حدّ للتشويش حسب المحتوى. عند تشويش شفرة برمجية مثلا فالحدّ هو أن نتيجة التشويش يجب أن تبقى في حدود ما يمكن للحاسوب التعامل معه وإلا فإن البرنامج سيتوقّف عن العمل. أمثلة: مشوِّش JavaScript و ProGuard. ملحوظة: ربما تتساءل متى يُستحسن استخدام التشويش بدلا من التعمية؛ والجواب هو أن التشويش يُستخدَم لجعل البيانات أصعب فهما على مستغِلّ محدَّد (شخص مّا) مع إبقائها في متناول مستغِلّ آخر (حاسوب). بالنسبة للتعميّة فيصعُب في جميع الأحوال الاستفادة من البيانات دون الحصول على المفتاح السّري. خلاصة يهدف الترميز إلى الإبقاء على قابلية استخدام البيانات، ويمكن عكسُه بنفس خوارزمية الترميز؛ أي أنه لا يحتاج لمفاتيح سرية. تُستخدَم التعمية للحفاظ على خصوصية البيانات وتتطلّب إزالةُ التعمية استخدامَ مفتاح سري. تُستخدَم التجزئة لغرض التحقق من سلامة البيانات باكتشاف وجود تعديلات تدلّ عليها مُخرجات التجزئة. يُستخدم التشويش لمنع الأشخاص من فهم معنى بيانات خصوصا شفرات برمجية للحد من إمكانية تطبيق الهندسة العكسية على برنامج أو سرقة وظائفه. ترجمة -وبتصرّف- لمقال Encoding vs. Encryption vs. Hashing vs. Obfuscation لصاحبه Daniel Miessler.1 نقطة
-
المسترجِعات Accessors والمعدِّلات Mutators في Laravel هي مجموعة دوالّ مخصّصة يعرّفها المستخدم لتهيئة خواص النماذج Models. تُستخدم المسترجعات لتهيئة خواصّ النموذج عند طلب الحصول عليها من قاعدة البيانات، بينما تُستخدَم المعدّلات لتهيئة الخواصّ قبل حفظ النموذج في القاعدة. تعريف مسترجع تُسمى الدوال المسترجعة بالصيغة ()getFooAttribute حيث Foo هو اسم الخاصيّة التي نريد تهيئتها في الدالة، مع الانتباه إلى حالة الحرف الأول من الخاصية (حرف كبير Uppercase). سيستدعي Laravel تلقائيا هذه الدالة في كلّ مرة تبحث فيها عن قيمة الخاصيّة foo. لا يقتصر استخدام المسترجعات على سلاسل المحارف، بل يمكنك استخدامها لتهيئة أي نوع من البيانات تواريخ، أثمان، …إلخ. سنفترض أن لدينا نموذجا باسم Member (عضو) يحوي الخاصيّات التاليّة: first_name last_name email password last_visit settings created_at updated_at توجد من ضمن اللائحة أعلاه بضعة خاصيّات سيكون مفيدا لنا تطبيق المسترجعات عليها. على سبيل المثال، لا يهتمّ المستخدمون كثيرا بطريقة كتابة أسمائهم، لذا يمكننا استخدام المسترجعات للتأكد من أن الأسماء تُكتب بطريقة صحيحة. يحاكي المثال التالي إضافة مستخدم لم ينتبه كثيرا لطريقة كتابة بياناته: $user = App\Member::create([ 'first_name' => 'mirza', 'last_name' => 'pasic', 'email' => 'mirza.pasic@bosnadev.com', 'password' => '!supersecretpassword!', 'last_login' => Carbon\Carbon::now(), 'settings' => ['two_factor_aut' => false, 'session_time' => 1200], 'created_at' => Carbon\Carbon::now(), 'updated_at' => Carbon\Carbon::now() ]); يمكننا استخدام المسترجعات لتهيئة مُدخلات المستخدم: use Illuminate\Database\Eloquent\Model; /** * Class Member * @package App */ class Member extends Model { /** * التأكد من تهيئة الاسم الشخصي بعد الحصول على النموذج من قاعدة البيانات * * @param $value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } /** * التأكد من تهيئة الاسم العائلي بعد الحصول على النموذج من قاعدة البيانات * * @param $value * @return string */ public function getLastNameAttribute($value) { return ucfirst($value); } } سيعمل المسترجعان getFirstNameAttribute و getLastNameAttribute على تهيئة الحقلين first_name (الاسم الشخصي) وlast_name (الاسم العائلي) على التوالي لجعل الحرف الأول في كلّ واحد منهما يُكتب كبيرا (Uppercase)، بغضّ النظر عن الطريقة التي أدخلهما بها المستخدم. يمكن أيضا استخدام المسترجعات لدمج خاصيّتين في النموذج لتكوّنا واحدة جديدة. يمكن مثلا تعريف الاسم الكامل full_name بناء على الاسم الشخصي والاسم العائلي: /** * Get members full name * * @return string */ public function getFullNameAttribute() { return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name); } ثم يمكننا استخدامه كما لو كان فعلا يوجد حقل باسم full_name في النموذج: $member = App\Member::find(1); echo $member->full_name; يمكنك إن أردت استخدام المسترجعات على أنواع بيانات أخرى. مثلا، لتهيئة التاريخ. نستخدم في المثال التالي الدالة getLastLoginAttribute لتهيئة تاريخ آخر دخول (الحقل last_login) بحيث يظهر بالصيغة d.m.Y (يمثّل الحرف d اليوم، الحرفm الشهر وY السنة مكتوبة بأربعة أرقام): /** * Custom format for the last login date * * @param $value * @return string */ public function getLastLoginAttribute($value) { return \Carbon\Carbon::parse($value)->format('d.m.Y.'); } ثم نستخدم الحقل last_login كما في المثال التالي: $member = App\Member::find(1); echo $member->last_login; يظهر الحقل كما يلي: 11.07.2016. تعريف معدل تشبه آلية تسميّة المعدِّل تعريفَ المسترجع، مع فرق إحلال set مكان get. إذا أردنا تعريف معدِّل للخاصيّة foo فسيكون اسمُه setFooAttribute. نعود لمثال النموذج Member السابق. نريد الآن أن نتأكد من تهيئة اسم العضو قبل حفظ النموذج في قاعدة البيانات: /** * التأكد من تهيئة الاسم الشخصي **قبل** حفظ النموذج * * @param $value * @return string */ public function setFirstNameAttribute($value) { $this->attributes['first_name'] = ucfirst($value); } /** * التأكد من تهيئة الاسم العائلي **قبل** حفظ النموذج * * @param $value * @return string */ public function setLastNameAttribute($value) { $this->attributes['last_name'] = ucfirst($value); } ربما لاحظت أن الدالة لا ترجِع أية قيمة. ما يحدُث هو أننا نضبُط الخاصيّة بالقيمة التي نريد مباشرة. نتأكد بهذه الطريقة أن الاسمين الشّخصي والعائلي سيكونان مهيأيْن دائما بالصيغة التي نريد. أمثلة على المسترجعات والمعدلات رأينا في الفقرات السابقة أمثلة لاستخدامات سهلة للمسترجعات والمعدّلات؛ إلا أن هذه الدوال يمكن أن تُستخدَم لأمور أكثر تخصيصا كما سنرى في الأمثلة التالية. حماية كلمات السّر يمكن استخدام المعدِّلات لتجزئة كلمة السّر Password hashing قبل حفظها في قاعدة البيانات؛ مثلا: public function setPasswordAttribute($value) { $this->attributes['password'] = Hash::make($value); } تتأكد بهذه الطريقة أن كلمة السّر لن تُحفَظ أبدا بصيغتها المقروءة في قاعدة البيانات، وهو ما يعدّ إجراء أمنيًّا أساسيا. استخدمنا في المثال السابق صنف Hash الذي يوفّره Laravel مبدئيا، ولكن يمكنك استخدام دوال تعميّة إن أردت، مثل ()bcrypt. الترميز بصيغة Json إن نظرت إلى نموذج Member السابق فستجد أنه يحوي خاصيّة باسم settings تُستخدَم لحفظ تفضيلات العضو الشخصيّة وخيارات أخرى يتيحها التطبيق. يمكن استخدام مصفوفة لإدارة هذه الخيارات وحفظها في قاعدة البيانات بصيغة Json. تتيح قواعد بيانات مثل PostgreSQL نوع البيانات Json في حقول الجدول منذ زمن، كما أن MySQL أتاحت نوع البيانات هذا في الإصدار 5.7.8. ملحوظة: دعم نوع البيانات Json في MySQL لا زال في بداياته، وقد تواجه مشاكل عند استخدامه. بالنسبة لخاصيّة settings فسنحتاج لمعدِّل يخزّن البيانات بصيغة Json في القاعدة ومسترجِع لتحويل Json إلى مصفوفة من سلسلة محارف: /** * Make sure that we get an array from JSON string * * @param $value * @return array */ public function getSettingsAttribute($value) { return json_decode($value, true); } /** * Encode an array to a JSON string * * @param $value */ public function setSettingsAttribute($value) { $this->attributes['settings'] = json_encode($value); } المثال كاملا في ما يلي الخطوات اللازمة لإنشاء مثال عملي يعتمد على النموذج المقدّم في هذا الدرس. نفترض وجود Laravel مثبّت بقاعدة بيانات مضبوطة. إنشاء التهجير والنموذج php artisan make:model Member -m Model created successfully. Created Migration: 2016_07_04_020531_create_members_table التعديل على التهجير public function up() { Schema::create('members', function (Blueprint $table) { $table->increments('id'); $table->string('first_name'); $table->string('last_name'); $table->string('email'); $table->string('password'); $table->date('last_login'); $table->string('settings'); $table->timestamps(); }); } التعديل على النموذج في ما يلي الشفرة الكاملة للنموذج Member مع المسترجعات والمعدِّلات. <?php namespace App; use Illuminate\Support\Facades\Hash; use Illuminate\Database\Eloquent\Model; /** * Class Member * @package App */ class Member extends Model { /** * @var array */ protected $fillable = ['first_name', 'last_name', 'email', 'password', 'last_login', 'settings', 'created_at', 'updated_at']; /** * التأكد من تهيئة الاسم الشخصي بعد الحصول على النموذج من قاعدة البيانات * * @param $value * @return string */ public function getFirstNameAttribute($value) { return ucfirst($value); } /** * التأكد من تهيئة الاسم العائلي بعد الحصول على النموذج من قاعدة البيانات * * @param $value * @return string */ public function getLastNameAttribute($value) { return ucfirst($value); } /** * الاسم الكامل للعضو * * @return string */ public function getFullNameAttribute() { return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name); } /** * تهيئة تاريخ آخر زيارة * * @param $value * @return string */ public function getLastLoginAttribute($value) { return \Carbon\Carbon::parse($value)->format('d.m.Y.'); } /** * التأكد من تهيئة الاسم الشخصي **قبل** حفظ النموذج * * @param $value * @return string */ public function setFirstNameAttribute($value) { $this->attributes['first_name'] = ucfirst($value); } /** * التأكد من تهيئة الاسم العائلي **قبل** حفظ النموذج * * @param $value * @return string */ public function setLastNameAttribute($value) { $this->attributes['last_name'] = ucfirst($value); } /** * تهيئة كلمة السّر **قبل** حفظها * * @param $value */ public function setPasswordAttribute($value) { $this->attributes['password'] = Hash::make($value); } /** * الحصول على مصفوفة من حقل بصيغة * Json * * @param $value * @return array */ public function getSettingsAttribute($value) { return json_decode($value, true); } /** * الترميز بصيغة * Json * قبل حفظ الحقل * @param $value */ public function setSettingsAttribute($value) { $this->attributes['settings'] = json_encode($value); } } استخدام النموذج Route::get('members', function() { $user = App\Member::create([ 'first_name' => 'mirza', 'last_name' => 'pasic', 'email' => 'mirza.pasic@bosnadev.com', 'password' => '!supersecretpassword!', 'last_login' => Carbon\Carbon::now(), 'settings' => ['two_factor_aut' => true, 'session_time' => 1200], 'created_at' => Carbon\Carbon::now(), 'updated_at' => Carbon\Carbon::now() ]); $member = App\Member::find(1); echo $member->last_login . '<br>'; echo $member->full_name . '<br>'; }); ترجمة -وبتصرّف- للمقال Laravel Accessors and Mutators لصاحبه Mirza Pasic.1 نقطة