maksimru/eloquent-subquery-magic

Eloquent extension providing ability to use a lot of subquery functions like fromSubquery or leftJoinSubquery
18,577 19
Install
composer require maksimru/eloquent-subquery-magic
Latest Version:v0.13
PHP:>=5.6
License:MIT
Last Updated:Nov 1, 2019
Links: GitHub  ·  Packagist
Maintainer: maksimru

Scrutinizer Code Quality codecov StyleCI CircleCI

About

Library extends Laravel's Eloquent ORM with various helpful sub query operations such as leftJoinSubquery or fromSubquery and provide clean methods to use Eloquent without raw statements

Usage

No installation required

Simply add SubqueryMagic trait into your models


use Illuminate\Database\Eloquent\Model;
use MaksimM\SubqueryMagic\SubqueryMagic;

class SomeModel extends Model
{
    use SubqueryMagic;
}

Installation

composer require maksimru/eloquent-subquery-magic

Supported operations (with examples)

  1. leftJoinSubquery
    User::selectRaw('user_id,comments_by_user.total_count')->leftJoinSubquery(
      //subquery
      Comment::selectRaw('user_id,count(*) total_count')
          ->groupBy('user_id'),
      //alias
      'comments_by_user', 
      //closure for "on" statement
      function ($join) {
          $join->on('users.id', '=', 'comments_by_user.user_id');
      }
    )->get();
    
  2. joinSubquery
    User::selectRaw('user_id,comments_by_user.total_count')->joinSubquery(
      //subquery
      Comment::selectRaw('user_id,count(*) total_count')
          ->groupBy('user_id'),
      //alias
      'comments_by_user', 
      //closure for "on" statement
      function ($join) {
          $join->on('users.id', '=', 'comments_by_user.user_id');
      }
    )->get();
    
  3. rightJoinSubquery
    User::selectRaw('user_id,comments_by_user.total_count')->rightJoinSubquery(
        //subquery
        Comment::selectRaw('user_id,count(*) total_count')
           ->groupBy('user_id'),
        //alias
        'comments_by_user', 
        //closure for "on" statement
        function ($join) {
           $join->on('users.id', '=', 'comments_by_user.user_id');
        }
    )->get();
    
  4. whereInSubquery
    User::whereInSubquery('id', Comment::selectRaw('distinct(user_id)'))->get();
    
  5. whereNotInSubquery
    User::whereNotInSubquery('id', Comment::selectRaw('distinct(user_id)'))->get();
    
  6. orWhereInSubquery
    User::where('is_enabled','=',true)->orWhereInSubquery('id', Comment::selectRaw('distinct(user_id)'))->get();
    
  7. orWhereNotInSubquery
    User::where('is_enabled','=',true)->orWhereNotInSubquery('id', Comment::selectRaw('distinct(user_id)'))->get();
    
  8. fromSubquery
    User::selectRaw('info.min_id,info.max_id,info.total_count')->fromSubquery(
        //subquery
        User::selectRaw('min(id) min_id,max(id) max_id,count(*) total_count'),
        //alias
        'info'
    )->get()
    

Nested queries

It is possible to use it in nested queries, but you need to boot scope manually in each closure

User::where(function ($nested_query) {
    (new SubqueryMagicScope())->extend($nested_query);
    $nested_query->where('id', '<', 10);
    $nested_query->orWhereNotInSubquery('id', Comment::selectRaw('distinct(user_id)'));
})

Complex example

User::selectRaw('users.name,filtered_members_with_stats.total_count')
    ->where(function ($nested_query) {
        (new SubqueryMagicScope())->extend($nested_query);
        $nested_query->where('id', '<', 10);
        $nested_query->orWhereNotInSubquery('id', Comment::selectRaw('distinct(user_id)'));
    })->rightJoinSubquery(
        User::selectRaw('user_id,comments_by_user.total_count')->leftJoinSubquery(
            Comment::selectRaw('user_id,count(*) total_count')
                ->groupBy('user_id'),
            'comments_by_user', function ($join) {
                $join->on('users.id', '=', 'comments_by_user.user_id');
            }
        )->where('id','<',20),
        'filtered_members_with_stats', function ($join) {
            $join->on('users.id', '=', 'filtered_members_with_stats.user_id');
        }
    )
    ->get();

It will be executed as:


SELECT users.name,
       filtered_members_with_stats.total_count
FROM `users`
RIGHT JOIN
  (SELECT name,
          comments_by_user.total_count
   FROM `users`
   LEFT JOIN
     (SELECT user_id,
             count(*) total_count
      FROM `comments`
      GROUP BY `user_id`) `comments_by_user` ON `users`.`id` = `comments_by_user`.`user_id`
   WHERE `id` < 20) `filtered_members_with_stats` ON `users`.`id` = `filtered_members_with_stats`.`user_id`
WHERE (`id` < 10
       OR `id` NOT IN
         (SELECT distinct(user_id)
          FROM `comments`))
          

Related Packages

spatie/laravel-translatable

A trait to make an Eloquent model hold translations

30,089,119 2,462
spatie/laravel-sluggable

Generate slugs when saving Eloquent models

14,394,488 1,555
kodeine/laravel-acl

Light-weight role-based permissions for Laravel 5 built in Auth system.

364,261 774
hootlex/laravel-friendships

This package gives Eloquent models the ability to manage their friendships.

125,940 698