I'm always excited to take on new projects and collaborate with innovative minds.

Phone

+20 115 052 9992

Website

https://ibrahimahmed.online/

Social Links

ازاي تبني فلاتر بحث معقدة (Complex Filters) وتظبط الـ URL مع Inertia.js زي البروفيشنال

ازاي تبني فلاتر بحث معقدة (Complex Filters) وتظبط الـ URL مع Inertia.js زي البروفيشنال يا هلا بيك يا صديقي المبرمج في مقال جديد من سلسلة شروحات تطوير الويب (Web

ازاي تبني فلاتر بحث معقدة (Complex Filters) وتظبط الـ URL مع Inertia.js زي البروفيشنال
Reading Count: 5

ازاي تبني فلاتر بحث معقدة (Complex Filters) وتظبط الـ URL مع Inertia.js زي البروفيشنال

يا هلا بيك يا صديقي المبرمج في مقال جديد من سلسلة شروحات تطوير الويب (Web Development). كام مرة وأنت شغال على مشروع (Project) طلبت منك الإدارة أو العميل يعمل صفحة منتجات أو مستخدمين فيها فلاتر بحث معقدة (Complex Filters) زي البحث بالاسم، التصفية بالسعر، الترتيب، والـ Pagination كمان؟ طبعاً عملت ده كله بلوب (Loop) وجافاسكريبت (JavaScript)، والدنيا اشتלت تمام وزي الفل.

لكن.. استنى! المستخدم عمل تحديث للصفحة (Refresh) أو حب يبعت لينك الصفحة لصحابه عشان يشوفوا النتائج.. وبووم! كل الفلاتر طارت ورجعت الصفحة لحالتها الافتراضية. هنا بقى بيظهر "الوجع" الحقيقي للمبرمج، ويبدأ التفكير: ازاي أعمل مزامنة لمدخلات البحث مع شريط العنوان (URL Query Synchronization) عشان أحافظ على النتائج حتى لو حصل تحديث؟ ده بالظبط اللي هنشرحه النهاردة باستخدام إنرتيا جي إس (Inertia.js).

ليه مزامنة الـ URL مهمة أصلاً في تطبيقات إنرتيا (Inertia.js)؟

لما بنشتغل بـ Inertia، إحنا غالباً بنستعمل إطارات عمل زي لارا فود (Laravel) من الباك إند، وفريم وورك زي ڤيوز (Vue.js) أو رياكت (React) من الفرونت إند. الميزة الكبيرة في Inertia إنها بتخلينا نحس إننا شغالين إسكت (Single Page Application - SPA) بس بنفس منطق الـ Routing العادي.

المشكلة إن المطورين المبتدئين أحياناً بيخزنوا حالة الفلاتر (Filter State) جوه الـ Component State المحلية (زي useState في React أو ref في Vue). الطريقة دي سريعة، بس بتدمر تجربة المستخدم (User Experience) للأسباب دي:

  • المستخدم ما يقدرش يعمل نسخ (Copy) للينك بالفلتر ويبعته لحد.
  • زرار الرجوع (Back Button) في المتصفح مش هيشتغل بالطريقة الصح مع الفلاتر.
  • لو الصفحة عملت Refresh، كل الفلاتر هتموت والبحث هيصفر.

الحل السحري هنا هو ربط حالة الفلاتر مباشرة بـ URL Query Parameters، وهنا بيجي دور Inertia في تسهيل المهمة دي عن طريق أداة الزيارة (Inertia Visit).

الخطوة الأولى: تجهيز هيكل الـ Backend (Laravel Controller)

عشان نبني فلاتر معقدة، لازم نستقبل البيانات دي في السيرفر ونعالجها صح. تعالوا نفترض إن عندنا جدول للمنتجات (Products) وعاوزين نفترق بالاسم، القسم (Category)، وأعلى سعر.


public function index(Request $request)
{
    $products = Product::query()
        ->when($request->input('search'), function ($query, $search) {
            $query->where('name', 'like', '%' . $search . '%');
        })
        ->when($request->input('category_id'), function ($query, $categoryId) {
            $query->where('category_id', $categoryId);
        })
        ->when($request->input('max_price'), function ($query, $maxPrice) {
            $query->where('price', '<=', $maxPrice);
        })
        ->paginate(10)
        ->withQueryString(); // دي مهمة جداً عشان تحافظ على الـ URL مع الـ Pagination

    return Inertia::render('Products/Index', [
        'products' => $products,
        'filters' => $request->only(['search', 'category_id', 'max_price'])
    ]);
}

لاحظ استخدام الدالة withQueryString() في لاراڤيل، دي بتخلي أزرار التنقل بين الصفحات (Pagination Links) تحتفظ بالمتغيرات الموجودة في الـ URL زي البحث والفلاتر.

الخطوة الثانية: بناء واجهة المستخدم وربطها برمجياً (Frontend with Vue.js & Inertia)

دلوقت هنروح للفرونت إند، وتحديداَ باستخدام ڤيوز (Vue.js Composition API). الفكرة هنا إننا هنستخدم router.get من مكتبة Inertia عشان نبعت طلب جديد للسيرفر كل ما المستخدم يغير فلتر، مع استخدام خاصية preserveState و preserveScroll عشان الصفحة ما تعيدش تحميل نفسها بشكل مزعج أو تطلع لفوق خالص.


<script setup>
import { ref, watch } from 'vue';
import { router } from '@inertiajs/vue3';
import debounce from 'lodash/debounce';

const props = defineProps({
    products: Object,
    filters: Object
});

// بنعرف الـ State ونملأها بالقيم الجاية من الـ URL (عشان لو عمل Refresh)
const form = ref({
    search: props.filters.search || '',
    category_id: props.filters.category_id || '',
    max_price: props.filters.max_price || ''
});

// بنعمل Watcher على الـ Form مع Debounce للبحث عشان ما نبعتليش طلب مع كل حرف
watch(form, debounce((newValue) => {
    router.get('/products', newValue, {
        preserveState: true,
        preserveScroll: true,
        replace: true, // عشان ما نملاش الـ History بالملفات الزيادة
    });
}, 300), { deep: true });
</script>

الكود ده عبقري وبسيط في نفس الوقت! أول ما المستخدم يكتب حرف أو يغير اختيار في القائمة، الـ Watcher بيلقط التغيير، وبيستنى 300 جزء من الثانية (عن طريق debounce عشان الـ Performance)، وبعدين بيبعت طلب لـ Inertia يحدّث الـ URL وكمان يجيب البيانات الجديدة بسلاسة تامة.

نصيحة من أخ لتطوير مهاراتك البرمجية

يا صديقي، مفيش مبرمج شاطر اتولد بيعرف يكتب الكود ده من أول مرة. السر كله في التمرس وفهم الـ Flow الخاص بدورة حياة الطلب (Request Lifecycle) بين الفرونت إند والباك إند. لما تقابل مشكلة إن الفلاتر بتتمسح مع التحديث، متجريش على طول تكتب كود معقد، فكر الأول: هل الـ State دي متخزنة في مكان يختفي مع الـ Refresh؟ لو الإجابة نعم، يبقى الـ URL هو المكان الآمن الوحيد لتخزين الحالة دي. اتعلم دايماً تقرأ التوثيق الرسمي (Official Documentation) لـ Inertia، وهتلاقي جواها كنوز تخلي أداء شغلك أسرع وأسهل بكتير. بالتوفيق يا بطل!


Share

Related posts

Aug 08, 2026 • 2 min read
Reading Count: 7
تمرير البيانات الحساسة بأمان من Laravel إلى Inertia بدون كشفها للجميع

يا هلا بيك يا بشمهندس في مقال تقني جديد من سلسلة الشروحات اللي بتهم كل مطور ويب شغال بلغة PHP وفريم...

Aug 08, 2026 • 2 min read
Reading Count: 12
إدارة الـ WebSockets واستقبال الـ Events اللحظية داخل مكونات Inertia
Aug 07, 2026 • 2 min read
Reading Count: 5
إدارة الـ WebSockets واستقبال الـ Events اللحظية داخل مكونات Inertia: ودع الـ Reload للأبد

التصنيف: تطوير الويب (Web Development) - شروحات تقنية (Tutorials) إدارة الـ WebSockets واستقبال الـ...