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

Withable Laravel Package

jedrzej/withable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require jedrzej/withable:0.0.6
    

    Add the trait to your Eloquent model:

    use Jedrzej\Withable\WithableTrait;
    
    class Post extends Model
    {
        use WithableTrait;
        protected $withable = ['author', 'comments'];
    }
    
  2. First Use Case:

    • Trigger eager loading via a request parameter:
      /posts?with=author,comments
      
    • In your controller:
      $posts = Post::all(); // Automatically eager loads 'author' and 'comments'
      
  3. Where to Look First:

    • Check the WithableTrait source in vendor/jedrzej/withable/src/WithableTrait.php for core logic.
    • Review the getWithableRelations() method if dynamic relation definitions are needed.

Implementation Patterns

Usage Patterns

  1. Basic Eager Loading:

    // URL: /posts?with=author
    $posts = Post::all(); // Loads 'author' relation for all posts
    
  2. Multiple Relations:

    // URL: /posts?with=author,comments
    $posts = Post::all(); // Loads both relations
    
  3. Dynamic Relations:

    class Post extends Model
    {
        use WithableTrait;
    
        protected function getWithableRelations()
        {
            return ['author', 'comments', 'tags']; // Conditionally add relations
        }
    }
    
  4. Integration with API Resources:

    // In a resource class:
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'author' => $this->whenLoaded('author', function () {
                return $this->author->name;
            }),
        ];
    }
    
  5. Combining with Other Traits:

    use Jedrzej\Sortable\SortableTrait;
    use Jedrzej\Searchable\SearchableTrait;
    
    class Post extends Model
    {
        use WithableTrait, SortableTrait, SearchableTrait;
        protected $withable = ['author'];
        protected $searchable = ['title', 'body'];
    }
    

Workflows

  • API Endpoints: Use with parameter for client-driven eager loading:

    Route::get('/posts', function () {
        return Post::all(); // Respects ?with=author,comments
    });
    
  • Admin Panels: Dynamically load nested relations for detailed views:

    // URL: /admin/posts?with=author,comments.user
    $posts = Post::all(); // Loads nested relations
    
  • Testing: Mock the withable property or getWithableRelations() in tests:

    $post = new Post();
    $post->setWithable(['author']); // Force specific relations
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity: The with parameter is case-sensitive. Ensure relation names match exactly (e.g., author vs Author).

  2. Circular References: Nested relations (e.g., ?with=author.posts) may cause SQLSTATE[23000] errors. Use withCount or limit depth:

    protected $withable = ['author']; // Avoid nested relations
    
  3. Performance:

    • Unbounded with parameters can lead to N+1 queries. Validate input:
      public function getWithableRelations()
      {
          return array_intersect(['author', 'comments'], explode(',', request('with')));
      }
      
    • Use with() manually for complex cases:
      $posts = Post::with(request('with'))->get();
      
  4. Laravel Version Quirks:

    • Laravel 5.5+ may require adjusting the trait for Illuminate\Database\Eloquent\Model (not Eloquent).
    • Test in your Laravel version; the package targets 4/5/6.
  5. Overriding Default Behavior: The trait hooks into getQuery() and toArray(). Override these methods cautiously to avoid conflicts.

Debugging

  • Check Loaded Relations:
    $post->relationLoaded('author'); // Returns bool
    
  • Log Queries: Enable Laravel’s query logging to verify eager loading:
    DB::enableQueryLog();
    $posts = Post::all();
    dd(DB::getQueryLog());
    
  • Validate Input: Sanitize the with parameter to prevent SQL injection:
    $allowed = ['author', 'comments'];
    $with = array_intersect(explode(',', request('with')), $allowed);
    

Tips

  1. Default Relations: Set defaults in getWithableRelations():

    protected function getWithableRelations()
    {
        return ['author']; // Default relation
    }
    
  2. Conditional Loading: Dynamically adjust relations based on user roles:

    protected function getWithableRelations()
    {
        $relations = ['author'];
        if (auth()->user()->isAdmin()) {
            $relations[] = 'comments';
        }
        return $relations;
    }
    
  3. Combine with withCount:

    // URL: /posts?with=author,comments:count
    $posts = Post::withCount('comments')->get();
    
  4. Extend the Trait: Add custom logic to the trait’s bootWithable() method:

    namespace Jedrzej\Withable;
    
    trait WithableTrait {
        public static function bootWithable()
        {
            static::addGlobalScope('withable', function (Builder $builder) {
                // Custom scope logic
            });
        }
    }
    
  5. Documentation: Clearly document the with parameter in your API specs (e.g., OpenAPI/Swagger):

    parameters:
      - name: with
        in: query
        description: Comma-separated list of relations to eager load (e.g., "author,comments")
        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