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

El Sayed El Tohamy

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

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

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

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

    1

كل منشورات العضو El Sayed El Tohamy

  1. هل يمكنك توضيح سؤالك أكثر؟ كذلك يفضل كتابة الشفرات داخل محرر الشفرات حتى تسهل قراءتها ومساعدتك.
  2. حتى تكون الأمور واضحة بالنسبة لك، يجب معرفة أن التطبيق نفسه منفصل تمامًا عن قواعد البيانات، بمعنى أن التطبيق له ملفاته الخاصة مكتوب بها شفرات برمجية، أما قواعد البيانات فهي عبارة عن ملفات مختلفة تمامًا عن التطبيق تُستخدم لحفظ البيانات. لذلك معظم التطبيقات - إن لم يكن كلها - تستطيع التعامل مع جميع أنواع قواعد البيانات. بناء عليه، يمكنك تطوير تطبيق (سواء للهاتف أو الويب أو حتى سطح المكتب)، ويمكنك ربطه بأي قواعد بيانات. هذه القواعد قد تكون: - محلية: أي يتم تثبيتها على نفس الجهاز وبالتالي تستهلك من مساحة التخزين على الجهاز وبالتأكيد محدودة بإمكانيات وسرعة الجهاز. - سحابية: موجودة على خادم ويمكن للتطبيقات الاتصال بها، لذلك يتطلب الأمر وجود اتصال بالإنترنت (إلا إذا كانت على خادم شبكة محلية). القواعد السحابية لها فائدة عظيمة جدًا: وهي أنه يمكنك الاتصال بها من أنواع تطبيقات مختلفة، لأننا كما قلنا: "قواعد البيانات شئ، والتطبيق شئ آخر"، لذلك يمكن لتطبيق الويب الاتصال بقواعد البيانات، وإذا لديك تطبيق هاتف محمول يمكنه أيضًا الاتصال بنفس قواعد البيانات، فتستطيع إدخال البيانات عن طريق أي تطبيق منهم. الرائع في الأمر أنك إذا فتحت التطبيق الآخر سترى ما تم إدخاله عن طريق التطبيق الأول.
  3. أحب أن أطمئنك، الكلام الذي سمعته غير دقيق (ورغم ذلك يجب وضعه في الحسبان)، لأن أدوات الذكاء الاصطناعي مثلها مثل أي أداة ظهرت، تخدم المجال وتوجد وظائف جديدة ربما لم تكن موجودة قبل ذلك، ولكن في المقابل تتطلب زيادة مهارة الشخص ليستطيع العمل مع الآلة الجديدة. أعطيك مثالاً: الجرار الزراعي، هل تسبب في اختفاء مهنة المزارع؟ بالتأكيد لا، ولكنه تتطلب أن يتعلم المزارع قيادة الجرار، وزاد من إنتاجية المزارع وساعد في إنماء الاقتصاد. بل وظهرت مهن جديدة لم تكن معروفة مثل الميكانيكي، وكهربائي السيارات، وعامل محطة الوقود، وتاجر قطع غيار الجرار. وقس على هذا جميع المهن، مثل ظهور ماكينات النسيج الآلية، وماكينات الطباعة الآلية وغيرها الكثير. وبالمثل في مجال تطوير الواجهة الأمامية، ربما يساعدك الذكاء الاصطناعي في أداء مهامك بشكل أسرع وأكثر احترافية، لكنه لن يستبدلك أو يحل محلك لأن هناك لمسات بشرية لا يمكن للذكاء الاصطناعي تعويضها مثل اللمسات الجمالية والإحساس بالآخرين وثقافاتهم ورغباتهم، إضافة إلى أن الكثير من الناس يريدون التعامل مع مبرمج بشري وليس آلة يطلب منه الأشياء فينفذها بدون نقاش كأنه صخرة صماء. تحذير هام: هذا لا يعني أن تتكاسل عن تحصيل العلم ومتابعة التطورات الجديدة، فرغم كل ما ذكرته لك وطمأنتك به، إلا أن ظهور الذكاء الاصطناعي ربما يقلل فعلأ من بعض فرص العمل، لذلك إذا أردت أن تحصل على وظيفة لابد أن تكون مميزًا ومؤهلاً لهذه الوظيفة ومحترفًا أكثر من غيرك حتى تجد لك مكانًا وسط العالم الذي يجري بسرعات فلكية ترهق الجميع.
  4. أهنئك على اجتهادك ومحاولاتك، وكلها صحيحة بفضل الله مع بعض الملاحظات البسيطة. الاستعلام الأول والثاني سليم تمامًا لا ملاحظات عليه الاستعلام الثالث بالفعل يعرض المنتجات على حسب أفضلية المبيعات، إلا إنه يعرض جميع المنتجات في حين نحن نريد عرض أول خمس منتجات فقط لذلك هناك إضافة بسيطة جدًا وهي limit 5 بآخر الاستعلام select product_name, quantity, price, (quantity*price) as total_price from master..Products, orders where Products.product_id = orders.product_id order by quantity desc limit 5 الاستعلام صحيح مائة بالمائة. أما بخصوص الاستعلام الرابع نحن نريد استخراج السنة والشهر من التاريخ، لأنه سيتم التجميع بناء عليهم وليس على التاريخ كله SELECT YEAR(order_date) AS SalesYear, MONTH(order_date) AS SalesMonth, SUM(Price) AS TotalSales FROM Sales GROUP BY YEAR(order_date), MONTH(order_date) ORDER BY YEAR(order_date), MONTH(order_date)
  5. تسلسل الخطوات مضبوط، أحييك على تفكيرك المنطقي، ولكن يوجد خطأ بسيط وهو في الجملة الشرطية حيث يجب إزالة علامة = وذلك لأننا لا نريد استبعاد الصفر حيث أن مضروب الصفر يساوي 1 ليصير الأمر if (n < 0) وكذلك نقل أمر الطباعة خارج الحلقة التكرارية، لأننا نريد طباعة الناتج النهائي وليس الناتج بعد كل عملية ضرب، بالإضافة إلى أنه لن يتم الطباعة في حال n = 0 for (int i = 1; i <= n; i++) { sum = sum * i; } Console.WriteLine(sum);
  6. ملحوظة: يرجى كتابة عنوان واضح حتى تعم الفائدة على الجميع. بخصوص استخدام لغة البايثون من خلال الجافاسكريبت، فيمكن ذلك عن طريق إنشاء واجهات برمجية التطبيقات APIs ثم استدعاؤها من خلال الجافاسكريبت، وفي الحقيقة هذا يتم مع كل لغات البرمجة وليس مع البايثون فقط. ووجهة برمجة التطيبقات API هي عبارة عن وظائف يتم كتابتها بلغة برمجة معينة على الخادم، ثم تهيئتها لتكون متاحة لاستدعائها بواسطة أي لغة أخرى. بالنسبة لبايثون، فإن أطر عمل مثل الفلاسك والجانجو Flask & Django يوفران بيئة تطوير جاهزة تُمكن المبرمج من البدء في كتابة الواجهات البرمجية بكل سهولة ويسر.
  7. هذا السؤال هام لأقصى درجة، فمن خلال التصميم يتم تحديد صلاحيات المستخدمين والتحكم بها، وفي الواقع إجابة هذا السؤال تحتاج إلى مجلدات حيث أن الموضوع لا يقتصر على تصميم قواعد البيانات فحسب، وإنما أيضًا معرفة تامة بالصلاحيات واختياراتها وما الاختيار الافتراضي وأشياء كثيرة تخص استيثاق المستخدمين Authentication وصلاحياتهم Authorization لتصميم صلاحيات المستخدمين يمكن اتباع عدة استراتيجيات منها ما هو بسيط الذي يغطي الاحتياجات الأساسية لإدارة المستخدمين وصلاحياتهم، ومنها ما هو معقد جدًا ولكنه يشمل على خصائص وخيارات كثيرة. سأشرح لك الأسلوب البسيط لأنه يطابق المخطط الموضح بالسؤال: عند تصميم التطبيقات متعددة المستخدمين، يجب تحديد صلاحيات كل مستخدم وبالمنطق ستكون العلاقة متعدد إلى متعدد Many-to-Many لأن كل مستخدم ربما يكون له أكثر من صلاحية، وكذلك الصلاحية ربما تُعطى لأكثر من مستخدم، لذلك يتوجب وجود جدول وسيط “Junction Table” أو “Intermediate Table”، وفيه يتم ذكر معرف المستخدم userID وأمامه معرف الخدمة المسموحة له serviceID ويمكن تكرار نفس المستخدم مع أكثر من خدمة. الآن نفترض أن جدول المستخدمين به 3 مستخدمين، وجدول الخدمات به 5 خدمات فيبدوان هكذا //Users table user_id user_name 1 user1 2 user2 3 user3 //Services Table service_id service_name 1 service1 2 service2 3 service3 4 service4 5 service5 الآن لإعطاء الصلاحيات للمستخدمين يتطلب إنشاء الجدول الوسيط وتحديد كل مستخدم والصلاحيات الممنوحة له، فإذا افترضنا أن المستخدم الأول له كل الصلاحيات فيتم تكرار معرف المستخدم userID مع الخمس صلاحيات، وإذا افترضنا أن المستخدم الثاني له ثلاث صلاحيات فيتم تكراره مع هذه الصلاحيات الثلاثة، وهكذا مع كل المستخدمين، فيبدو هكذا.. //Table Users_Services user_ID service_ID 1 1 1 2 1 3 1 4 1 5 2 1 2 3 2 4 هذا أبسط تصميم، ولكن به مشكلة كبيرة جدًا، تخيل لو أن لديك 200 صلاحية، فأنت تحتاج تكرار المستخدم الأول مع 200 صلاحية، وإذا يوجد مستخدم آخر له أيضًا كل الصلاحيات فسوف تضطر إلى تكرارها معه أيضًا، فتخيل مدى الجهد والوقت واحتمالية الأخطاء التي ممكن أن تحدث بسبب هذا النظام. لذلك تم تطوير هذا النظام ليكون أكثر تقدمًا، بحيث يتم إنشاء جدول ونسميه المجموعات أو القواعد User_Roles ويتم الربط بينه وبين جدول الخدمات Services ثم نربط كل مستخدم بالمجموعة التي تناسبه، وبذلك نحدد صلاحيات المجموعة (مرة واحدة) وبعدها يمكن ربط عشرات المستخدمين بهذه المجموعة (بخطوة واحدة) فيكتسبوا الصلاحيات منها، وهكذا وفرنا على المستخدم تكرار أعمال مرهقة جدًا وربما يتسبب في أخطاء وإعطاء بعض المستخدمين صلاحيات ليست من حقه. الخلاصة: جدول المجموعات User_Roles يرتبط مع جدول الخدمات Services عن طريق جدول وسيط، ثم جدول المستخدمين Users يرتبط بجدول بالمجموعات بعلاقة واحد إلى متعدد One-to-Many لأن كل مستخدم له مجموعة واحدة فقط. هناك تصميمات أعقد من ذلك، وفيها يمكن للمستخدم أن ينتمي لأكثر من مجموعة ولكنها تصميمات معقدة جدًا وتحتاج خبرة عالية لفك التداخلات أو التشابكات Conflicts بين المجموعات التي ينتمي إليها المستخدم. فيكون النموذج النهائي: Users (user_id, user_name, user_roleID) Services (service_id, service_name) User_Roles (role_id, role_name) Services_Roles(service_id, role_id) //Intermediate table
  8. كما وضح أستاذنا حمزة عباد: إذا كنت تتابع إحدى الدورات يرجى طرح السؤال أسفل الدرس. ولكن يبدو من لقطات الشاشة أنك استخدمت الأمر let x = new sqlite3.Database("workx1"); لاحظ أنك لم تضع امتدادًا في اسم قواعد البيانات وبالتالي فإن قواعد البيانات ستأخذ الامتداد .sqlite لذلك ابحث في المجلد عن قواعد البيانات بالاسم workx1.sqlite أو ضع امتدادًا للملف فيصير let x = new sqlite3.Database("workx1.db");
  9. يجب ملاحظة شيء هام، وهو ليس الهدف من أكاديمية حسوب حل التمارين والاختبارات للطلاب فهذا ضد قواعد الأكاديمية. إنما الهدف هو تعليم المتدربين والطلاب واكتسابهم المهارات التي من خلالها يستطيعون حل المشاكل بأنفسهم. لذلك، أعطيكي بعض الملاحظات على الشيفرات المكتوبة، وعليك اكتشاف الخطأ وتصحيحه. أولاً: عند تعليق سطر (أي تهميشه) فإن السطر لا يتم تنفيذه ويتم اعتباره كأنه ملاحظة مكتوبة وليس شيفرت مطلوب تنفيذها، وبناء عليه يجب عليك البحث عن السطور المعلقة (التي قبلها //) وتفعيلها. ثانيًا: في الحلقة التكرارية for نحن نحدد البداية مثل i = 0 ونحدد الشرط الذي يضمن استمرار الحلقة التكرارية مثل i <= count ونحدد قيمة الزيادة عن طريق ++i، فإذا كتبنا الشرط بشكل خاطيء سيحدث خطأ إما الحلقة لن يتم تنفيذها، أو سيبدأ تنفيذها ولكنها لن تنتهي أبدًا، لذلك يجب عليكِ النظر في الشرط المكتوب وتصحيحه.
  10. دعينا نتفق أولًا على شيء هام جدًا وهو أنه لا أفضلية مطلقة لأي شيء، فلا يمكننا الجزم بأن MongoDB أفضل دائمًا من MySQL أو العكس، وإنما نقول الأنسب على حسب المشروع، فيمكن لنفس المبرمج أن يطور تطبيقين يستخدم في الأول MySQL بينما يستخدم في الآخر MongoDB ، لماذا؟ لأنه وجد أن خصائص المشروع الأول تحتاج قواعد بيانات ذات هيكلية معروفة ومحددة، بينما في التطبيق الثاني البيانات متفاوتة بشكل كبير جدًا فنحتاج مرونة وعدم تقيد بأعمدة محددة. هيا إلى مثال عملي (فبالمثال يتضح المقال) وليكن المشروع الذي تقومين بالعمل عليه وهو تطبيق حجز قاعات المناسبات: في هذا التطبيق يواجههنا احتمالان: الاحتمال الأول: أن خصائص الحجز واضحة ومحددة وثابتة، بمعني كل حجز له تاريخ، عدد مدعويين، عدد مشروبات، عدد وجبات. نلاحظ في هذا الاحتمال أننا مطالبون في كل حجز بتقديم معلومات معروفة وهي التاريخ وعدد المدعويين وعدد المشروبات وعدد الوجبات، لذلك فالأنسب في هذه الحالة استخدام قواعد بيانات مهيكلة يتم فيها إنشاء الجدول بعدد أربعة أعمدة كل عمود يخص بيانًا محددًا. الاحتمال الثاني: خصائص الحجز تتنوع وتختلف بشكل كبير جدًا لكل حجز، فهناك حجز يتم فيه تحديد التاريخ وعدد المدعويين فقط وحجز آخر يتم فيه تحديد التاريخ واسم الفرقة وعدد الوجبات وحجز ثالث يتم فيه تحديد التاريخ وعدد المدعويين ونظام الإضاءة وعدد الوجبات وفريق التصوير نلاحظ في الاحتمال الثاني أن الخصائص تختلف من حفلة إلى أخرى بشكل كبير جدًا وبالتالي لا يمكننا إنشاء جدول بأعمدة محددة ثابتة، فالاختيار الأمثل في هذه الحالة هو استخدام MongoDB ليمنحنا المرونة المطلوبة. وباتباع المثال السابق يمكن تحديد نوع قواعد البيانات في كل مشروع.
  11. في الحقيقة هذا السؤال هام جدًا جدًا، وهو من الأسئلة المتقدمة التي ستظهر مع ذوي الخبرة، لأن هذه المشكلة ستظهر عندما يقوم المبرمج بتطوير تطبيق وتوزيعه أو تثبيته عند العميل ثم بعد ذلك يقوم بعمل إضافات على هذا التطبيق، فتظهر هذه المشكلة. دعنا نصف المشكلة: عند تطوير أي تطبيق وإخراج الإصدار الأول منه، تكون إمكانيات هذا التطبيق محدودة إلى حد ما، ولكن مع انتشار التطبيق وأخذ الإفادات من المستخدمين سوف تظهر طلبات وإمكانيات جديدة مطلوب إضافتها إلى التطبيق (وهذا شأن أي تطبيق في العالم). إذًا ما المشكلة؟ المشكلة تكمن عندما يتعامل التطبيق مع ملفات أخرى مثل قواعد البيانات، فسنجد أن الإصدار الأول من التطبيق يتعامل مع قواعد بيانات تحتوي على عدد محدود من الجداول (وليكن 5 جداول)، ولكن مع الإضافات الجديدة سنحتاج إلى إضافة جداول أخرى (وليكن 3 جداول جديدة فيصبح الإجمالي 8 جداول). هنا تكمن المشكلة، لأن المستخدمين الحاليين قد أضافوا بيانات على قواعد البيانات (ذات الخمس جداول) وبالتالي لا يمكن حذف هذه القواعد وتنزيل القاعدة الجديدة (ذات الثمان جداول). فما الحل؟ سأذكر لك الخطوات العامة لأي تطبيق مهما كان نوعه سواء تطبيق أندرويد أو تطبيق ويندوز أو ماك، هذه الخطوات يجب اتباعها أولًا: بالنسبة للتطبيقات التي لا تقوم بحذف قواعد البيانات: هنا سنحتاج فقط تنفيذ بعض الاستعلامات التي تقوم بإنشاء الجداول الجديدة على قاعدة البيانات الموجودة حاليًا، وهكذا تظل الخمس جداول القديمة كما هي ببياناتها، ويضاف إليهم ثلاث جداول أخرى) ويتم تحديث التطبيق فيعمل بدون مشاكل. ثانيًا: بالنسبة للتطبيقات التي تحذف قواعد البيانات مع كل تحديث: إذا استطعنا تعطيل خاصية حذف الملفات مع التحديث عن طريق التحكم في خصائص التطبيق بملف الخصائص مثل gradle.properties كأن نضيف السطر التالي: android.builder.sdkDownload=false أو بأي طريقة تراها مناسبة على حسب التطبيق الذي تقوم به. فإذا فعلت هذا، اتبع التعليمات المذكورة سابقًا (بالنقطة أولاً). أما إذا لم تتمكن من تعطيل هذه الخاصية فيتوجب عليك قبل تحديث التطبيق أن تأخذ نسخة احتياطية من قواعد البيانات، وبعد التحديث، تحذف قواعد البيانات الجديدة التي نزلت حالًا مع التحديث، ثم تقوم باستعادة النسخة الاحتياطية ثم تقوم بإضافة التغييرات الجديدة عليها بعد الاسترجاع (أي إضافة الثلاث جداول الجديدة). بالتأكيد الموضوع متقدم، ويحتاج بحثًا وجهدًا، ولكن هذه الخطوط العامة التي يجب وضعها بالحسبان، والتي اكتسبناها على مدار سنوات خبرتنا بالبرمجيات وكنا نعاني كثيرًا من هذه النقطة، ولم تكن البرمجيات تقدمت بعد (أتحدث عن بدايات الألفينات).
  12. يقدم لنا الأمر desc أساسيًا معلومات عن الأعمدة الموجودة بالجدول مثل نوع بيانات العمود data type، المقيدات constraints والخصائص الأخرى. لكن لاستعراض المفاتيح التابعة (الأجنبية) Foreign Keys الخاصة بجدول معين وليكن bonuses نستخدم الاستعلام التالي SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_SCHEMA = (SELECT DATABASE()) AND REFERENCED_TABLE_NAME = 'bonuses';
  13. صورة المفتاح بجانب الحقل تعني أن هذا الحقل يُستخدم للربط مع جدول آخر أي أنه مفتاح تابع Foreign Key. ونلاحظ أن هذا المفتاح عبارة عن رقم يمكن من خلال هذا الرقم الوصول إلى سجل في جدول آخر وهو الجدول الأساسي Primary Table
  14. هناك أسلوب متبع ويعتبر من ضمن الممارسات الجيدة Best practice بحيث نعرف من خلاله المستخدم الذي قام بإضافة هذا السجل، وبالتالي يمكننا مراقبة إدخال البيانات ومعرفة المستبب في الخطأ إن وجد. إضافة إلى هذا العمود يوجد عمودان آخران يفضل إضافتهما وهما updated_id لمعرفة آخر مستخدم قام بالتعديل على هذا السجل creation_date لتسجيل وقت إنشاء هذا السجل ويفيد في معرفة تسلسل إدخال الحركات.
  15. وعليكم السلام ورحمة الله وبركاته، المفترض ان العلاقة بين جدول الإدارات أو الأقسام Sub_sections وجدول الموظفين Employees هي علاقة واحد إلى متعدد one-to-many أي كل سجل في جدول الإدارات يمكنه أن يرتبط بالعديد من السجلات بجدول الموظفين، وهذا منطقي لأن كل إدارة أو قسم يمكن أن يحتوي على موظف (واحد على الأقل) أو أكثر من موظف. ويتضح أيضًا من الصورة أن هناك علاقة ذاتية واحد إلى متعدد بين جدول الإدارات (الأقسام) ونفسه، بحيث كل قسم له قسم رئيسي، فهذه علاقة ذاتية تتم بين الجدول ونفسه في جملة الاستعلام، بحيث كل قسم يمكن أن يحتوي على عدة أقسام فرعية. ولكن ألاحظ وجود خطأ في العلاقة بين جدول الموظفين وجدول الإدارات، حيث يتم الربط بينهما بعلاقتين. ما السبب في هذا؟ المبرمج الذي وضع العلاقتين يقصد أن كل موظف له قسم رئيسي section_id وله قسم فرعي sub_section_id أيضًا لذلك قام بوضع علاقتين بين هذين الجدولين، في الحقيقة لا داعي لهذا لأنه يمكن معرفة القسم الرئيسي للموظف بمجرد أن عرفنا القسم الفرعي له (وذلك لأن القسم الفرعي يستطيع أن يصل إلى القسم الرئيسي الخاص به)، وبذلك يكفي الموظف معرفة القسم الفرعي ومنه يعرف القسم الرئيسي، فيتم الربط أولاً بين جدول الموظفين Employees وجدول الإدارات أو الأقسام Sub_sections ثم يتم الربط ثانيًا مع جدول الإدارات لمعرفة القسم الرئيسي. لذلك وجود علاقتين بين الجدولين بهذا الشكل خطأ كبير وكارثي يجب تجنبه إلا في حالات معينة نادرة (كأن ينتمي الموظف لقسمين في نفس الوقت).
  16. في البداية دعنا نتعرف أولاً عن معني كل مصطلح منهم أولًا: تنسيق EDIFACT هو اختصار لـ “Electronic Data Interchange for Administration, Commerce, and Transport” وهو تنسيق قياسي يُستخدم لتبادل البيانات بين أنظمة المؤسسات. يعتمد على ترميز البيانات بشكل نصي ويستخدم لتبادل المعلومات التجارية والمالية واللوجستية. باختصار هو طريقة لتوحيد التواصل بين الأنظمة المختلفة للمؤسسات، وبالتالي مهما كان نشاط المؤسسة وأسلوبها في التعامل، فالجميع مجبر على اتباع قواعد معينة لتوحيد التواصل فيما بينهم. فيتم استخدام رموز معينة للتعبير عن الشيء المطلوب، المثال التالي يوضح عناصر إشعار شحن يمكن استخدامه بين عدة مؤسسات رقم الفاتورة تاريخ الفاتورة إشارة الشحن (تاريخ شحن كل عنصر) شروط الدفع تفاصيل العناصر المحددة والرسوم الزيادات والخصومات أما لغة XML فهي لغة ترميزية يمكننا من خلالها تمثيل البيانات المهيكلة والمنظمة، على سبيل المثال بيانات جدول بقواعد البيانات يمكن تمثيلها باستخدام هذه اللغة كما بالمثال التالي: <?xml version="1.0" encoding="UTF-8"?> <products> <product> <name>K.B</name> <price>100</price> </product> <product> <name>Mouse</name> <price>80</price> </product> <product> <name>Speaker</name> <price>200</price> </product> </products> وللتحويل بينهما، يجب فهم هيكلة EDIFACT ثم يمكن تحويلها إلى ملف نصي، ومن ثم تحويل الملف النصي إلى هيكلة xml العناصر: رقم الفاتورة (Invoice Number): في XML، يمكن تمثيله باستخدام عنصر مثل <InvoiceNumber>. تاريخ الفاتورة (Invoice Date): يمكن تمثيله باستخدام عنصر مثل <InvoiceDate>. إشارة الشحن (Shipment Referral - تاريخ شحن كل عنصر): يمكن تمثيله باستخدام عنصر مثل <ShipmentReferral>. شروط الدفع (Payment Terms): يمكن تمثيله باستخدام عنصر مثل <PaymentTerms>. تفاصيل العناصر المحددة والرسوم (Specific Item Details and Charges): يمكن تمثيلها باستخدام عناصر مثل <Item> و <Charge>. الزيادات والخصومات (Surcharges/Discounts): يمكن تمثيلها باستخدام عناصر مثل <Surcharge> و <Discount> وستكون الشيفرة كاملة شيء كهذا <Invoice> <InvoiceNumber>12345</InvoiceNumber> <InvoiceDate>2024-05-21</InvoiceDate> <ShipmentReferral> <Item1>2024-05-15</Item1> <Item2>2024-05-18</Item2> <!-- ... --> </ShipmentReferral> <PaymentTerms>Net 30</PaymentTerms> <ItemDetails> <Item> <Description>Product A</Description> <Quantity>10</Quantity> <UnitPrice>100</UnitPrice> <!-- ... --> </Item> <!-- ... --> </ItemDetails> <Surcharges> <Surcharge> <Description>Shipping Fee</Description> <Amount>20</Amount> </Surcharge> <!-- ... --> </Surcharges> <Discounts> <Discount> <Description>10% Off</Description> <Amount>50</Amount> </Discount> <!-- ... --> </Discounts> </Invoice> بالتأكيد الموضوع يحتاج إتقان كلٍ من التنسيقين وكذلك معرفة ودراسة تفاصيل المعلومات المراد تحويلها حتى لا يحدث خطأ.
  17. بطء المواقع تتحكم فيها العديد من العوامل، لذلك يجب أولًا استخدام إحدى أدوات التحليل التي تقوم بتحليل الموقع واستخراج المشاكل التي به. من أهم هذه الأدوات الرسمية والتي تشرف عليها شركة جوجل https://pagespeed.web.dev/ من خلال هذه الصفحة تستطيع إدخال رابط موقعك وتطلب تحليله لكل من الهاتف المحمول Mobile أو اللاب توب Desktop ومن خلال تحليل موقعك عل هذه الأداة يتضح أن الموقع يعمل بشكل مقبول بالنسبة لللاب توب والأجهزة الكبيرة، أما بالنسبة للهاتف المحمول فتوجد عدة ملاحظات يجب معالجتها. بالتأكيد الموضوع يحتاج خبرة وسيحتاج منك بعض البحث عن كل نقطة أو الاستعانة بأحد المبرمجين الخبرة. ولكن أعطيك بعض الإرشادات بخصوص الملاحظات التي ظهرت: من ضمن الملاحظات أن الصور يمكن تحسين حجمها حتى تظهر بشكل أسرع وتوفر على المستخدم الذي يتصفح موقعك عن طريق باقة الإنترنت وليس الواي فاي. أرفقت لك صورة توضح الحجم الحالي والحجم المقترح لتحسين الأداء وبهذا الأسلوب تستطيع المرور على كل نقطة والبحث عن كيفية إصلاحها.
  18. اطلعت على الشيفرات الخاص بك، وتبدو صحيحة، وأنت بالفعل قمت بعمل الاتصال مع قواعد البيانات، وإرسال البيانات إليها، المفترض أن يتم الاتصال ثم تسجيل البيانات. فإذا لم يحدث كما هو متوقع يرجى بحث النقاط التالية - أولاً: التأكد من الاتصال الصحيح بقواعد البيانات أنت تستخدم localhost, 8889 لذلك يرجى التأكد أن فعلًا قواعد البيانات متصلة بهذا الخادم على نفس المنفذ، وسنقوم بعمل تعديل صغير بالشيفرات، لأن السطر الخاص بالاتصال إذا حدث به مشكلة فلن يتم تنفيذ باقي الأسطر <?php $servername = "localhost:8889"; $username = "root"; $password = "root"; $dbname = "student_information2"; try { // نضع الشيفرات داخل كتلة // try-catch $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } if ($_SERVER["REQUEST_METHOD"] == "POST") { // باقي الأسطر تكتب بشكل طبيعي // ... if (mysqli_query($conn, $sql)) { echo "Data inserted successfully!"; } else { echo "Error inserting data: " . mysqli_error($conn); } } $conn->close(); } catch (Exception $e) { echo "An error occurred: " . $e->getMessage(); } ?> - ثانيًا: التأكد من استخدام أسماء الحقول الصحيحة عند القراءة باستخدام $_post
  19. بما أنك تعاملت مع هذا الموضوع من قبل، فالأمر يشبهه من حيث ترتيب الخطوات، فأنت تعاملت مع المصفوفة array والتي كان بمثابة قواعد البيانات التي تخزن فيها البيانات وتسترجعها، نفس الخطوات ستقوم بها ولكن مع بعض التفاصيل. ومن الأشياء الهامة التي يجب وضعها في الاعتبار، أنه من أنجح الطرق للربط بين الواجهة الأمامية Frontend والواجهة الخلفية Backend هو باستخدام الواجهات البرمجية APIs التي يتم إنشاؤها بالواجهة الخلفية، واستدعاؤها بالواجهة الأمامية. أولاً: إنشاء واجهة برمجية للاتصال بقاعدة البيانات: للتعامل مع أي قواعد بيانات لابد من إنشاء اتصال بها، يمكنك استخدام معلومات الاتصال (مثل اسم المستخدم وكلمة المرور واسم قاعدة البيانات) للاتصال بقاعدة البيانات. قم بفحص الاستجابة العائدة من الواجهة البرمجية للتأكد من نجاح الاتصال. العمليات الأساسية (CRUD): يتم إنشاء واجهة برمجية لكل عملية مثل: واجهة برمجية لإنشاء مستخدم جديد، وهذه يتم استدعاؤها من صفحة Register وتقوم بإضافة مستخدم جديد للجدول باستخدام الأمر insert واجهة برمجية لدخول المستخدم: نعطيها اسم المستخدم وكلمة المرور، وهي تستعلم عن هذه البيانات باستخدام الأمر select وهكذا يتم إنشاء الواجهات البرمجية APIs المطلوبة، واستدعاؤها من الواجهة الأمامية. هذه بعض الإرشادات لخطوات التعامل مع قواعد البيانات، وبالتأكيد الأمر يحتاج إلى دراسة قواعد البيانات والأوامر الأساسية بها مثل insert, update, delete, select وكذلك معرفة بإنشاء الجداول عن طريق الأمر create table وأيضًا معرفة كيفية الاتصال بين الواجهة الخلفية مع قواعد البيانات. لمعرفة المزيد عن قواعد البيانات انقر هنا
  20. يتم تعريف الخدمات المصغرة Microservices على أنها نوع من أنواع هيكلة المشاريع، يتم فيه تقسيم المشروع إلى عدة مشروعات صغيرة مستقلة تمامًا عن بعضها البعض، كل خدمة تعتبر فعليًا مشروعًا مستقلاً له فريق مستقل وقواعد بيانات مستقلة ويتم نشره ورفعه على الخادم بشكل مستقل، ويتم التواصل بين هذه الخدمات عن طريق بروتوكولات خفيفة الوزن لتبادل البيانات بينها حتى تكتمل المنظومة كلها. وهي تكنولوجيا ظهرت حديثًا إلى حد ما، وتحتاج خبرة عالية سواء من مهيكل المشروع Solution Architecture أو فرق العمل من المطورين، ومن ضمن فوائدها أنها تقوم بتقسيم المشروعات الضخمة إلى عدة مشاريع صغيرة مستقلة تمامًا عن بعضها وبالتالي يتم تطوير كل مشروع بفريق منفصل تمامًا دون الاعتماد على أي مشروع آخر مما يعطي مرونة في تطوير البرمجيات مقابل النظام الاعتيادي Monolithic. من خلال خبرتي، ورغم أن هذه الهيكلة فعليًا مفيدة جدًا في تقسيم المشروعات الضخمة وتسهيل العمل، إلا أنني عانيت في تجربتين مختلفتين استخدمت فيهما هذا النوع من الهيكلة، والمعانات كانت بسبب عدم خبرة فرق المطورين، لذلك لا تلجأ أبدًا لهذا النوع إلا بعد تدريب الفريق جيدًا. ملحوظة: النظام الاعتيادي كان يتم فيه تطوير النظام كاملاً في مشروع واحد كله مترابط وكل جزء فيه يعتمد على الأجزاء الأخرى. فإذا أردنا المقارنة بينهما، فنشبههما بمصنعين الأول: عبارة عن ورشة ضخمة فيها جميع الخدمات تحت هذه الورشة الثاني: يتم تقسيم مساحة الأرض إلى عدة مصانع صغيرة، كل منها له مدير وفريق حسابات ومخازنه الخاصة وإدارته المستقلة تمامًا عن باقي المصانع، ثم يتم رصف طرق بين هذه المصانع المصغرة لنقل المنتجات منها وإليها. بالتأكيد النوع الثاني فيه استقلالية رائعة، ولكن في المقابل يحتاج عملية تنظيم رهيبة بمعني الكلمة بين هذه المصانع المصغرة وإلا ستفشل المنظمة ككل بسبب عدم التنسيق الجيد، وهذا ما سيحدث إذا لم يتم الانتباه لهذه النقطة عند استخدام الخدمات المصغرة Microservices. كما ذكرنا، هي ليست خدمة تقدمها بعض البرامج، إنما هي نوعية لتطوير وهيكلة البرامج الضخمة، ويمكن تطويرها بأي لغة برمجة تدعم هذه الطريقة، مثل بايثون، جافا، سي شارب.
  21. للانتقال إلى صفحة مختلفة يتم تعين اسمها في الصفة href للرابط التشعبي hyperlink فيكون السطر كالتالي: <p> Don't Have an Account? <a href='register.html'>Create New</a></p> ومنطقيًا تكون أيقونة المستخدم وعرب التسوق تكونان مختفيتين حتى يتم تسجيل الدخول، ويتم ذلك بعدة طرق من ضمنها استخدام الجافاسكريتب مع CSS
  22. السبب هو أن ما تم تحويله إلى نص هو قيمة المتغير وليس المتغير نفسه فالسطر التالي echo gettype((string) $age); يقوم بتحويل قيمة المتغير التي هي 26 ونوعها (عدد صحيح) int يحولها إلى نص string، أي أنه أخذ قيمة المتغير وطبق عليها عملية التحويل، أما المتغير نفسه لم يتغير، ولتغير نوع المتغير يجب كتابة الأمر بالشكل التالي $age = (string)$age; echo gettype($age); نلاحظ بالسطر الأول، قمنا بإعادة تعيين قيمة نصية string للمتغير، وهي مأخوذة من قيمته السابقة التي هي 26 يحولها إلى نص، ثم يعينها للمتغير مرة أخرى، في هذه الحالة يتم تغيير نوع بيانات المتغير.
  23. وعليكم السلام ورحمة الله وبركاته، باختصار شديد، أعرض لك جميع الاختيارت (ولكن الاختيار الأخير هو الأجدد) لتحويل موقع ويب إلى تطبيق محلي native application لدينا عدة اختيارات، أولها: تطوير تطبيق منفصل لكل من الأندرويد وIOS بلغات البرمجة المخصصة لكل منصة ثانيًا: تطوير تطبيق واحد باستخدام لغات البرمجة الهجينة وسيعمل على كل المنصات (ولكن بالتأكيد سيفقد بعض المزيا) ثالثًا: تطوير تطبيق ويب فيو web view وهو يعرض نفس الموقع ولكن من داخل تطبيق وليس المتصفح هذه النقاط وضحها الزملاء الأفاضل بالتعليقات السابقة. رابعًا: والأحدث توجد نقنية جديدة رائعة ظهرت مؤخرًا، وهي تطبيقات الويب التقدمية PWA Progressive Web Application وهي باختصار: تعديلات تتم على موقع الويب نفسه (أي لا نحتاج لتطوير تطبيقات محلية)، هذه التعديلات تجعل تطبيق الويب يتصرف وكأنه تطبيق محلي، أي - يمكن تثبيته على الجهاز الخاص بك وإظهار أيقونة على سطح المكتب أو شاشة البداية - يمكنه العمل بنافذة مستقلة دون الحاجة إلى المتصفح - يمكنه العمل بدون اتصال بالإنترنت offline - يمكنه الوصول إلى موارد الجهاز مثل الكاميرا والبلوتوث وغيرها - يمكنه إظهار الإشعارات - يمكنه التزامن عند عودة الاتصال، فيقوم بإرسال البيانات إلى الخادم والتي تم تخزينها أثناء الانقطاع والعديد من المزايا الأخرى، التي تجعله يبدو ويتصرف كالتطبيقات المحلية (رغم أنه نفس الموقع ولكن بعد إجراء عدة تعديلات عليه)، وهي تقنية جديدة تنمو سريعًا وتنتشر بشكل خرافي.
  24. وعليكم السلام ورحمة الله، دعنا أولًا نتفق على شيء هام جدًا، وهو إذا لديك اختياران كلاهما صحيح، فلا يوجد تفضيل مطلق (أي دائمًا)، بمعنى لا يوجد اختيار هو الأفضل دائمًا، ولكن يوجد اختيار هو الأنسب للحالة التي بين أيدينا، (أؤكد أن الخيارين صحيحان فنحن هنا لا نقارن بين ممارسة صحيحة وأخرى خاطئة). كلتا الشفرتين صحيحتان سواء كصيغة أو كممارسة، نأتي هنا للأنسب، أيهما أنسب؟ هذا يتوقف على الحالة كما وضحت، ففي الكثير من الأحيان يفضل المبرمجون الطريقة الثانية كما وضح مهندس مصطفى @Mustafa Suleiman لأنها طريقة واضحة ومباشرة وخصوصًا إذا يوجد مبتدئين بالفريق فربما لا يعرفون الطريق الأولى. وبالمناسبة الطريقة الأولى مشهورة جدًا في لغات البرمجة وتسمى "العامل الثلاثي" ternary operator ويفضلها الكثير من المبرمجين لأنها رائعة في إعطاء المتغير إحدى قيمتين بناء على شرط معين، فمن يعتاد عليها يدمنها حرفيًا (وأنا واحد منهم)، ولكن هل أستخدمها في كل مكان؟ بالطبع لا ولكن هناك حالات مناسبة لها وحالات أخرى غير مناسبة، من أكبر الفوائد لهذه الطريقة أنها تجنب الوقوع في الأخطاء، انظر للشيفرات التالية .. device = "cuda" if torch.cuda.is_available(): device = "cude" else "cpu": devic = "cpu" هل لاحظت شيئًا؟ لقد حدث خطأ إملائي في اسم المتغير بالسطر الأخير، وهذا سيسبب في مشاكل كبيرة جدًا، لأن بايثون سيعتبر أنك تريد تعريف متغير جديد اسمه devic ولا يعلم أنه تقصد المتغير device، هذه من ضمن فوائد العامل الثلاثي، ولكن كما قلت، يستخدم بحذر. الخلاصة: تعتمد الطريقة على الحالة التي بين يديك، فإذا كان الفريق يحتوي العديد من المبتدئين، فالطريقة الثانية أنسب، أما إذا لديهم خلفية جيدة عن العامل الثلاثي، فالطريقة الثانية ستكون أنسب في حالة إعطاء إحدى قيمتين للمتغير بناء على شرط معين.
  25. على ما يبدو أنك تريد إظهار سعر البيع بمجرد تغيير سعر الشراء أو النسبة المئوية، في هذه الحالة تحتاج لمعالجة حدث التغير لمربع النص TextChanged لكل من مربعي النص، وكتابة المعادلة الصحيحة لحساب سعر البيع. ولكن يمكنك إضافة زر أوامر Button وكتابة الشيفرات داخله بدلاً من معالجة حدث التغير لمربعات النص. وبالمناسبة يمنكك استخدام أداة أخرى أفضل من مربع النص تسمى NumericUpDown وتستخدم لإدخال قيم عددية فقط، ويتم معرفة القيمة المكتوبة عن طريق الخاصية Value بدلاً من الخاصية Text لمربع النص. إذاً، يفضل إضافة زر أوامر، وتسميته بالشكل الصحيح وليكن btnCalcPrice، ثم النقر عليه مرتين لمعالجة الحدث Click وكتابة الشيفرات التالية // نفترض لديك مربعان نص وأداة عنوان بالأسماء التالية // txtOrigin, txtRatio, lblSalePrice // قراءة سعر الشراء الأصلي من مربع النص الأول decimal originPrice = decimal.Parse(txtOrigin.Text); // قراءة النسبة المئوية من مربع النص الثاني decimal ratio = decimal.Parse(txtRatio.Text); // حساب سعر البيع عن طريق إضافة النسبة المئوية من سعر الشراء إلى سعر الشراء // بفرض سعر الشراء 80، والنسبة 20 فإنه يضيف 20% من سعر الشراء (أي 16 جنيهًا) إلى السعر الأصلي 80، ليصير سعر البيع 96 decimal salePrice = originPrice + (originPrice * ratio / 100); // يتم إظهار سعر البيع في أداة العنوان lblSalePrice.Text = salePrice.ToString(); الآن، اكتب السعر السعر الأصلي، والنسبة، ثم اضغط على الزر ليظهر سعر البيع.
×
×
  • أضف...