staudenmeir/laravel-cte

带有常见表表达式 (CTE) 的 Laravel 查询

v1.11.1 2024-07-11 09:07 UTC

README

CI Code Coverage Latest Stable Version Total Downloads License

此 Laravel 扩展为查询构建器和 Eloquent 添加了对常见表表达式 (CTE) 的支持。

支持 Laravel 5.5+。

兼容性

  • MySQL 8.0+
  • MariaDB 10.2+
  • PostgreSQL 9.4+
  • SQLite 3.8.3+
  • SQL Server 2008+
  • Oracle 9.2+
  • SingleStore 8.1+
  • Firebird

安装

composer require staudenmeir/laravel-cte:"^1.0"

如果您在 Windows 的 PowerShell 中(例如在 VS Code 中),请使用此命令

composer require staudenmeir/laravel-cte:"^^^^1.0"

版本

用法

SELECT 查询

使用 withExpression() 并提供一个查询构建器实例、SQL 字符串或闭包

$posts = DB::table('p')
    ->select('p.*', 'u.name')
    ->withExpression('p', DB::table('posts'))
    ->withExpression('u', function ($query) {
        $query->from('users');
    })
    ->join('u', 'u.id', '=', 'p.user_id')
    ->get();

递归表达式

使用 withRecursiveExpression() 进行递归表达式

$query = DB::table('users')
    ->whereNull('parent_id')
    ->unionAll(
        DB::table('users')
            ->select('users.*')
            ->join('tree', 'tree.id', '=', 'users.parent_id')
    );

$tree = DB::table('tree')
    ->withRecursiveExpression('tree', $query)
    ->get();

物化表达式

使用 withMaterializedExpression()/withNonMaterializedExpression() 进行(非)物化表达式(PostgreSQL, SQLite)

$posts = DB::table('p')
    ->select('p.*', 'u.name')
    ->withMaterializedExpression('p', DB::table('posts'))
    ->withNonMaterializedExpression('u', function ($query) {
        $query->from('users');
    })
    ->join('u', 'u.id', '=', 'p.user_id')
    ->get();

自定义列

您可以将表达式的列作为第三个参数提供

$query = 'select 1 union all select number + 1 from numbers where number < 10';

$numbers = DB::table('numbers')
    ->withRecursiveExpression('numbers', $query, ['number'])
    ->get();

循环检测

MariaDB 10.5.2+PostgreSQL 14+ 支持原生循环检测,以防止递归表达式中的无限循环。将指示循环的列作为 withRecursiveExpressionAndCycleDetection() 的第三个参数提供

$query = DB::table('users')
    ->whereNull('parent_id')
    ->unionAll(
        DB::table('users')
            ->select('users.*')
            ->join('tree', 'tree.id', '=', 'users.parent_id')
    );

$tree = DB::table('tree')
    ->withRecursiveExpressionAndCycleDetection('tree', $query, 'id')
    ->get();

在 PostgreSQL 中,您可以自定义显示是否检测到循环的列的名称以及跟踪路径的列的名称

$tree = DB::table('tree')
    ->withRecursiveExpressionAndCycleDetection('tree', $query, 'id', 'is_cycle', 'path')
    ->get();

INSERT/UPDATE/DELETE 查询

您可以在 INSERTUPDATEDELETE 查询中使用常见表表达式

DB::table('profiles')
    ->withExpression('u', DB::table('users')->select('id', 'name'))
    ->insertUsing(['user_id', 'name'], DB::table('u'));
DB::table('profiles')
    ->withExpression('u', DB::table('users'))
    ->join('u', 'u.id', '=', 'profiles.user_id')
    ->update(['profiles.name' => DB::raw('u.name')]);
DB::table('profiles')
    ->withExpression('u', DB::table('users')->where('active', false))
    ->whereIn('user_id', DB::table('u')->select('id'))
    ->delete();

Eloquent

您可以在 Eloquent 查询中使用常见表表达式。

在 Laravel 5.5–5.7 中,这需要 QueriesExpressions 特性

class User extends Model
{
    use \Staudenmeir\LaravelCte\Eloquent\QueriesExpressions;
}

$query = User::whereNull('parent_id')
    ->unionAll(
        User::select('users.*')
            ->join('tree', 'tree.id', '=', 'users.parent_id')
    );

$tree = User::from('tree')
    ->withRecursiveExpression('tree', $query)
    ->get();

递归关系

如果您想实现递归关系,可以使用此包:[staudenmeir/laravel-adjacency-list](https://github.com/staudenmeir/laravel-adjacency-list)

Lumen

如果您正在使用 Lumen,您必须手动实例化查询构建器

$builder = new \Staudenmeir\LaravelCte\Query\Builder(app('db')->connection());

$result = $builder->from(...)->withExpression(...)->get();

在 Eloquent 中,对于 Lumen 的所有版本,都需要 QueriesExpressions 特性。

贡献

请参阅CONTRIBUTING行为准则以获取详细信息。