-
المساهمات
19761 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
472
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Mustafa Suleiman
-
لا تشغلك بالك كثيرًا بمثل تلك الأمور استمر في التعلم وتطوير مستواك وتعميق فهمك فذلك ما يضمن مستقبلك إن شاء الله، الأمر مؤثر بالفعل لكن ليس بالشكل الذي تتوقعه أي الاستبدال التام، بل أدوات مساعدة لك لتنفيذ المهام المتكررة والمعروفة في كل مشروع بجانب تنفيذ بعض الأمور طالما لديك القدرة على وصف ما تريده، ولكن في المهام المعقدة الأمر كل عائد إليك. فكر بها مثل الآلة الحاسبة، هل اختفى مدرسي الرياضيات؟ بالطبع لا، لكن تم استخدامها كأداة مساعدة لتقليل عبء حساب المسائل البسيطة وبعض الآلات الحاسبة تستطيع حل المسائل المتوسطة، لكن مهمة حل المسألة في يدك أنت فهي لا تفهم المسألة بالكامل بل مُدربة على الحل بطريقة معينة. بالتالي الأدوات المساعدة عمومًا لن تمحو الحاجة إلى المبرمج، بل ستُغير شكل عمله وطريقة إنجازه للمهام، فهي لا تفهم السياق الكامل للمنتج، ولا تصمّم البنية المعمارية System Design للمشروع أو تتخذ قرارات عمل وأولويات، فكلها تتطلب مبرمج ذو خبرة. مُدرس الرياضيات أصبح يعتمد على الآلة الحاسبة لتسريع عمله في حل المسائل، نفس الأمر بالنسبة لك استخدم ما هو متوفر من أدوات للإنتاج بشكل أفضل، فذلك المطلوب في سوق العمل. لكن لا تقم بذلك إلا بعد دراسة الأساسيات بشكل قوي والتعمق بها، وعدم الإعتماد عليها كل الإعتماد، فذلك من شأنه خفض مستواك وليس رفعه.
- 5 اجابة
-
- 1
-
-
ما هو الكورس الذي قمت بدراسته؟
-
المشكلة أنّ المسار خطأ، وليس لها علاقة بالـ 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
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
- 2 اجابة
-
- 1
-
-
الأفضل أن يرى المستخدم قائمة بكل الترقيات المُسجلة، مع أهم المعلومات التى تسمح له بالبحث، الفرز، والانتقال سريعاً إلى تفاصيل أو تعديل الترقية، والمعلومات التى يجب عرضها تُستخرج من جدول 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 اجابة
-
- 1
-
-
في المتحكم في دالة 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')){ }
-
بناءًا على ما درسته، متاح لك دورة تطوير التطبيقات بواسطة جافاسكريبت، ومن خلالها تستطيع تعلم تطوير الواجهة الأمامية والخلفية أيضًا من خلال تقنيات MERN وهم MongoDB وExpress.js و React و Node.js. كذلك تعلم تطوير تطبيقات الهاتف من خلال React Native، وأيضًا تطبيقات سطح المكتب من خلال Electrone.js، أيضًا بها شرح لكيفية تضمين الذكاء الاصطناعي في المشاريع. بالتالي الدورة شاملة وستصبح مطور Full-stack وذلك مطلوب في سوق العمل حاليًا، وأنت قد تعلمت اللغات الأساسية للويب بالفعل وهم HTML, CSS, JS، لذا تحتاج إلى تطوير مهاراتك بتعلم تقنيات جافاسكريبت. متاح لك أيضًا دورة الذكاء الاصطناعي، ومن خلالها تستطيع أن تصبح محلل بيانات أو مطور ذكاء اصطناعي، أي هي الدورة الأنسب لدراسة الذكاء الاصطناعي بعمق والتخصص به في حال ذلك ما تريده. وفي حال أردت التخصص في الواجهة الخلفية فقط فلديك دورة PHP، وستتعلم بها أساسيات اللغة وإطار لارافل الشهير الخاص بها بالإضافة إلى ووردبريس، وكلاهما مطلوبين بشدة في مواقع العمل الحر، ولديك أساسيات الواجهة الأمامية لذا تستطيع أن تصبح مطور Full-stack. وأيضًا دورة بايثون، وهي الأقرب لدورة الذكاء الاصطناعي، حيث أنّ لغة بايثون هي اللغة الأساسية في ذلك المجال ومجال تحليل البيانات، ومن خلالها أيضًا ستتعلم إطار جانغو والذي يسمح لك بتطوير مشاريع Full-stack.
- 4 اجابة
-
- 1
-
-
مرحبًا بأهل غزة الكرام، الجميع يتفهم الوضع، لذا أرجو التحدث مع مركز المساعدة وإرسال نفس الرسالة وسيتم الرد عليك إن شاء الله، حيث الأمور المالية يتم مناقشتها من خلالهم وليس من خلال قسم أسئلة البرمجة.
- 2 اجابة
-
- 1
-
-
جميع الدورات بالأكاديمية لا تشترط وجود أي خبرة برمجية مُسبقة، ففي كل دورة يوجد مسارات خاصة بالأساسيات اللازمة لتعلم التخصص الخاص بالدورة، أي الدورة موجهة للمبتدئين في المقام الأول، وبالطبع توجد مسارات متقدمة في الدورة يستطيع من لديه خبرة دراستها لتحسين مهاراته، لذا تناسب الجميع. لأنّ الدورة تم إعدادها بشكل ممنهج بحيث تكون المسارات متدرجة من البداية ثم صعودًا نحو المستوى المتقدم، من خلال شرح الأساسيات ثم تطبيقات عليها ثم شرح التقنيات الخاصة باللغة، ثم مشاريع عملية كاملة على التقنيات الخاصة باللغة ثم مفاهيم متقدمة.
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
-
0 bytes مفادها أنّ الملف part1 به مشكلة، هل قمت بتحميله بشكل صحيح أو حدث خطأ أثناء تحميله أو نقله؟ عامًة حاول تثبيت UnRAR: sudo apt install unrar ثم تنفيذ الأمر التالي في مسار المجلد الذي به الملفات: unrar x اسم الملف الذي تريد فك ضغطه أو تجربة أداة أخرى وهي 7-Zip: sudo apt install p7zip-full p7zip-rar ثم تنفيذ: 7z x اسم الملف لو استمرت المشكلة، فالملفات معطوبة.
- 3 اجابة
-
- 1
-
-
الفكرة ليس في التطبيق على كل ساعة، بل في التطبيق على مفهوم معين تعلمته، مثلاً تعلمت أساسيات حلقات التكرار في بايثون، هنا تتوقف وتقوم بتنفيذ تمرين للتطبيق على ذلك المفهوم، وربط التمرين بما تعلمته سابقًا أي القوائم والمتغيرات والجمل الشرطية وهكذا. في حال كان الدرس طويل أو به مفاهيم مختلفة، أرجو قراءة التالي: في بعض الدروس ستجد شرح نظري، هنا يتعين عليك الاستيعاب قدر الإمكان والسؤال عن الأمور الغير واضحة لك لتفصيلها وتبسيط، وبعد فترة من التطبيق العملي سيتضح لك الأمر أكثر. ولا يوجد مدة محددة للتطبيق، الأمر كله يعود للوقت المتوفر لك وتحتاج إلى إدارته، عامًة عليك تخصيص 50% من وقتك للتطبيق العملي. وللعلم مجال الذكاء الاصطناعي يعتبر ضمن أكثر مجالات البرمجة تعقيدًا وبحاجة إلى مجهود واستيعاب أكثر من باقي المجالات. لذا يجب دراسة الدورة بهدف الاستيعاب وليس بهدف إنهائها في أسرع وقت، البحث والمشاهدة بجانب ما يتم شرحه أمر لابد منه وذلك حال أي دورة في أي مكان، فلا توجد تلك الدورة التي تقدم لك كل شيء. وإدارة مجهودك بذكاء من خلال معرفة ما يجب عليك تعلمه في البداية وما تحتاجه لاحقًا، فبطبيعة الحال توجد أساسيات ثم أمور خاصة بالمستوى المتوسط ويليها المستوى المتقدم. اتبع قاعدة 20 - 80 وهو مبدأ باريتو، الفكرة الأساسية هي أن 20% من المجهود تغطي 80% من النتائج أو المهام المطلوبة. وبالتطبيق على الدورة، ركز على تعلم أساسيات البرمجة كالمتغيرات، الحلقات، الدوال، والهياكل البيانية (القوائم والمصفوفات) لحل 80% من المشكلات البرمجية البسيطة إلى المتوسطة. وفي التطبيق العملي عليك قضاء 20% من وقتك في تعلم النظريات و80% في كتابة الكود وحل المشكلات العملية يساعد على تثبيت المعرفة. بعد فترة من الوقت لن تصلح تلك القاعدة بسبب تعقيد مجال الذكاء الاصطناعي، ويجب تعميق الفهم لما يتجاوز استيعاب الأساسيات، أي قاعدة 20% لن تجدي نفعًا بعد فترة لكن ستفيدك في البداية.
- 4 اجابة
-
- 1
-
-
استخدم الدالة التالية سواء في نفس الملف أو في ملف آخر وتستطيع استدعائها: 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>";
- 14 اجابة
-
- 1
-
-
كل شيء كما هو، فقط استبدل الكود بداخل كتلة الشرط if ($_SERVER["REQUEST_METHOD"] == "POST")
- 14 اجابة
-
- 1
-
-
عليك جلب التاريخ 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(); }
-
قم بفتح منفذ الأوامر م نفذ الأمر التالي لتشغيل خادم apache و mysql: sudo /opt/lampp/lampp start ثم توجه لرابط المشروع في المتصفح مجددًا.
- 5 اجابة
-
- 1
-
-
هل السؤال خاص بأحد الدروس؟ في حال ذلك، ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم أسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
-
الفكرة كالتالي، ستطلب من المستخدم إدخال بريده الإلكتروني المرتبط بالحساب ولو البريد الإلكتروني موجود في قاعدة البيانات، قم بإنشاء رمز وهو 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 لحفظ والتحقق من كلمة المرور، والأفضل تحديد صلاحية رمز إعادة التعيين لمدة محدودة مثلاً ساعة واحدة، ولا يجب توضيح هل البريد متوفر أم لا في الاستجابة لتجنب هجمات التخمين. أيضًا لمنع هجمات إعادة الإرسال، احذف الرمز بعد استخدامه مباشرة.
- 5 اجابة
-
- 1
-
-
لم تذكر السبب؟ هل هو لمجال العمل الحر؟ ما الدافع لتعلمه؟ عامًة ليس عليك ذلك نفس الأمر بالنسبة لتعلم لغة جديدة خاصة بالواجهة الخلفية ولتكن C# أو Go أو بايثون، أو حتى إطار خاص بلغة PHP مثل إطار NativePHP. كن مرنًا ولا تجعل نفسك محصورًا في تقنية معينة، أي أن تكون مهندس برمجيات software engineer وليس مطور programmer فقط. وإلا ستبقى محصورًا فقط في المشاريع التي تتطلب لارافل، وفي حال هناك مشروع يتطلب Odoo فلن تتمكن من تقديم عرض عليه أو العمل عليه في حال كنت في شركة. كل ما ستتعلمه سيضيف إليك وليس العكس، وتصبح قادر على العمل على مشاريع أكثر في مجال العمل الحر أو تنفيذ ما تريد في حال تعمل بمفردك أو تضيف إلى مهارة وزيادة قيمتك عند العمل في الشركات. بالطبع لا أقصد أن تقوم بتشتيت نفسك في بدايات تعلمك، لكن بعد الوصول لمستوى متوسط في تخصص معين، كن مرنًا ولا تخف من تعلم تقنية جديدة.
- 4 اجابة
-
- 2
-
-
-
حسب ما ذكرت أنت تريد المنطق التالي: كل 6 شهور للموظف = 15 يوم رصيد إجازة سنوية يبدأ التراكم بعد سنة من التعيين، لو تاريخ التعيين 12-01-1999، يبدأ التراكم من 12-01-2000. كل إجازة تخصم من الرصيد المتراكم وليس السنوي فقط. يجوز للموظف أن يأخذ أي عدد من الإجازات السنوية متى ما توفر له رصيد. لا يوجد سقف سنوي للإجازة، متاح أن يحصل الموظف على إجازتين طويلتين في سنتين متتاليتين لو له رصيد. والكود لديك يتبع المنطق السابق لا مشكلة، لكن المنطق به بعض التعقيد في التواريخ غير ضروري، ويكفي أن تبدأ من تاريخ التعيين + سنة واحدة، وتكرر كل 6 شهور حتى اليوم، أو تستطيع التمرير حتى تاريخ نهاية الإجازة المطلوبة لو أردت مزيد من الدقة. وعند تمرير المتغيرات للدالة هنا: $start_date_calc = new DateTime($employee['start_date']); $start_date_calc->modify('+1 year'); $start_date_calc = $start_date_calc->format('Y-m-d'); $stmt = $con->prepare("SELECT SUM(days) as total_days FROM vacations WHERE emp_id = ? AND accept = 1"); $used_days = $row['total_days'] ? $row['total_days'] : 0; $vacation_balance = calculateVacationBalance($start_date_calc, $used_days); الكود يعمل لكن الأفضل، تنفيذ المنطق بحيث لو الموظف متقدم بطلب إجازة تبدأ في تاريخ مستقبلي 1-1-2026، إذًا يجب جمع الأيام كلها حتى تلك اللحظة أي الإجازات المنتهية قبل 1-1-2026، وتراكم الرصيد أيضاً حتى نفس التاريخ، وهكذا تجعل التحقق دقيق، حتى لو سجل الموظف أكثر من إجازة في نفس الوقت لا يحدث تجاوز للرصيد، كالتالي: <?php include('header.php'); error_reporting(0); ini_set('display_errors', 0); function calculateVacationBalance($hireDate, $toDate, $usedDays) { $start = new DateTime($hireDate); $start->modify('+1 year'); $to = new DateTime($toDate); $totalAccruedDays = 0; while ($start <= $to) { $totalAccruedDays += 15; $start->modify('+6 months'); } $totalAccruedDays -= $usedDays; return $totalAccruedDays; } ?> <head> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script> <style> .rak { width: 400px; height: 300px; font-size: 14px !important;} </style> </head> <div class="col-md-9 pan1"> <ol class="breadcrumb" style="background-color: #fff;padding-top:8px;padding-bottom:8px;color:#000;font-size:16px;"> <li><a href="vacations.php">الاجازات</a></li> <li class="active">اضافة اجازة جديد</li> </ol> </div> </div> <div class="row"> <div class="col-md-9 pan1"> <div class="panel" style="color:#000;"> <div class="panel-body" style="font-size:14px; padding-left:40px;padding-right:40px;padding-bottom:25px;padding-top:25px;"> <form method="POST" enctype="multipart/form-data"> <div class="row"> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <label>الموظف</label> <select name="emp_id" id=""> <?php $sql = "SELECT e.person_id, p.name FROM employees e JOIN people p ON e.person_id = p.id;"; $result = $con->query($sql); while ($row = $result->fetch_assoc()) { echo "<option value='{$row['person_id']}'>{$row['name']}</option>"; } ?> </select> </div> </div> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <label>نوع الاجازة</label> <select name="type" id=""> <option value="اجازة مرضية">اجازة مرضية</option> <option value="اجازة وضع">اجازة وضع</option> <option value="اجازة بدون مرتب">اجازة بدون مرتب</option> <option value="اجازة زواج">اجازة زواج</option> <option value="اجازة سنوية">اجازة سنوية</option> </select> </div> </div> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <label>تاريخ البداية</label> <input name="start_date" type="date" class="form-control"> </div> </div> </div> <div class="row"> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <label>تاريخ المباشرة</label> <input name="end_date" type="date" class="form-control"> </div> </div> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <label>سبب الاجازة</label> <input name="reason" type="text" class="form-control" placeholder="ادخل سبب الاجازة"> </div> </div> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <label>الموافقة مسبقا</label> <input name="companion" type="checkbox" class="form-control"> </div> </div> </div> <div class="row"> <div class="col-md-4"> <div class="form-group" style="margin-top:10px;"> <button name="submit" type="submit" class="btn btn-primary">إضافة <span class="ion-android-add"></span></button> <button type="reset" class="btn btn-danger">إلغاء <span class="ion-android-delete"></span></button> </div> </div> </div> </form> <?php if ($_SERVER["REQUEST_METHOD"] == "POST") { $emp_id = $_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'); $start = new DateTime($start_date); $end = new DateTime($end_date); $interval = $start->diff($end); $years = $interval->y; $months = $interval->m; $days = $interval->d; $requested_days = $end->diff($start)->days; $errors = []; if (empty($type)) { $errors[] = 'يجب تحديد نوع الإجازة'; } if (empty($start_date)) { $errors[] = 'يجب إدخال تاريخ بداية الإجازة'; } if (empty($end_date)) { $errors[] = 'يجب إدخال تاريخ المباشرة'; } if ($end <= $start) { $errors[] = 'تاريخ المباشرة يجب أن يكون بعد بداية الإجازة'; } if (!empty($errors)) { echo implode('<br>', $errors); exit; } mysqli_begin_transaction($con); try { $stmt = $con->prepare("SELECT * FROM employees WHERE person_id = ?"); $stmt->bind_param("i", $emp_id); $stmt->execute(); $employee = $stmt->get_result()->fetch_assoc(); $stmt->close(); if (!$employee) { echo "لم يتم العثور على بيانات الموظف"; exit; } // تحقق لا يوجد إجازة قيد الإجراء $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id = ? AND accept = 0"); $stmt->bind_param("i", $emp_id); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); if ($count > 0) { echo "عذرًا، هنالك إجازة قيد الإجراء للموظف الحالي، الرجاء التحقق."; exit(); } $stmt = $con->prepare("SELECT * FROM people WHERE id = ?"); $stmt->bind_param("i", $emp_id); $stmt->execute(); $people = $stmt->get_result()->fetch_assoc(); $stmt->close(); if ($type == "اجازة وضع" && $people['gender'] == "ذكر") { echo "عذرًا، لا يمكن إعطاء هذا النوع من الإجازة للموظف المختار."; exit(); } if ($type == "اجازة زواج") { $stmt = $con->prepare("SELECT COUNT(*) FROM vacations WHERE emp_id = ? AND type = ? "); $stmt->bind_param("is", $emp_id, $type); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); if ($count > 0) { echo "عذرًا، الموظف المختار قد حصل على إجازة زواج مسبقًا."; exit(); } $stmt = $con->prepare("SELECT start_date, end_date FROM vacations WHERE emp_id = ? AND type = ?"); $stmt->bind_param("is", $emp_id, $type); $stmt->execute(); $stmt->bind_result($s, $e); $stmt->fetch(); $stmt->close(); if ($s && $e) { $days = (new DateTime($e))->diff(new DateTime($s))->days; if ($days > 14) { echo "عذرًا، إجازة الزواج لا يمكن أن تتجاوز أسبوعين."; exit(); } } } if ($type == "اجازة سنوية") { $hire_date = $employee['start_date']; $requested_start_str = $start->format('Y-m-d'); $stmt = $con->prepare(" SELECT COALESCE(SUM(DATEDIFF(end_date, start_date)),0) AS used FROM vacations WHERE emp_id = ? AND type = 'اجازة سنوية' AND accept = 1 AND end_date <= ? "); $stmt->bind_param("is", $emp_id, $requested_start_str); $stmt->execute(); $stmt->bind_result($used_days); $stmt->fetch(); $stmt->close(); $vacation_balance = calculateVacationBalance($hire_date, $requested_start_str, $used_days); if ($vacation_balance < $requested_days) { echo "عذرًا، لا يمكن إنشاء الإجازة لعدم توفر الرصيد الكافي. رصيدك: $vacation_balance يوم، والطلب: $requested_days يوم"; exit(); } } if ($type == "اجازة بدون مرتب" ) { $days = 365; } $stmt = $con->prepare("INSERT INTO vacations (emp_id, years, months, days, reason, companion, type, start_date, end_date, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $start_date_formatted = $start->format('Y-m-d'); $end_date_formatted = $end->format('Y-m-d'); $stmt->bind_param("iiiisissss", $emp_id, $years, $months, $requested_days, // الآن أصبحت days هي فارق الأيام $reason, $companion, $type, $start_date_formatted, $end_date_formatted, $created_at ); if ($stmt->execute()) { echo "<script> Swal.fire({ title: 'رسالة تأكيد', text: 'تم إضافة بيانات اجازة موظف بنجاح!', icon: 'success', customClass: 'rak', }); </script>"; echo '<meta http-equiv="refresh" content="2;url=vacations.php" />'; } $stmt->close(); mysqli_commit($con); } catch (Exception $e) { mysqli_rollback($con); echo "خطأ: " . $e->getMessage(); exit; } } ?> </div> </div> </div> </div> <?php include('footer.php'); ?>
