آموزش ساخت جستجوی پیشرفته در لاراول با پکیج Eloquent-Builder

06 شهریور 1397
kisspng-euclidean-vector-flat-design-news-search-vector-5a7e726d585490

در پروژه اخیر ما نیاز به یک جستجوی پیشرفته روی مدل های مختلف داشتیم. این جستجو فیلترهای زیادی را شامل می شد که نیازمند یک سیستم جستجوی منعطف و مقیاس پذیر بود. من تصمیم گرفتم برای این سیستم یک پکیج پیاده سازی کنم که شما می توانید آن را در گیت هاب مشاهده و در پروژهای خود استفاده کنید.

جستجوی پیشرفته لاراول

مشکل چیست؟

مشکل از اینجا شروع می شود که شما با مجموعه ای از فیلترها روبرو می شوید که برای اضافه کردن آنها به Query باید شرط های زیادی را بررسی کنید.

نوشتن شرط های زیاد حتما از خوانایی کد شما می کاهد و روند توسعه را کُند و پیچیده می کند. همچنین, شما از فیلتر ها و شرط هایی که نوشتید فقط می توانید در یک حوزه استفاده کنید و قابل استفاده مجدد نیز نخواهند بود.

راه حل

شما باید کدهای خود را Refactor کنید!

برای رهایی از این مشکل باید کد خود را به روش Polymorphism برای جایگزین کردن شرط ها Refactor کنید.

برای آشنایی بیشتر این design pattern اینجا کلیک کنید.

مثال عملی

فرض کنید شما نیاز دارید لیست کاربرانی را با پارامترهای درخواستی زیر دریافت کنید:

http://virgool.io/users?age_more_than=25&gender=male&has_published_post=true

پارامتر های درخواستی به صورت زیر خواهند بود:

[
'age_more_than' => '25',
'gender' => 'male',
'has_published_post' => 'true',
]

در روش معمولی ما بصورت زیر فیلتر ها را اعمال میکنیم:

<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = User::where('is_active', true);
        if ($request->has('age_more_than')) {
            $users->where('age', '>', $request->age_more_than);
        }
        if ($request->has('gender')) {
            $users->where('gender', $request->gender);
        }
        if ($request->has('has_published_post')) {
            $users->where(function ($query) use ($request) {
                $query->whereHas('posts', function ($query) use ($request) {
                    $query->where('is_published', $request->has_published_post);
                });
            });
        }
        return $users->get();
    }
}

در اینجا به ازای پارامتر های درخواستی, شرط هایی را برسی کردیم. همچنین با اضافه شدن پارامترهای درخواستی, ما باید شرط های دیگری را جهت بررسی و محدود کردن Query به تیکه کد بالا اضافه کنیم که تمیزی کد ما را از بین می برد.

استفاده از پکیج Eloquent-Builder برای حل مشکل

بعد از نصب پکیج معرفی شده, تنها کافیست کد خود را به صورت زیر تغییر دهید:

<?php
namespace App\Http\Controllers;
use App\User;
use Fouladgar\EloquentBuilder\EloquentBuilder;
use Illuminate\Http\Request;
class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = EloquentBuilder::to(
                    User::class,
                    $request->all()
                 );
        return $users->get();
    }
}

شما فقط کافیست مدل و لیست پارامترها را به متد to ارسال کنید و بعد از آن به ازای پارامترهای درخواستی که قرار است به Query اضافه شوند فیلتر تعریف کنیم.

به همین راحتی!

تعریف یک فیلتر

برای نمونه من یکی از فیلترهای مثال بالا را پیاده سازی میکنم.به مثال زیر دقت کنید:

<?php
namespace App\EloquentFilters\User;
use Fouladgar\EloquentBuilder\Support\Foundation\Contracts\Filter;
use Illuminate\Database\Eloquent\Builder;
class AgeMoreThanFilter implements Filter
{
    /**
     * Apply the age condition to the query.
     *
     * @param Builder $builder
     * @param mixed   $value
     *
     * @return Builder
     */
    public function apply(Builder $builder, $value): Builder
    {
        return $builder->where('age', '>', $value);
    }
}

برای مشاهده جزئیات بیشتر به آدرس پکیج در گیت هاب مراجعه کنید.

موفق باشید و ممنون بابت وقتی که گذاشتید.

نویسنده شوید
دیدگاه‌های شما (3 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

masoomeh
07 فروردین 1401
این نوع سرچ یک میلیون رکورد رو پاسخ میده؟ با سرعت مناسب؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مهدی
05 تیر 1400
سلام برا pagination هم عمل می کنه یعنی من می خوام یه جستجو داشته باشم که از فیلدها استفاده کنه همراه با ajax و داخل اش صفحه بندی هم همزمان انجام بدم با این پکیج میشه این کار را انجام داد

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

فائزه
25 دی 1397
سلام خیلی متشکر واسه این پکیج عالی تون فقط کاش برای آموزش متن یا فیلم فارسی هم میزاشتید که خیلی بهتر می شد. با تشکر

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

محمد فولادگر
25 دی 1397
سلام خیلی ممنونم از شما. بله حق با شماست. اگه فرصتی بشه حتما یه فیلم آموزشی از پکیج میزارم. خوشحال میشم اگه به مشکلی برخوردید در قسمت Issues های پکیج قرار دهید: https://github.com/mohammad-fouladgar/eloquent-builder/issues با تشکر

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.