Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Purity Laravel Package

abbasudo/laravel-purity

Laravel Purity adds elegant filtering and sorting to Eloquent queries via a simple filter() method. Let frontend users drive complex query conditions using URL query string parameters (e.g., filters[title][$contains]=Purity), with minimal boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:
    composer require abbasudo/laravel-purity
    php artisan vendor:publish --tag=purity
    
  2. Add Traits to Model:
    use Abbasudo\Purity\Traits\Filterable;
    use Abbasudo\Purity\Traits\Sortable;
    
    class Post extends Model
    {
        use Filterable, Sortable;
    }
    
  3. Apply in Controller:
    return Post::filter()->sort()->get();
    
  4. Frontend Usage: Use qs library to construct query strings:
    const qs = require('qs');
    const query = qs.stringify({
        filters: { title: { $contains: 'Purity' } },
        sort: ['title:asc']
    });
    await request(`/api/posts?${query}`);
    

First Use Case

Create a filtered/sorted API endpoint for a Post model:

// routes/api.php
Route::get('/posts', [PostController::class, 'index']);

// app/Http/Controllers/PostController.php
public function index()
{
    return Post::filter()->sort()->paginate(10);
}

Now users can filter/sort via URL:

GET /api/posts?filters[title][$contains]=Laravel&sort[0]=created_at:desc

Implementation Patterns

Core Workflows

  1. Basic Filtering/Sorting:

    // Controller
    $posts = Post::filter()->sort()->get();
    
    // Frontend
    const query = qs.stringify({
        filters: { title: { $eq: 'Hello' } },
        sort: ['title']
    });
    
  2. Livewire Integration:

    // Component
    #[Url]
    public $filters = ['title' => []];
    
    public function render()
    {
        $posts = Post::filter($this->filters)->get();
        return view('livewire.posts', compact('posts'));
    }
    
    <!-- Blade -->
    <input wire:model.live="filters.title.$eq" placeholder="Exact title">
    
  3. Relation Filtering:

    // Model
    class Post extends Model
    {
        use Filterable;
        public function tags() { return $this;hasMany(Tag::class); }
    }
    
    class Tag extends Model
    {
        use Filterable;
        protected $filterFields = ['name'];
    }
    
    // Frontend
    const query = qs.stringify({
        filters: { 'tags.name': { $contains: 'Tech' } }
    });
    

Integration Tips

  • API Resources: Combine with Laravel's API Resources for structured responses:
    return PostResource::collection(Post::filter()->sort()->paginate());
    
  • Form Requests: Validate filter inputs in a FormRequest:
    public function rules()
    {
        return [
            'filters.title.$contains' => 'nullable|string|max:255',
            'sort' => 'nullable|array',
        ];
    }
    
  • Caching: Cache filtered/sorted queries:
    return Cache::remember('filtered_posts', now()->addHour(), function() {
        return Post::filter()->sort()->get();
    });
    

Gotchas and Tips

Pitfalls

  1. Silent Exceptions:

    • By default, Purity silences exceptions. Enable debugging in config/purity.php:
      'silent' => false,
      
    • Log custom exceptions in app/Exceptions/Handler.php:
      public function register()
      {
          $this->reportable(function (\Abbasudo\Purity\Exceptions\FilterException $e) {
              Log::error($e);
          });
      }
      
  2. Relation Fields:

    • Ensure related models have Filterable trait and $filterFields defined.
    • Nested relations (e.g., post.tags.user.name) are not supported.
  3. Field Renaming:

    • Use renameFields in config/purity.php to map API fields to DB columns:
      'rename_fields' => [
          'post_title' => 'title',
      ],
      

Debugging

  • Query Inspection: Use Laravel Debugbar to inspect generated queries:
    \DB::enableQueryLog();
    Post::filter()->sort()->get();
    dd(\DB::getQueryLog());
    
  • Frontend Validation: Validate filter operators on the frontend (e.g., using qs library):
    const validOperators = ['$eq', '$contains', '$gt'];
    if (!validOperators.includes(Object.keys(filters)[0])) {
        throw new Error('Invalid filter operator');
    }
    

Extension Points

  1. Custom Filters: Add custom filter methods in app/Providers/PurityServiceProvider.php:

    public function boot()
    {
        \Abbasudo\Purity\Facades\Purity::extend('custom', function ($query, $value) {
            return $query->where('column', 'like', "%{$value}%");
        });
    }
    

    Usage:

    filters: { title: { $custom: 'search' } }
    
  2. Middleware: Restrict filters/sorts to authenticated users:

    public function handle($request, Closure $next)
    {
        if (!$request->user()->can('filter_posts')) {
            abort(403);
        }
        return $next($request);
    }
    

    Apply to routes:

    Route::get('/posts', [PostController::class, 'index'])->middleware('can:filter_posts');
    
  3. Testing: Mock filter/sort logic in tests:

    $this->get('/api/posts?filters[title][$eq]=Test')
         ->assertOk()
         ->assertJsonCount(1);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport