You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将原生SQL转换为Laravel Eloquent或查询构造器实现

原生SQL转Laravel查询构造器/Eloquent实现

各位Laravel开发者大家好,我想咨询如何将一段原生SQL查询转换为Laravel查询构造器或Eloquent ORM的实现,我已定义好相关模型、关联及数据表结构,具体信息如下:

已定义的模型关联

Server模型

public function users()
{
    return $this->belongsToMany(User::class,'server_users')->withPivot('spam','inbox');;
}

public function users_cancellation()
{
    return $this->belongsToMany(User::class,'server_user_cancellations')->withPivot('spam','inbox');;
}

User模型

public function servers(): BelongsToMany
{
    return $this->belongsToMany(Server::class, 'server_users');
}

public function servers_cancellation(): BelongsToMany
{
    return $this->belongsToMany(Server::class, 'server_user_cancellations');
}

相关数据表结构

users表

$table->id();
$table->string('full_name');
$table->string('username')->unique();
$table->string('password');
$table->string('type');
$table->boolean('is_active')->default(true);
$table->rememberToken();
$table->timestamps();
$table->softDeletes();

servers表

Schema::create('servers', function (Blueprint $table) {
    $table->id();
    $table->string('name')->default('SM');
    $table->ipAddress('ip')->unique();
    $table->string('username')->default('root');
    $table->boolean('is_active')->default(true);
    $table->softDeletes();
    $table->timestamps();
});

server_user_cancellations表

Schema::create('server_user_cancellations', function (Blueprint $table) {
    $table->id();
    $table->foreignIdFor(Server::class)->constrained()->cascadeOnDelete()->cascadeOnUpdate();
    $table->foreignIdFor(User::class)->constrained()->cascadeOnUpdate()->cascadeOnDelete();
    $table->boolean('spam')->nullable();
    $table->boolean('inbox')->nullable();
    $table->timestamps();
});

server_users表

Schema::create('server_users', function (Blueprint $table) {
    $table->id();
    $table->foreignIdFor(Server::class)->constrained()->cascadeOnDelete()->cascadeOnUpdate();
    $table->foreignIdFor(User::class)->constrained()->cascadeOnUpdate()->cascadeOnDelete();
    $table->boolean('spam')->nullable();
    $table->boolean('inbox')->nullable();
    $table->timestamps();
});

待转换的原生SQL

if ($request->wantsJson()) {
  $servers = DB::select('
  SELECT 
    s.name,
    s.id,
    s.ip,
    (SELECT count(id) 
      FROM server_user_cancellations 
      where server_id = s.id and user_id=?
    ) as exist
  FROM servers s
  WHERE s.id IN
    (SELECT  distinct server_id from server_users  where user_id=?)
    AND s.is_active=true
    AND s.is_installed=true
    AND s."deleted_at" is null', 
  [auth()->id(), auth()->id()]
);

可直接使用的转换后代码

方案1:Eloquent关联实现(推荐)

复用已定义的模型关联,逻辑更简洁,框架会自动处理软删除过滤,性能优于子查询写法:

if ($request->wantsJson()) {
    $userId = auth()->id();
    $servers = auth()->user()
        ->servers()
        ->where('is_active', true)
        ->where('is_installed', true)
        ->withCount([
            'users_cancellation as exist' => fn($query) => $query->where('user_id', $userId)
        ])
        ->select('id', 'name', 'ip')
        ->get();
}

注意:你提供的servers表迁移代码中没有is_installed字段,原SQL包含该字段过滤条件,请上线前确认字段是否存在,避免报错。

方案2:查询构造器实现(和原生SQL逻辑1:1对齐)

如果需要完全匹配原生SQL的执行逻辑,可使用查询构造器写法:

if ($request->wantsJson()) {
    $userId = auth()->id();
    $servers = DB::table('servers as s')
        ->select('s.name', 's.id', 's.ip')
        ->selectRaw('(SELECT count(id) FROM server_user_cancellations WHERE server_id = s.id AND user_id = ?) as exist', [$userId])
        ->whereIn('s.id', function ($query) use ($userId) {
            $query->distinct()
                ->select('server_id')
                ->from('server_users')
                ->where('user_id', $userId);
        })
        ->where('s.is_active', true)
        ->where('s.is_installed', true)
        ->whereNull('s.deleted_at')
        ->get();
}

内容的提问来源于stack exchange,提问作者housna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 18:54:27