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

Pimpable Laravel Package

jedrzej/pimpable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:
    composer require jedrzej/pimpable
    
  2. Use the Trait: Add use PimpableTrait; to your Eloquent model (e.g., Post.php).
    class Post extends Model
    {
        use PimpableTrait;
    }
    
  3. First API Endpoint: In your controller, replace raw queries with pimp():
    public function index()
    {
        return Post::pimp()->get(); // Handles filtering, sorting, and eager loading via request params
    }
    

First Use Case

Scenario: Fetch posts with:

  • Thread ID 42
  • Text containing "awesome"
  • Sorted by is_active (desc) then created_at (desc)
  • Include user relation

Request:

GET /api/posts?thread_id=42&text=%awesome%&sort[]=is_active,desc&sort[]=created_at,desc&with=user

Implementation Patterns

Core Workflow

  1. Request Handling:

    • Automatically parses query params (filter, sort, with) into query constraints.
    • Example params:
      • filter[field]=value (e.g., filter[status]=published)
      • filter[field][op]=value (e.g., filter[created_at][ge]=2023-01-01)
      • sort[]=field,order (e.g., sort[]=created_at,desc)
      • with[]=relation1,relation2 (e.g., with[]=user,comments)
  2. Chaining Methods: Combine pimp() with other query builders:

    Post::where('draft', false)->pimp()->get();
    
  3. Customizing Behavior:

    • Override Default Rules: Use pimpable() method in your model:
      public function pimpable()
      {
          return $this->pimpable()
              ->addFilter('status', 'in', ['published', 'draft'])
              ->addSort('created_at');
      }
      
    • Dynamic Rules: Fetch rules from a config or database:
      $rules = config('api.filters.posts');
      return Post::pimp($rules)->get();
      
  4. Validation:

    • Validate incoming params (e.g., using Laravel’s Validator):
      $validated = request()->validate([
          'filter.*.0' => 'sometimes|string',
          'sort' => 'sometimes|array',
      ]);
      
  5. Pagination:

    • Integrate with Laravel’s pagination:
      return Post::pimp()->paginate(15);
      

Advanced Patterns

  • Nested Relations: Use dot notation for deep eager loading:
    GET /api/posts?with=user.address
    
  • Custom Operators: Extend filter operators (e.g., like, between) via addOperator():
    $this->pimpable()->addOperator('contains', function ($query, $field, $value) {
        return $query->where($field, 'like', "%{$value}%");
    });
    
  • API Versioning: Use middleware to apply version-specific rules:
    // In middleware
    $request->merge(['filter' => ['version' => 'v2']]);
    

Gotchas and Tips

Pitfalls

  1. Performance:

    • N+1 Queries: Forgetting with[] params can trigger N+1 issues. Always eager-load relations explicitly.
    • Complex Filters: Overusing whereRaw or custom operators may bloat queries. Test with DB::enableQueryLog():
      $query = Post::pimp();
      $query->toSql(); // Inspect SQL
      dd(DB::getQueryLog());
      
    • Sorting: Sorting on non-indexed columns (e.g., text) can be slow. Use database indexes or orderByRaw for complex sorts.
  2. Security:

    • SQL Injection: Custom operators or raw queries can expose risks. Sanitize inputs:
      $value = str_replace('%', '\%', request('filter.text'));
      
    • Mass Assignment: Ensure with[] params don’t enable unintended relation loading. Whitelist allowed relations:
      protected $withable = ['user', 'comments']; // Only allow these
      
  3. Edge Cases:

    • Empty Requests: Handle cases where no filters/sorts are provided:
      if (!request()->has(['filter', 'sort', 'with'])) {
          return Post::all(); // Fallback
      }
      
    • Boolean Fields: Use 1/0 or true/false for clarity (e.g., filter[is_active]=1).
  4. Laravel Version Quirks:

    • Laravel 5.5+: Use HasApiTokens or Authorizable traits carefully—they may conflict with PimpableTrait.
    • Laravel 6: Ensure use Illuminate\Database\Eloquent\Model; (not Eloquent).

Debugging Tips

  1. Log Request Params:
    \Log::info('Pimpable params:', [
        'filter' => request('filter'),
        'sort' => request('sort'),
        'with' => request('with'),
    ]);
    
  2. Disable Pimpable Temporarily: Comment out use PimpableTrait; to isolate issues.
  3. Test with Hardcoded Values: Bypass request params for testing:
    Post::pimp(['filter' => ['status' => 'published']])->get();
    

Extension Points

  1. Custom Rules Provider: Create a service to dynamically load rules:

    class FilterRuleProvider
    {
        public function getRules(string $model): array
        {
            return config("api.filters.{$model}");
        }
    }
    

    Then use it in your model:

    public function pimpable()
    {
        $rules = app(FilterRuleProvider::class)->getRules('Post');
        return $this->pimpable()->addRules($rules);
    }
    
  2. Event Listeners: Listen for pimpable.before and pimpable.after events to modify queries:

    event(new PimpableEvent($query, $params));
    

    Register in EventServiceProvider:

    protected $listen = [
        'pimpable.before' => [PimpableLogger::class],
    ];
    
  3. API Documentation: Auto-generate OpenAPI/Swagger docs by inspecting pimpable() rules:

    # swagger.yaml
    parameters:
      - name: filter[status]
        in: query
        description: Filter by status (e.g., published,draft)
        schema:
          type: string
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui