-
المساهمات
19881 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
475
نوع المحتوى
ريادة الأعمال
البرمجة
التصميم
DevOps
التسويق والمبيعات
العمل الحر
البرامج والتطبيقات
آخر التحديثات
قصص نجاح
أسئلة وأجوبة
كتب
دورات
كل منشورات العضو Mustafa Suleiman
-
لا يُشترط ذلك، الفكرة هي أنّ الأمر سيصبح أسهل بمراحل بسبب المعرفة التي ستكتسبها، لكن تستطيع تعلم بايثون بدون دراسة علوم الحاسوب. الفكرة هي أنك لن تتمكن من معرفة كيف تعمل بعض الأمور في الخلفية وما سببها وهكذا. في حال تواجه صعوبة في فهم بعض الأمور، من الأفضل البدء بها بالطبع، أو مثلاً ليس لديك أي احتكاك بالحاسوب وما يتعلق به وتستخدمه بشكل عادي. من الصعب إعطائك نصيحة بشكل عام دون معرفة تفاصيل عنك ستجد تفصيل هنا:
-
تقوم باستدعاء Auth::routes() مرتين، والاستدعاء الثاني (مع ['register' => false]) يقوم بإلغاء الأول. أولاً قم بإزالة استدعاء Auth::routes() المكرر، فأنت تحتاج فقط إلى استدعاء Auth::routes() مرة واحدة لتحديد مسارات المصادقة. ثم تمرير الخيار ['register' => false] من خلال تمرير ذلك الخيار داخل استدعاء Auth::routes() الفردي، وبذلك تخبر Laravel باستبعاد مسارات التسجيل. <?php use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; use App\Http\Controllers\StudentController; Route::get('/', function () { return view('welcome'); }); Route::get('/student', [StudentController::class, 'index'])->name('student'); Route::get('/student.edit', [StudentController::class, 'edit'])->name('student.edit'); Route::get('/create', [StudentController::class, 'create'])->name('create'); Route::get('/student.destroy', [StudentController::class, 'destroy'])->name('student.destroy'); Route::post('/store', [StudentController::class, 'store'])->name('storestudent'); Auth::routes(['register' => false]); Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])->name('home');
-
في البداية كلاهما مختلفان، Segment Tree تلك خوارزمية بينما Dynamic Programming هي تقنية أو مفهوم في لغات االبرمجة. أولاً شجرة المقطع أو Segment Tree عبارة عن بنية بيانات لتخزين المعلومات حول الفواصل الزمنية أو الأجزاء، مما يسمح بالاستعلام وتحديث الفواصل الزمنية بكفاءة. وتعمل بالآلية التالية، أولاً البناء وبه يتم بناء شجرة المقطع لتخزين قيم مصفوفة معينة في شكل شجرة ثنائية، كل عقدة في الشجرة تمثل فاصل زمني معين من المصفوفة. ثم الاستعلام، حيث تستخدم شجرة المقطع للعثور على إجابة لاستعلام معين حول فاصل زمني معين، مثل إيجاد الحد الأدنى أو مجموع القيم في هذا الفاصل. بعد ذلك التحديث، بتعديل القيم في المصفوفة الأصلية، وتحديث الشجرة بشكل فعال. أداء الخوارزمية: بناء شجرة المقطع في زمن (O(n \log n)). تنفيذ الاستعلام في زمن (O(\log n)). تنفيذ التحديث في زمن (O(\log n)). بالتالي تستخدم في مشاكل الفواصل الزمنية، مثل مجموع الفواصل الزمنية، الحد الأدنى للفواصل الزمنية، إلخ، وتحديث الفواصل الزمنية بكفاءة. تخيل أنك أنت بحاجة إلى حساب عدد الكتب الموجودة في مجموعة معينة من الأرفف بسرعة، فكم عدد الكتب الموجودة بين الرف رقم 10 والرف رقم 20؟ بنفس الآلية التي شرحناها نقوم بالتالي: البناء تقسم المكتبة إلى أجزاء أصغر وتخزن عدد الكتب في كل جزء. الاستعلام عندما تسأل عن عدد الكتب بين رفوف معينة، يمكنك الوصول إلى الأجزاء المناسبة بسرعة وجمع الأعداد بسهولة. التحديث عند إضافة أو إزالة كتب من الرفوف، يمكنك تحديث الشجرة بسرعة بحيث تعكس التغييرات. بينما Dynamic Programming البرمجة الديناميكية هي تقنية في البرمجة ونستخدمها في الخوارزميات لحل المشاكل المعقدة عن طريق تقسيمها إلى مشاكل فرعية أبسط، وحل كل مشكلة فرعية مرة واحدة وتخزين الحلول في جدول لتجنب الحسابات المتكررة. أي هي الغرض منها حل المشاكل المعقدة عن طريق تقسيمها إلى مشاكل أصغر وحلها تدريجيًا وبالإمكان استخدام شجرة المقطع لتحسين الأداء في بعض مشاكل البرمجة الديناميكية التي تتطلب استعلامات وتحديثات متكررة على فواصل زمنية. لكن أحيانًا تكون البرمجة الديناميكية كافية لحل المشكلة، وللعلم استخدام شجرة المقطع قد يجعل الحل أكثر كفاءة في بعض السيناريوهات، خاصة عندما تتضمن المشكلة فواصل زمنية متعددة وتحديثات.
-
تستطيع ذلك، في الواقع يٌفضل إرجاء مساري الخوارزميات وأنماط التصميم إلى نهاية الدورة، لكونهما من أصعب المفاهيم البرمجية في بدايات التعلم، ولن تتمكن من فهمها بشكل كامل، وستتسائل ما الفائدة منها؟ لذا حاول فهمها بنسبة 50 ألى 70% وبعد فترة من تعلم البرمجة ووصولك لمرحلة المشاريع العملية الكاملة، وتنفيذ أكثر من مشروع، تستطيع الرجوع إليها ومراجتعها مرة أخرى وحينها ستفهم ما الفائدة منها.
- 2 اجابة
-
- 1
-
-
سيتم المتابعة معك بلا شك، أرجو الإنتظار لبعض الوقت. شكرًا لتفهمك.
-
ما تواجهينه يحدث للجميع، الفرق بين من أكملوا رحلة تعلم البرمجة ومن توقفوا أنهم حاولوا ومع الاستمرار والصبر يصبح الأمر أسهل فأسهل، الأمر أشبه بتعلم اللغة الإنجليزية مثلاً هل يمكن تعلمها مباشرًة وهل الأمر سهل في البداية؟ بالطبع لا، الأمر بحاجة لممارسة واستمرار. بخصوص الأمور المالية أرجو التحدث لمركز المساعدة وسيتم مساعدتك.
-
غالبًا هناك مشكلة في الإعدادات لديك، قم بالضغط على السهم بجانب علامة التشغيل واختر run in dedicated terminal إن لم يعمل قم بتجربة تحميل الإضافة التالية وتشغيل الكود https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner
-
تفقد هل المتغير البيئي NEXT_PUBLIC_API_DOMAIN قد تم تعريفه بشكل صحيح في ملف .env، وكمثال: NEXT_PUBLIC_API_DOMAIN=http://localhost:3000 أو ضع ذلك في ملف next.config.js. env: { NEXT_PUBLIC_API_DOMAIN: 'http://localhost:3000', }, }; أيضًا تفقد أن استدعاء fetchProperty يتم بشكل صحيح وأنه يعيد البيانات المناسبة بإضافة بعض رسائل التصحيح للتأكد من أن الدالة تعمل كما هو متوقع. بالمثل لـ useParams بإضافة رسالة تصحيح للتأكد من أن id يتم التعرف عليه بشكل صحيح. "use client" import React, { useEffect, useState } from "react"; import Link from "next/link"; import { useParams } from "next/navigation"; import { FaArrowLeft } from 'react-icons/fa'; import { fetchProperty } from "@/utils/requests"; const PropertyPage = () => { const [property, setProperty] = useState(null); const [loading, setLoading] = useState(true); const { id } = useParams(); console.log("Property ID: ", id); useEffect(() => { const fetchPropertyData = async () => { if (!id) return; try { const property = await fetchProperty(id); setProperty(property); } catch (error) { console.error('Error fetching property: ', error); } finally { setLoading(false); } }; fetchPropertyData(); }, [id]); console.log("Property Data: ", property); if (loading) return <h1>Loading...</h1>; if (!property) return <h1>No Property Found</h1>; return ( <> <section> <div className="container m-auto py-6 px-6"> <Link href="/properties" className="text-green-500 hover:text-green-600 flex items-center" > <FaArrowLeft className="mr-2" /> Back to Properties </Link> </div> </section> <section className="bg-green-50"> <div className="container m-auto py-10 px-6"> <div className="grid grid-cols-1 md:grid-cols-70/30 w-full gap-6"> <aside className="space-y-4"> property single page </aside> </div> </div> </section> </> ); }; export default PropertyPage; ولنتفقد هل الدالة fetchProperty تعمل بشكل صحيح، بإضافة بعض الرسائل التصحيحية للتأكد من أن البيانات تأتي كما هو متوقع. const apiDomain = process.env.NEXT_PUBLIC_API_DOMAIN || null; async function fetchProperty(id) { try { if (!apiDomain) { console.error('API domain not set'); return null; } const res = await fetch(`${apiDomain}/properties/${id}`); if (!res.ok) { throw new Error("Failed to fetch data"); } return res.json(); } catch (error) { console.log(error); return null; } } export { fetchProperty };
- 1 جواب
-
- 1
-
-
من البرامج المجانية لذلك هي Canva حيث توفر قوالب خطط عمل قابلة للتخصيص مع واجهة سهلة الاستخدام. أيضًا لديك Google Docs/Sheets/Slides لإنشاء خطة عمل احترافية باستخدام القوالب أو من البداية. نسخة الويب من Microsoft Word/Excel/PowerPoint مجانية وتستطيع تنفيذ ذلك من خلالها. لديك أيضًا LivePlan يقدم فترة تجريبية مجانية تسمح لك بإنشاء خطة عمل كاملة. بالنسبة للبرامج المدفوعة، يوجد Business Plan Pro يوفر مجموعة شاملة من الميزات لإنشاء خطط عمل احترافية، بما في ذلك القوالب والأمثلة والنصائح. بالإضافة إلى Enloop أداة سهلة الاستخدام لإنشاء خطط عمل، مع ميزة التنبؤ المالي التلقائي. و StratPad أيضًا أداة مرئية لإنشاء خطط عمل، مع التركيز على استراتيجية العمل. للمزيد لديك PlanGuru وStratPad.
- 1 جواب
-
- 1
-
-
في الإختبار يتم قياس مدى الاستيعاب لما تم شرحه ومدى الاستيعاب لما تم تنفيذه في التطبيقات العملية، بالتالي الإعتماد على جوجل غير مُصرح به. لن يتم سؤالك في جميع الأمور النظرية، بل الجانب العملي والأمور المتعلقة به لها النصيب الأكبر. في بداية تعلمك الاستيعاب والحفظ مهمين ثم التطبيق العملي لتوظيف ما تعلمتيه وتثبيته، ولا مشكلة بعد ذلك لو نسيتي بعض الأمور، ففور سؤالك عن أمر معين ستتذكري تلك الدالة لأنك قمتي بالتطبيق عليها واستوعبتي طريقة عملها وحفظتي ذلك سابقًا. ولا أقصد حفظ كل لغة البرمجة، بل أقصد استيعاب وحفظ ما ستقومين استخدامه بكثرة خاصًة الأساسيات، ولا مشكلة بعد ذلك لو نسيتي بعض الأمور، لكن هناك أساسيات لا يُعقل أن يتم نسيانها عند الإختبار. ستجدي تفصيل أكثر هنا:
-
أرجو توضيح متى تحدث معك المشكلة لمساعدتك بشكل أفضل فعند زيارة الرابط كان يعمل بشكل سليم
-
يعمل بشكل سليم، قم بحذف الكاش من خلال: php artisan optimize:clear
- 14 اجابة
-
- 1
-
-
ليست نفس المشكلة، لديك حاليًا مسار student.edit غير معرف، عليك تعريفه بنفس الكيفية التي تم شرحها سابقًا في التعليقات
-
بسبب إنشاء Promise داخل مكون عميل Client Component باستخدام fetchProperty داخل useEffect. للتوضيح، مكونات العميل و SSR في Next.js، يتم تشغيل مكونات العميل (المُعلّمة بـ "use client") في المتصفح، بينما تشغيل مكونات الخادم Server Components على الخادم. بالتالي عندما تستخدم async/await داخل مكون عميل، فأنت تحاول بشكل أساسي إيقاف تنفيذ JavaScript على الخادم أثناء انتظار اكتمال الوعد، وذلك غير ممكن لأن مكونات العميل لا يتم تنفيذها على الخادم. أيضًا تستخدم React مفهوم "Suspense" للتعامل مع الحالات غير المتزامنة (مثل جلب البيانات). إذن عند مواجهة React مكونًا في حالة "suspended" (أي في انتظار وعد)، فإنه ينتظر حتى يتم حل ذلك الوعد قبل عرض المكون، ولكن الطريقة التي تستخدم بها async/await في الكود لا تتكامل بشكل صحيح مع آلية Suspense في React. وعند إزالة async، فإن fetchPropertyData تصبح دالة عادية لا تُرجع وعدًا، وبالتالي، لا يكون هناك انتظار للوعد، ويصبح تنفيذ الكود متزامنًا. أي أنّ React لا يواجه أي مكونات في حالة "suspended"، وبالتالي لا يتم طرح أي خطأ. لذا إما حذف async من المكون وإخبار Next.js أنك تقوم بإرجاع عناصر JSX، وترك الأمر لخطاف useEffect لتولي الأمر، كالتالي: "use client" import React, { useEffect, useState } from "react"; import Link from "next/link"; import { useParams } from "next/navigation"; import { FaArrowLeft } from 'react-icons/fa'; import { fetchProperty } from "@/utils/requests"; const PropertyPage = () => { const [property, setProperty] = useState(null) const [loading, setLoading] = useState(true) const { id } = useParams() useEffect(() => { const fetchPropertyData = async () => { if (!id) return try { const property = await fetchProperty(id) setProperty(property) } catch (error) { console.error('Error fetching property', error) } finally { setLoading(false) } if (property === null) { fetchPropertyData() } } fetchPropertyData() // نقوم هنا بنداء الدالة مباشرًة }, [id, property]) return ( // باقي الكود ); }; export default PropertyPage; أو نقل جلب البيانات إلى مكون خادم بإنشاء مكون خادم (بدون "use client") لجلب البيانات باستخدام fetchProperty، ثم مرر البيانات ك props إلى مكون العميل PropertyPage.
- 2 اجابة
-
- 1
-
-
الإجابة على مثل ذلك السؤال ستضرك أكثر من نفعها، أنت لم تحدد سوق العمل الذي ترغب بالعمل به، تحديد الإجابة بشكل عام أمر غير صحيح. فهناك أسواق بحاجة إلى React Native وأخرى إلى Flutter، لذا ما هو سوق العمل الذي ترغب به، عليك تفقد الوظائف التي يتم عرضها وما هو المطلوب لتستطيع تحديد ما ستقوم بتعلمه. على مواقع العمل الحر ستجد أن Flutter أكثر طلبًا بالطبع بسبب استقرار ذلك الإطار وسهولة وسرعة تطوير المشاريع من خلاله، أيضًا تكلفة تطوير المشروع من خلاله أقل من React Native، لكن React Native أصعب في عملية التطوير بسبب مشاكل التعامل مع مكتبات مختلفة والتوافقية بينهم.
-
هناك أمر هام يجب تفهمه، وهو أنك كمطور واجهة خلفية مسؤوليتك هي إنشاء الـ API لكي يتم استخدامها من قبل مطور الواجهة الأمامية. أيضًا استخدام API's لخدمات خارجية مثل بوابات الدفع payment gateways، ومواقع التواصل مثل فيسبوك و منصة x. أو المنصات السحابية مثل AWS و Google Cloud، أو إرسال الرسائل باستخدام واجهات برمجة التطبيقات مثل Twilio أو SendGrid لإرسال رسائل SMS أو بريد إلكتروني، أو خرائط جوجل. أي مطور الواجهة الخلفية يُهيئ الـ API بإنشاء نقطة نهاية (endpoint) تتيح لواجهة المستخدم التفاعل مع خدمة خارجية مثل Twilio أو SendGrid أو Google Maps. وكل ذلك سيتم شرحه بدورة PHP بالفعل.
-
بشكل مُختصر فكر في المنحة على أنها مسابقة، لذا اجعل من نفسك شخص تنافسي مميز عن الأغلبية. أغلب المنح ستجد أنها تتطلب معدل لا يقل عن 80% من البكالوريس، مثلاً في تركيا لديك منحة علي كوشتشو للعلوم والتكنولوجيا، وكلما إرتفع المُعدل كان لك الأفضلية بالطبع ولكنه ليس العامل الوحيد. لديك العمل التطوعي، مثل العمل في جمعيات خيرية أو تطوعات في الجامعة أو المدرسة وهكذا، مثل تلك الأمور يتم النظر إليها عند التقدم، وذلك ستضعه في خطاب الدوافع أو الغرض statement، ستذكر به محاسنك مثل الجوائر التكريمية والتطوعات وخلافه مثل خطاب التوصية. أيضًا بعد ذلك مباشرًة هو إيجادتك للغة الإنجليزية بمستوى تستطيع به التحدث والكتابة بشكل جيد، أي يكون لدى المشاركين الحد الأدنى من مستوى اللغة الإنجليزية في اختبار IELTS 3.5 أو ما يعادله، وأعلى مستوى في اللغة الإنجليزية للبرنامج هو IELTS 5.0 أو ما يعادله. وسيظهر ذلك جليًا في استمارة المنحة Application التي ستقوم بكتابتها للتقدم إليها. ولزيادة فرصك في الحصول على منحة عليك التقديم على كافة المنح التي تستوفي شروطها بغض النظر عن البلد. وهناك معلومة طريفة، وهي أنّ عدد المنح الدراسية الموجودة في العالم أكثر من عدد المتقدمين لتلك المنح! وذلك راجع إما لعدم المعرفة بوجودها بسبب قلة البحث أو التكاسل وخلافه، هناك منح لا يحصل عليها أحد unclaimed لأنه لم يتم التقدم إليها! لذا لديك مواقع مثل فرصة و مرجع توفر لك تفاصيل كاملة عن المنح التي يتم الإعلان عنها، لديك أيضًا Scholarships.com.
-
الأمر يتم من خلال PHP و HTML و JavaScript معًا. أولاً نقوم بإنشاء حقل الاختيار Select للجنس: <label for="gender">الجنس:</label> <select id="gender" name="gender"> <option value="">اختر الجنس</option> <option value="male">ذكر</option> <option value="female">أنثى</option> </select> ثم إنشاء حقول الوظائف (مخفية في البداية): <div id="maleJobs" style="display: none;"> <label for="maleJob">الوظيفة (للذكور):</label> <select id="maleJob" name="maleJob"> <option value="">اختر الوظيفة</option> <option value="engineer">مهندس</option> <option value="doctor">طبيب</option> <option value="teacher">مدرس</option> </select> </div> <div id="femaleJobs" style="display: none;"> <label for="femaleJob">الوظيفة (للإناث):</label> <select id="femaleJob" name="femaleJob"> <option value="">اختر الوظيفة</option> <option value="nurse">ممرضة</option> <option value="teacher">مدرسة</option> <option value="designer">مصممة</option> </select> </div> هنا يأتي دور JavaScript لإظهار حقل الوظائف المناسب: <script> const genderSelect = document.getElementById('gender'); const maleJobsDiv = document.getElementById('maleJobs'); const femaleJobsDiv = document.getElementById('femaleJobs'); genderSelect.addEventListener('change', function() { if (this.value === 'male') { maleJobsDiv.style.display = 'block'; femaleJobsDiv.style.display = 'none'; } else if (this.value === 'female') { maleJobsDiv.style.display = 'none'; femaleJobsDiv.style.display = 'block'; } else { maleJobsDiv.style.display = 'none'; femaleJobsDiv.style.display = 'none'; } }); </script> حيث ستعمل addEventListener على تنفيذ دالة عند تغيير قيمة حقل الجنس، داخل الدالة، نتحقق من قيمة حقل الجنس ونعرض حقل الوظائف المناسب باستخدام style.display = 'block'. نخفي حقل الوظائف الآخر باستخدام style.display = 'none'. بالطبع ستحتاج إلى إرسال البيانات من خلال النموذج إلى السيرفر ثم معالجتها في PHP.
- 13 اجابة
-
- 1
-
-
توجد أكثر من طريقة، وأولهم استخدام ملفات لكل لغة. عليك أولاً إنشاء ملفات منفصلة لكل لغة تريد دعمها، مثل ar.php للغة العربية و en.php للغة الإنجليزية. داخل كل ملف لغة، قم بتخزين الترجمات كمصفوفة ترابطية، حيث يكون المفتاح هو النص الأصلي والقيمة هي الترجمة. للتوضيح: <?php return [ 'Welcome' => 'أهلاً بك', 'Login' => 'تسجيل الدخول', ]; ?> في سكربت PHP الرئيسي، قم بتحميل ملف اللغة المناسب حسب لغة المستخدم، وتستطيع الإعتماد على متغير $_SERVER['HTTP_ACCEPT_LANGUAGE'] لتحديد لغة متصفح المستخدم. <?php $lang = isset($_SESSION['lang']) ? $_SESSION['lang'] : 'en'; $translations = require_once "languages/$lang.php"; ?> ثم استخدم المفتاح من المصفوفة لعرض الترجمة المقابلة. <?php echo $translations['Welcome']; ?> وسيعرض "أهلاً بك" لو كانت لغة المستخدم هي العربية. الطريقة الثانية الإعتماد على قاعدة البيانات، بإنشاء جدول في قاعدة البيانات لتخزين الترجمات، ويجب أن يحتوي الجدول على حقول للنص الأصلي، واللغة، والترجمة. لكن الطريقة الأفضل والإحترافية هي باستخدام مكتبة Gettext الموجودة في PHP، ستعمل على إنشاء ملفات PO (Portable Object) لكل لغة تريد دعمها، حيث تحتوي ملفات PO على النص الأصلي والترجمة. ثم تحويل ملفات PO إلى ملفات MO (Machine Object) باستخدام الأمر msgfmt، بعد ذلك استخدم دوال Gettext لتحميل الترجمات من ملفات MO وعرضها.
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم الأسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
- 1 جواب
-
- 1
-
-
ستجد أسفل فيديو الدرس في نهاية الصفحة صندوق تعليقات كما هنا، أرجو طرح الأسئلة أسفل الدرس وليس هنا في قسم الأسئلة البرمجة حيث نطرح الأسئلة العامة الغير متعلقة بمحتوى الدورة أو الدرس، وذلك لمساعدتك بشكل أفضل.
-
خلال دورة تطوير واجهات المستخدم يتم التطرق إلى الأساسيات أولاً للتالي HTML, CSS,JS و مكتبةjQuery، ثم خلال المشاريع يتم التطرق إلى أمور متقدمة بالإضافة للأساسيات. لذا بعد الإنتهاء ستجد أنه تم شرح نسبة كبيرة من اللغات السابقة. لكن هل تكتفي بذلك؟ حقيقًة الفرق بين مبرمج متميز ومبرمج عادي هو الرغبة في تعلم المزيد وبذل مجهود وعدم الإكتفاء، لأكون صريحًا معك لا توجد دورة توفر لك كل شيء، ستحتاج إلى البحث والمشاهدة والقراءة عن المزيد والتعمق فيما يتم شرحه وليس الإكتفاء بالشرح فقط. أتفهم الرغبة في إنهاء الدورة بشكل سريع، لكن ما الفائدة؟ الفائدة تكمن في زيادة مستواك وخبراتك بما ذكرت وتوظيف ذلك في نماذج وتطبيقات عملية لفهم كيف آلية عملها وما الفرق بين الخواص المختلفة وهكذا. بالطبع لا أطلب منك فهم كل ما هو موجود في موسوعة حسوب، لكن تفقد الخواص المتاحة وماذا تفعل وتعلم البعض منها وهكذا
-
غالب الظن أنك تقوم بتعديل ملف تهجير موجود مسبقًا بدلاً من إنشاء ملف جديد، بمعنى لإنشاء جدول جديد أو تعديل جدول موجود، يجب عليك دائمًا إنشاء ملف تهجير جديد، لا تقم بتعديل ملفات التهجير الموجودة مسبقًا. وإن قمت بتعديل ملف تهجير موجود مسبقًا، فلن يتم تطبيق التغييرات، لأن لارافل تحتفظ بسجل بالتغييرات التي تم إجراؤها على قاعدة البيانات. لذا، لو قمت بتعديل ملف تهجير موجود مسبقًا، فلن يتم تطبيقه لأن لارافل تعتقد أنه تم تطبيقه بالفعل.
-
تخيل معي لو حصل المهاجم على ملف تعريف ارتباط الجلسة Cookie للمستخدم أو بيانات الاعتماد الخاصة به، سيتمكن من انتحال شخصية المستخدم وإجراء طلبات نيابة عنه وذلك هجوم Session Hijacking، بالتالي المصادقة القائمة على الرموز تجعل من الصعب على المهاجمين اختطاف الجلسة، حيث يحتاجون إلى الحصول على الرمز أيضًا. بالإضافة إلى هجمات CSRF، حيث تساعد المصادقة من خلال الـ Token منع هجمات تزوير الطلبات عبر المواقع (CSRF)، حيث يخدع المهاجم متصفح المستخدم لإجراء طلبات غير مصرح بها إلى الخادم. ويصبح من الصعب على الخادم تتبع المستخدمين النشطين وإدارة جلساتهم أيضًا من خلال الرمز، لا يحتاج الخادم إلى إعادة المصادقة على المستخدم لكل طلب، والتعامل مع المزيد من الطلبات دون الحاجة إلى إعادة المصادقة على المستخدمين، مما يقلل من الحمل على الخادم ويحسن الأداء. ولا يحتاج الخادم أيضًا إلى الاحتفاظ بمعلومات الجلسة لكل مستخدم، ويستطيع المستخدمين الوصول إلى التطبيق من أجهزة أو جلسات متعددة دون الحاجة إلى إعادة المصادقة. بجانب أنه بإمكانك إلغاء الرموز أو إنهاء صلاحيتها، مما يسمح بالتحكم الدقيق في الوصول إلى التطبيق للمساعدة يساعد في تقليل مخاطر سرقة الـ Tokens، حيث يمكن إلغاء الـ Access Token المسروق دون الحاجة إلى تسجيل خروج المستخدم. ناهيك عن استخدام الرموز لتتبع نشاط المستخدم وتوفير سجل تدقيق أكثر تفصيلاً.
