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

Mustafa Suleiman

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

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

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

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

    447

كل منشورات العضو Mustafa Suleiman

  1. عند الضغط على دوراتي ستظهر لك جميع الدورات، وذلك لأنّ المسار الأول من جميع الدورات مجاني لك، أما الدورات التي اشتركت بها متاحة لك بالكامل، وعليك دراستها بنفس ترتيب المسارات التي بها واحد تلو الآخر، أي قم بالضغط عليها وستظهر لك المسارات الخاصة بها.
  2. أرجو الضغط على تبويب دوراتي بالأعلى وستظهر لك الدورات التي اشتركت بها:
  3. الأمر يعتمد على التخصص الذي اخترته، أعتقد أنك تريد أن تصبح مطور Full-stack، إذن تعلم جافاسكريبت لا غنى عنه، طالما اخترت مجال الويب سيتعين عليك التعامل معها بلا شك، سواء في الواجهة الأمامية أو في الواجهة الخلفية من خلال Node.js حيث ستتعلمها في مرحلة متقدمة بعد الوصول لمستوى جيد في PHP ولارافل، وذلك لأنها مطلوبة ومستخدمة في سوق العمل ومناسبة أكثر لمشاريع معينة. في الوقت الحالي، ركز على تعلم أساسيات جافاسكريبت ولا تتعمق كثيرًا، وتعمق أكثر في PHP طالما هي اللغة الأساسية بالنسبة لك وإطار لارافل الخاص بها، وبعد فترة تستطيع التعمق في جافاسكريبت والتقنيات الخاصة بها مثل React أو Vue.js. وتلك الأساسيات لازمة لكي تتمكن من استخدام المكتبات المبنية بواسطة جافاسكريبت وأيضًا تنفيذ المنطق الذي تريده في الواجهة الأمامية والتعامل مع الأخطاء. وللعلم يوجد مكتبة Alpine.js توفر لك التفاعلية التي توفرها جافاسكريبت بدون الحاجة للتعمق في اللغة، تعلمها بعد تعلم أساسيات اللغة وستحقق استفادة منها لحين التعمق في جافاسكريبت.
  4. المشكلة حاليًا هنا \partial_movie_files\BooleanOperations\partial_movie_file_list.txt. لم يتم إنشاء أي صور إطارات أصلاً، أو تم إنشاؤها فى مكان آخر ولم يجده، أو ربما المشهد لا ينتج أي إطار في حال ‎construct()‎ فارغ أي ليس به لا ‎Create‎ ولا ‎self.add()‎، من المفترض أن يكون: class BooleanOperations(Scene): def construct(self): c = Circle(color=RED, fill_opacity=0.5) self.add(c) self.wait() ضع أي عنصر Circle أو Text أو أي حركة ‎play()‎ داخل ‎construct()‎ وسيبدأ Manim بتوليد frames ثم يدمجها بدون خطأ. لو استمرت المشكلة غالبًا أنت نفّذت الأمر من داخل ‎Scripts‎، فصار ‎media_dir‎ = ‎Scripts\media‎ وتلك ليست مشكلة بذاتها، لكن لو شغّلت Manim مرة من الجذر ثم مرة من ‎Scripts‎ سيُنشئ مجلدين مختلفين ويختلط عليه الأمر. عليك تشغيله من الجذر دائمًا أي في مسار مجلد المشروع الرئيسي، احذف المجلد ‎media‎ بالكامل، ثم تنفيذ: manim Scripts\main.py BooleanOperations -p -qh
  5. لاحظ الأمر يبحث عن مجلد باسم scripts لذا يجب تنفيذه في المسار الذي يوجد به ذلك المجلد، أرجو تنفيذ الأمر في مسار مجلد الصحيح أي انتقل إلى: cd "D:\Hassoub\New_School\Pharaonic_Programmer\projects\Dijkstra's_Algorthum" ثم: manim Scripts\main.py BooleanOperations -v DEBUG -p -qh
  6. لا تشغلك بالك كثيرًا بمثل تلك الأمور استمر في التعلم وتطوير مستواك وتعميق فهمك فذلك ما يضمن مستقبلك إن شاء الله، الأمر مؤثر بالفعل لكن ليس بالشكل الذي تتوقعه أي الاستبدال التام، بل أدوات مساعدة لك لتنفيذ المهام المتكررة والمعروفة في كل مشروع بجانب تنفيذ بعض الأمور طالما لديك القدرة على وصف ما تريده، ولكن في المهام المعقدة الأمر كل عائد إليك. فكر بها مثل الآلة الحاسبة، هل اختفى مدرسي الرياضيات؟ بالطبع لا، لكن تم استخدامها كأداة مساعدة لتقليل عبء حساب المسائل البسيطة وبعض الآلات الحاسبة تستطيع حل المسائل المتوسطة، لكن مهمة حل المسألة في يدك أنت فهي لا تفهم المسألة بالكامل بل مُدربة على الحل بطريقة معينة. بالتالي الأدوات المساعدة عمومًا لن تمحو الحاجة إلى المبرمج، بل ستُغير شكل عمله وطريقة إنجازه للمهام، فهي لا تفهم السياق الكامل للمنتج، ولا تصمّم البنية المعمارية System Design للمشروع أو تتخذ قرارات عمل وأولويات، فكلها تتطلب مبرمج ذو خبرة. مُدرس الرياضيات أصبح يعتمد على الآلة الحاسبة لتسريع عمله في حل المسائل، نفس الأمر بالنسبة لك استخدم ما هو متوفر من أدوات للإنتاج بشكل أفضل، فذلك المطلوب في سوق العمل. لكن لا تقم بذلك إلا بعد دراسة الأساسيات بشكل قوي والتعمق بها، وعدم الإعتماد عليها كل الإعتماد، فذلك من شأنه خفض مستواك وليس رفعه.
  7. ما هو الكورس الذي قمت بدراسته؟
  8. نفذ التالي إذن لتفقد المشكلة أكثر: manim Scripts\main.py BooleanOperations -v DEBUG -p -qh
  9. حاليًا المشكلة في ffmpeg، وليس الكود نفسه، نفذ الأمر التالي: ffmpeg -version لو حصلت على ffmpeg is not recognized فذلك يعني أنّ مسار ffmpeg غير موجود فى متغيّر البيئة PATH في النظام عليك إضافته ثم أغلق منفذ الأوامر وأعد تشغيله للتعرف على متغيرات البيئة الجديدة.
  10. المشكلة أنّ المسار خطأ، وليس لها علاقة بالـ ffmpeg أو بالامتداد نفسه، عليك تنفيذ الأمر داخل مجلد المشروع نفسه بكتابة المسار التالي: manim Scripts\main.py BooleanOperations -qh -p أو: python -m manim Scripts\main.py BooleanOperations -qh -p الأفضل التوجه لمجلد المشروع ثم تنفيذه: cd Scripts manim main.py BooleanOperations -qh -p وفي VS Code (Manim-SideView) افتح الإعدادات ثم توجه إلى Extensions ثم Manim Sideview، وفي الحقل Script Path اجعله Scripts\main.py أو عطّل الحقل واترك الامتداد يلتقط الملف المفتوح حاليًّا. إن استمرت المشكلة، اجعل استدعاء Manim بأسلوب الـ module: python -m manim -p -qh -m Scripts.main BooleanOperations
  11. ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  12. الأفضل أن يرى المستخدم قائمة بكل الترقيات المُسجلة، مع أهم المعلومات التى تسمح له بالبحث، الفرز، والانتقال سريعاً إلى تفاصيل أو تعديل الترقية، والمعلومات التى يجب عرضها تُستخرج من جدول promotions نفسه بالإضافة إلى علاقة الموظف employee وربما المستخدم الذى أنشأ السجل created_id لو أردت. بحيث يتواجد في جدول العرض التالي: رقم تسلسل أو الـ ID. رقم القرار num. اسم الموظف – مع رابط لصفحة تفاصيله. الرقم الوظيفى أو الـ emp_id لو أردت إظهاره. الدرجة السابقة prev_degree الدرجة الجديدة new_degree. ترقية استثنائية؟ مع خيار نعم ولا أو أيقونة للضغط عليها للضغط عليها وتصبح excep = true. تاريخ الاستحقاق date. تاريخ آخر ترقية last_date ويظهر فارغاً في حال null. أُضيفت بواسطة، حيث تكتب اسم المستخدم من created_id. تاريخ الإدخال created_at. المرفقات، وتحتوي على أيقونة تحميل إن تم رفع ملف، أو عداد بعدد الملفات. وأزرار للإجراءات وهي عرض – تعديل – حذف حسب صلاحيات المستخدم. وللاستزادة تستطيع إضافة شريط بحث أو فلاتر، للبحث باسم الموظف، رقم القرار، الدرجة، الفترة الزمنية وخلافه، بالإضافة إلى زر إضافة ترقية فى أعلى الصفحة يقود إلى create.blade.php. وبالطبع عليك ترقيم الصفحات بواسطة الـ pagination لو القائمة طويلة.
  13. في المتحكم في دالة store، يتم التحقق من صحة البيانات وهي: prev_degree : رقم الدرجة الحالية للموظف. date : تاريخ الاستحقاق new_degree : الدرجة الجديدة. وتفشل الترقية فى الحالات الآتية قبل الحفظ، أولاً يوجد سجل Promotion بنفس emp_id و new_degree فيعاد توجيه المستخدم برسالة خطأ، أو جدول employees يحتوى أصلاً على نفس الدرجة المطلوبة للموظف. والترقية العادية يجب أن تكون +1 درجة بالضبط، حيث new_degree تساوي prev_degree + 1 ما لم يكن مربع ترقية استثنائية excep مُعلم عليه حيث يتم تجاوز الشرط. وعند النجاح يُنشأ كائن Promotion ويُملأ بالبيانات: num رقم القرار emp_id رقم الموظف prev_degree الدرجة السابقة new_degree الدرجة الجديدة date تاريخ الاستحقاق last_date تاريخ آخر ترقية وهو اختياري. excep ترقية استثنائية = true إذا تم اختيارها created_id رقم المستخدم الذى أجرى العملية ثم تحديث درجة الموظف فى جدول employees إلى new_degree، ورفع أى ملفات مرفقة وتخزينها فى storage/app/public/PROMOTION وتسجيل مسارها بجدول files. حاليًا، عليك وضع شرط للتأكد من أن new_degree أكبر من prev_degree فى الترقية الاستثنائية، لأنّ المستخدم يستطيع إدخال نفس الدرجة أو أقل. if(request('excep') && request('new_degree') <= request('prev_degree')){ }
  14. بناءًا على ما درسته، متاح لك دورة تطوير التطبيقات بواسطة جافاسكريبت، ومن خلالها تستطيع تعلم تطوير الواجهة الأمامية والخلفية أيضًا من خلال تقنيات MERN وهم MongoDB وExpress.js و React و Node.js. كذلك تعلم تطوير تطبيقات الهاتف من خلال React Native، وأيضًا تطبيقات سطح المكتب من خلال Electrone.js، أيضًا بها شرح لكيفية تضمين الذكاء الاصطناعي في المشاريع. بالتالي الدورة شاملة وستصبح مطور Full-stack وذلك مطلوب في سوق العمل حاليًا، وأنت قد تعلمت اللغات الأساسية للويب بالفعل وهم HTML, CSS, JS، لذا تحتاج إلى تطوير مهاراتك بتعلم تقنيات جافاسكريبت. متاح لك أيضًا دورة الذكاء الاصطناعي، ومن خلالها تستطيع أن تصبح محلل بيانات أو مطور ذكاء اصطناعي، أي هي الدورة الأنسب لدراسة الذكاء الاصطناعي بعمق والتخصص به في حال ذلك ما تريده. وفي حال أردت التخصص في الواجهة الخلفية فقط فلديك دورة PHP، وستتعلم بها أساسيات اللغة وإطار لارافل الشهير الخاص بها بالإضافة إلى ووردبريس، وكلاهما مطلوبين بشدة في مواقع العمل الحر، ولديك أساسيات الواجهة الأمامية لذا تستطيع أن تصبح مطور Full-stack. وأيضًا دورة بايثون، وهي الأقرب لدورة الذكاء الاصطناعي، حيث أنّ لغة بايثون هي اللغة الأساسية في ذلك المجال ومجال تحليل البيانات، ومن خلالها أيضًا ستتعلم إطار جانغو والذي يسمح لك بتطوير مشاريع Full-stack.
  15. مرحبًا بأهل غزة الكرام، الجميع يتفهم الوضع، لذا أرجو التحدث مع مركز المساعدة وإرسال نفس الرسالة وسيتم الرد عليك إن شاء الله، حيث الأمور المالية يتم مناقشتها من خلالهم وليس من خلال قسم أسئلة البرمجة.
  16. جميع الدورات بالأكاديمية لا تشترط وجود أي خبرة برمجية مُسبقة، ففي كل دورة يوجد مسارات خاصة بالأساسيات اللازمة لتعلم التخصص الخاص بالدورة، أي الدورة موجهة للمبتدئين في المقام الأول، وبالطبع توجد مسارات متقدمة في الدورة يستطيع من لديه خبرة دراستها لتحسين مهاراته، لذا تناسب الجميع. لأنّ الدورة تم إعدادها بشكل ممنهج بحيث تكون المسارات متدرجة من البداية ثم صعودًا نحو المستوى المتقدم، من خلال شرح الأساسيات ثم تطبيقات عليها ثم شرح التقنيات الخاصة باللغة، ثم مشاريع عملية كاملة على التقنيات الخاصة باللغة ثم مفاهيم متقدمة.
  17. ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  18. 0 bytes مفادها أنّ الملف part1 به مشكلة، هل قمت بتحميله بشكل صحيح أو حدث خطأ أثناء تحميله أو نقله؟ عامًة حاول تثبيت UnRAR: sudo apt install unrar ثم تنفيذ الأمر التالي في مسار المجلد الذي به الملفات: unrar x اسم الملف الذي تريد فك ضغطه أو تجربة أداة أخرى وهي 7-Zip: sudo apt install p7zip-full p7zip-rar ثم تنفيذ: 7z x اسم الملف لو استمرت المشكلة، فالملفات معطوبة.
  19. الفكرة ليس في التطبيق على كل ساعة، بل في التطبيق على مفهوم معين تعلمته، مثلاً تعلمت أساسيات حلقات التكرار في بايثون، هنا تتوقف وتقوم بتنفيذ تمرين للتطبيق على ذلك المفهوم، وربط التمرين بما تعلمته سابقًا أي القوائم والمتغيرات والجمل الشرطية وهكذا. في حال كان الدرس طويل أو به مفاهيم مختلفة، أرجو قراءة التالي: في بعض الدروس ستجد شرح نظري، هنا يتعين عليك الاستيعاب قدر الإمكان والسؤال عن الأمور الغير واضحة لك لتفصيلها وتبسيط، وبعد فترة من التطبيق العملي سيتضح لك الأمر أكثر. ولا يوجد مدة محددة للتطبيق، الأمر كله يعود للوقت المتوفر لك وتحتاج إلى إدارته، عامًة عليك تخصيص 50% من وقتك للتطبيق العملي. وللعلم مجال الذكاء الاصطناعي يعتبر ضمن أكثر مجالات البرمجة تعقيدًا وبحاجة إلى مجهود واستيعاب أكثر من باقي المجالات. لذا يجب دراسة الدورة بهدف الاستيعاب وليس بهدف إنهائها في أسرع وقت، البحث والمشاهدة بجانب ما يتم شرحه أمر لابد منه وذلك حال أي دورة في أي مكان، فلا توجد تلك الدورة التي تقدم لك كل شيء. وإدارة مجهودك بذكاء من خلال معرفة ما يجب عليك تعلمه في البداية وما تحتاجه لاحقًا، فبطبيعة الحال توجد أساسيات ثم أمور خاصة بالمستوى المتوسط ويليها المستوى المتقدم. اتبع قاعدة 20 - 80 وهو مبدأ باريتو، الفكرة الأساسية هي أن 20% من المجهود تغطي 80% من النتائج أو المهام المطلوبة. وبالتطبيق على الدورة، ركز على تعلم أساسيات البرمجة كالمتغيرات، الحلقات، الدوال، والهياكل البيانية (القوائم والمصفوفات) لحل 80% من المشكلات البرمجية البسيطة إلى المتوسطة. وفي التطبيق العملي عليك قضاء 20% من وقتك في تعلم النظريات و80% في كتابة الكود وحل المشكلات العملية يساعد على تثبيت المعرفة. بعد فترة من الوقت لن تصلح تلك القاعدة بسبب تعقيد مجال الذكاء الاصطناعي، ويجب تعميق الفهم لما يتجاوز استيعاب الأساسيات، أي قاعدة 20% لن تجدي نفعًا بعد فترة لكن ستفيدك في البداية.
  20. استخدم الدالة التالية سواء في نفس الملف أو في ملف آخر وتستطيع استدعائها: function getVacationBalances(mysqli $con, int $empID, int $year = null): array { $year = $year ?: date('Y'); $balances = []; $stmt = $con->prepare( "SELECT e.start_date AS hire_date, p.birth_date AS birth_date, p.gender AS gender FROM employees e JOIN people p ON p.id = e.person_id WHERE e.person_id = ?"); $stmt->bind_param("i", $empID); $stmt->execute(); $stmt->bind_result($hire_date, $birth_date, $gender); if (!$stmt->fetch()) return []; // لا يوجد موظف $stmt->close(); $to = new DateTime("$year-12-31"); $age = $to->diff(new DateTime($birth_date))->y; $serviceYears = $to->diff(new DateTime($hire_date))->y; $quota = [ 'اجازة سنوية' => ($age >= 50 || $serviceYears >= 20) ? 45 : 30, 'اجازة مرضية' => 60, 'اجازة الحج' => 20, 'اجازة زواج' => 14, 'اجازة وفاة الزوج' => ($gender === 'أنثى' ? 130 : 0), ]; $stmt = $con->prepare( "SELECT type, SUM(DATEDIFF(end_date,start_date)+1) AS used_days FROM vacations WHERE emp_id = ? AND accept = 1 AND ( -- للسنة والمرضية نحصر بالسنة (type IN('اجازة سنوية','اجازة مرضية') AND YEAR(start_date)=?) -- لباقى الأنواع مدى الخدمة كلها OR type NOT IN('اجازة سنوية','اجازة مرضية') ) GROUP BY type"); $stmt->bind_param("ii", $empID, $year); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { $balances[$row['type']]['used'] = (int)$row['used_days']; } $stmt->close(); foreach ($quota as $type => $q) { $used = $balances[$type]['used'] ?? 0; $balances[$type] = [ 'quota' => $q, 'used' => $used, 'remaining' => max(0, $q - $used) ]; } return $balances; } الاستدعاء سيكون كالتالي بتمرير الرصيد الحالى للسنة الجارية للدالة getVacationBalances: $balances = getVacationBalances($con, $emp_id); echo "<pre>"; foreach ($balances as $type=>$row){ echo "$type : المستحق = {$row['quota']} | المستخدم = {$row['used']} | المتبقي = {$row['remaining']}\n"; } echo "</pre>";
  21. كل شيء كما هو، فقط استبدل الكود بداخل كتلة الشرط if ($_SERVER["REQUEST_METHOD"] == "POST")
  22. عليك جلب التاريخ start_date من جدول employees وتاريخ الميلاد و الجنس من people، ثم حساب العمر وسنوات الخدمة فى نفس لحظة تقديم الطلب، ثم أضف التحقق من الرصيد المستحق أو الحد الأقصى لكل نوع إجازة، ومن شرط 15 يوم المتصلة فى السنة، ومنع طلب أيام أكثر من المسموح أو أقل من المطلوب. بدل الجزء التالي لديك في الكود داخل if ($_SERVER["REQUEST_METHOD"] == "POST") : if ($_SERVER["REQUEST_METHOD"] == "POST") { $emp_id = (int)$_POST['emp_id']; $type = $_POST['type']; $start_date = $_POST['start_date']; $end_date = $_POST['end_date']; $reason = $_POST['reason']; $companion = isset($_POST['companion']) ? 1 : 0; $created_at = date('Y-m-d H:i:s'); $errors = []; if (!$type) $errors[] = 'يجب تحديد نوع الإجازة'; if (!$start_date) $errors[] = 'يجب إدخال تاريخ بداية الإجازة'; if (!$end_date) $errors[] = 'يجب إدخال تاريخ المباشرة'; if ($end_date <= $start_date) $errors[] = 'تاريخ المباشرة يجب أن يكون بعد بداية الإجازة'; if ($errors) { echo implode('<br>',$errors); exit; } $stmt = $con->prepare("SELECT e.start_date , p.birth_date , p.gender FROM employees e JOIN people p ON p.id = e.person_id WHERE e.person_id = ?"); $stmt->bind_param("i",$emp_id); $stmt->execute(); $stmt->bind_result($hire_date,$birth_date,$gender); if(!$stmt->fetch()){ echo 'لم يتم العثور على بيانات الموظف'; exit; } $stmt->close(); $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id = ? AND accept = 0"); $stmt->bind_param("i",$emp_id); $stmt->execute(); $stmt->bind_result($pending); $stmt->fetch(); $stmt->close(); if($pending){ echo 'هناك إجازة قيد الإجراء لهذا الموظف.'; exit; } $start = new DateTime($start_date); $end = new DateTime($end_date); $requested_days = $start->diff($end)->days + 1; $current_year = (int)$start->format('Y'); switch ($type) { case 'اجازة سنوية': $to = new DateTime($end_date); $age = $to->diff( new DateTime($birth_date) )->y; $service_years = $to->diff( new DateTime($hire_date) )->y; $annual_quota = ($age >= 50 || $service_years >= 20) ? 45 : 30; $stmt = $con->prepare("SELECT COALESCE(SUM(DATEDIFF(end_date,start_date)+1),0) FROM vacations WHERE emp_id = ? AND type = 'اجازة سنوية' AND accept = 1 AND YEAR(start_date)=?"); $stmt->bind_param("ii",$emp_id,$current_year); $stmt->execute(); $stmt->bind_result($used); $stmt->fetch(); $stmt->close(); $remaining = $annual_quota - $used; if ($remaining <= 0){ echo 'استهلك الموظف كامل رصيده السنوى لهذا العام.'; exit; } if ($requested_days > $remaining){ echo "الرصيد المتبقى $remaining يوم ولا يمكنك طلب $requested_days يوم."; exit; } if ($requested_days < 15){ $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id = ? AND type='اجازة سنوية' AND accept = 1 AND YEAR(start_date)=? AND (DATEDIFF(end_date,start_date)+1) >= 15"); $stmt->bind_param("ii",$emp_id,$current_year); $stmt->execute(); $stmt->bind_result($have15); $stmt->fetch(); $stmt->close(); if(!$have15){ echo 'يجب أن يتمتع الموظف بحد أدنى 15 يوم متصلة فى السنة.'; exit; } } break; case 'اجازة مرضية': $stmt = $con->prepare("SELECT COALESCE(SUM(DATEDIFF(end_date,start_date)+1),0) FROM vacations WHERE emp_id = ? AND type = 'اجازة مرضية' AND accept = 1 AND YEAR(start_date)=?"); $stmt->bind_param("ii",$emp_id,$current_year); $stmt->execute(); $stmt->bind_result($used); $stmt->fetch(); $stmt->close(); if ($requested_days > 45){ echo 'الحد الأقصى المستمر للإجازة المرضية هو 45 يوم.'; exit; } if ( ($used + $requested_days) > 60 ){ $left = 60 - $used; echo "المتبقى من رصيد الإجازة المرضية هذا العام هو $left يوم."; exit; } break; case 'اجازة الحج': $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id=? AND type='اجازة الحج' AND accept=1"); $stmt->bind_param("i",$emp_id); $stmt->execute(); $stmt->bind_result($taken); $stmt->fetch(); $stmt->close(); if($taken){ echo 'تمّ الحصول على إجازة الحج من قبل، لا تُمنح إلا مرة واحدة.'; exit; } if ($requested_days > 20){ echo 'الحد الأقصى لإجازة الحج 20 يوم.'; exit; } break; case 'اجازة زواج': $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id=? AND type='اجازة زواج' AND accept=1"); $stmt->bind_param("i",$emp_id); $stmt->execute(); $stmt->bind_result($taken); $stmt->fetch(); $stmt->close(); if($taken){ echo 'تمّ الحصول على إجازة زواج سابقًا، لا تُمنح إلا مرة واحدة.'; exit; } if ($requested_days > 14){ echo 'الحد الأقصى لإجازة الزواج هو 14 يوم.'; exit; } break; case 'اجازة وفاة الزوج': if ($gender != 'أنثى'){ echo 'إجازة وفاة الزوج خاصة بالإناث فقط.'; exit; } $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id=? AND type='اجازة وفاة الزوج' AND accept=1"); $stmt->bind_param("i",$emp_id); $stmt->execute(); $stmt->bind_result($taken); $stmt->fetch(); $stmt->close(); if($taken){ echo 'تمّ الحصول على هذه الإجازة سابقًا، لا تُمنح إلا مرة واحدة.'; exit; } if ($requested_days != 130){ echo 'مدة الإجازة هى 4 أشهر و10 أيام (130 يوم) ويجب إدخال المدة كاملة.'; exit; } break; default: echo 'نوع الإجازة غير معروف'; exit; } $interval = $start->diff($end); $years = $interval->y; $months = $interval->m; $days_only = $requested_days; $stmt = $con->prepare("INSERT INTO vacations (emp_id,years,months,days,reason,companion,type,start_date,end_date,created_at) VALUES (?,?,?,?,?,?,?,?,?,?)"); $stmt->bind_param("iiiisissss", $emp_id,$years,$months,$days_only,$reason,$companion, $type,$start_date,$end_date,$created_at); if($stmt->execute()){ echo "<script> Swal.fire({title:'تم',text:'تم إضافة الإجازة بنجاح',icon:'success'}); </script>"; echo '<meta http-equiv="refresh" content="2;url=vacations.php">'; } else { echo 'حدث خطأ أثناء الحفظ: '.$stmt->error; } $stmt->close(); }
  23. قم بفتح منفذ الأوامر م نفذ الأمر التالي لتشغيل خادم apache و mysql: sudo /opt/lampp/lampp start ثم توجه لرابط المشروع في المتصفح مجددًا.
  24. هل السؤال خاص بأحد الدروس؟ في حال ذلك، ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
  25. الفكرة كالتالي، ستطلب من المستخدم إدخال بريده الإلكتروني المرتبط بالحساب ولو البريد الإلكتروني موجود في قاعدة البيانات، قم بإنشاء رمز وهو Token فريد ومؤقت ثم إرسال رابط إلى البريد الإلكتروني يحتوي على الرمز الفريد. وعند النقر على الرابط، اسمح للمستخدم بتعيين كلمة مرور جديدة. لذا قاعدة البيانات يجب أن تحتوي على جدول لتخزين الرموز المؤقتة associated مع المستخدم ووقت الانتهاء: CREATE TABLE password_resets ( id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255) NOT NULL, token VARCHAR(255) NOT NULL, expires_at DATETIME NOT NULL ); ونموذج طلب إعادة التعيين: <form action="request_reset.php" method="POST"> <input type="email" name="email" required placeholder="أدخل بريدك الإلكتروني"> <button type="submit">استعادة كلمة المرور</button> </form> ثم تثبيت مكتبة PHPMailer: composer require phpmailer/phpmailer ثم إنشاء منطق وإرسال رمز إعادة التعيين من خلال ملف وليكن باسم request_reset.php: <?php require 'vendor/autoload.php'; require 'db.php'; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; if ($_SERVER["REQUEST_METHOD"] == "POST") { $email = filter_var($_POST["email"], FILTER_SANITIZE_EMAIL); $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?"); $stmt->execute([$email]); if ($stmt->rowCount() > 0) { $token = bin2hex(random_bytes(32)); $expires = date("Y-m-d H:i:s", strtotime('+1 hour')); $stmt = $pdo->prepare("INSERT INTO password_resets (email, token, expires_at) VALUES (?, ?, ?)"); $stmt->execute([$email, $token, $expires]); $reset_link = "https://mustafa.com/reset_password.php?token=$token"; $mail = new PHPMailer(true); try { $mail->isSMTP(); $mail->Host = 'smtp.yourmailserver.com'; $mail->SMTPAuth = true; $mail->Username = 'ضع الإيميل هنا@yourdomain.com'; $mail->Password = 'الباسورد هنا'; $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; $mail->Port = 587; $mail->setFrom('no-reply@yourdomain.com', 'Support'); $mail->addAddress($email); $mail->isHTML(true); $mail->Subject = 'إعادة تعيين كلمة المرور'; $mail->Body = "لقد طلبت إعادة تعيين كلمة المرور. اضغط على الرابط التالي:<br><a href='$reset_link'>$reset_link</a><br>إذا لم تطلب ذلك، تجاهل الرسالة."; $mail->send(); echo "تم إرسال رابط استعادة كلمة المرور إلى بريدك الإلكتروني إذا كان موجودًا في النظام."; } catch (Exception $e) { echo "حدث خطأ أثناء إرسال البريد الإلكتروني."; } } else { echo "تم إرسال رابط استعادة كلمة المرور إلى بريدك الإلكتروني إذا كان موجودًا في النظام."; } } ?> ثم ملف إعادة تعيين كلمة المرور reset_password.php: <?php if (!isset($_GET['token'])) exit('رمز غير صالح!'); $token = $_GET['token']; require 'db.php'; $stmt = $pdo->prepare("SELECT email FROM password_resets WHERE token = ? AND expires_at > NOW()"); $stmt->execute([$token]); $user = $stmt->fetch(); if (!$user) exit('الرابط غير صالح أو انتهت صلاحيته!'); if ($_SERVER["REQUEST_METHOD"] == "POST") { $new_password = $_POST["password"]; $hashed = password_hash($new_password, PASSWORD_DEFAULT); $stmt = $pdo->prepare("UPDATE users SET password = ? WHERE email = ?"); $stmt->execute([$hashed, $user['email']]); $stmt = $pdo->prepare("DELETE FROM password_resets WHERE email = ?"); $stmt->execute([$user['email']]); echo "تم تحديث كلمة المرور بنجاح!"; exit; } ?> <form method="POST"> <input type="password" name="password" required placeholder="كلمة المرور الجديدة"> <button type="submit">إعادة تعيين كلمة المرور</button> </form> لاحظ password_hash وpassword_verify لحفظ والتحقق من كلمة المرور، والأفضل تحديد صلاحية رمز إعادة التعيين لمدة محدودة مثلاً ساعة واحدة، ولا يجب توضيح هل البريد متوفر أم لا في الاستجابة لتجنب هجمات التخمين. أيضًا لمنع هجمات إعادة الإرسال، احذف الرمز بعد استخدامه مباشرة.
×
×
  • أضف...