如何在Laravel Eloquent查询(或使用查询构建器)中为表设置别名?

201

假设我们正在使用 Laravel 的查询构建器:

$users = DB::table('really_long_table_name')
           ->select('really_long_table_name.id')
           ->get();

我正在寻找与这个SQL等效的东西:

really_long_table_name AS short_name

当我需要输入许多select和where时(通常我在select的列别名中也包含别名,并且它会在结果数组中使用),这将特别有帮助。如果没有任何表别名,对我来说需要键入更多内容,而所有内容都变得更加难以阅读。在Laravel文档中找不到答案,有任何想法吗?

10个回答

290

Laravel支持使用AS在表和列上创建别名。请尝试:

$users = DB::table('really_long_table_name AS t')
           ->select('t.id AS uid')
           ->get();

让我们通过一个很棒的 tinker 工具来看它的实际应用

$ php artisan tinker
[1] > Schema::create('really_long_table_name', function($table) {$table->increments('id');});
// NULL
[2] > DB::table('really_long_table_name')->insert(['id' => null]);
// true
[3] > DB::table('really_long_table_name AS t')->select('t.id AS uid')->get();
// array(
//   0 => object(stdClass)(
//     'uid' => '1'
//   )
// )

2
@RubensMariuzzo 我知道。我相信你可以在 Laravel 论坛 http://forums.laravel.io 上留下评论请求。 - peterm
2
@AldiUnanto Eloquent怎么样?Active Record是用于一个表的,因此您不需要别名。当您使用关系时,仍然一次处理一个表(即在关系上定义过滤器时)。现在,如果您正在使用带有Eloquent模型的查询构建器(即连接),则可以在所有连接的表上使用别名,但不能在模型表上使用别名。 - peterm
1
@peterm 如果我在Eloquent中使用查询构建器会怎样?我的意思是,Eloquent模型需要声明一个受保护的属性来表示表名(例如:protected $table = "books";),那么我该如何创建别名呢?(例如生成的SQL语句:... FROM books AS A ... - Aldi Unanto
你可以使用 protected $table = 'really_long_table_name AS short_name'; 但这可能会导致在插入数据时失败。同时也可能会破坏关系查询。我正在使用 Lumen 和 DDD/Repository 模式,完全避免使用 Eloquent。 - prograhammer
@peterm 我也卡在了Eloquent别名上。你有找到任何关于Eloquent的东西吗? - Lizesh Shakya
这并没有回答问题。问题具体是针对Eloquent的上下文,而不是针对基本数据库查询类型的上下文。 - Alexander Trauzzi

120

要在 Eloquent 模型中使用别名,请按照以下方式修改您的代码:

Item
    ::from( 'items as items_alias' )
    ->join( 'attachments as att', DB::raw( 'att.item_id' ), '=', DB::raw( 'items_alias.id' ) )
    ->select( DB::raw( 'items_alias.*' ) )
    ->get();

这将自动在表名中添加表前缀,并返回一个Items模型的实例,而不是裸查询结果。添加DB::raw可以防止Laravel在别名中添加表前缀。


3
@m3rg,你是否找到了在软删除的情况下使它工作的方法?查询失败并显示错误信息“Unknown column 'table_alias.deleted_at'”。 - dev7
1
@m3rg @Yani 我使用这个 ->withTrashed()->whereNull('table_alias.deleted_at') - Firman Hidayat
@Adam 如果表有前缀,这是必要的。 - AMIB
"::from('items as items_alias')" 可以使用,但当模型使用软删除时会出现问题。 - Tushar Saha
这篇原帖来自2015年,可能最新版本的处理别名更好了? - funder7
显示剩余5条评论

18

以下是具体步骤。我将以合并为例,让它对任何人都变得非常清晰。

$products = DB::table('products AS pr')
        ->leftJoin('product_families AS pf', 'pf.id', '=', 'pr.product_family_id')
        ->select('pr.id as id', 'pf.name as product_family_name', 'pf.id as product_family_id')
        ->orderBy('pr.id', 'desc')
        ->get();

希望这可以帮到您。


你能提供一个别名中有空格而不是下划线(_)的例子吗? - Channox

16

在Eloquent中使用,只需在您的模型上方添加:

protected $table = '表名 as 别名'

//表名应与您的数据库中完全一致

..然后在查询中使用:

ModelName::query()->select(别名.id, 别名.name)


8
Laravel Eloquent的设计非常糟糕,虽然你可以定义别名来优化查询操作,但更新和删除操作会因为别名而出现错误。 - Meas

5

我尝试了所有这些选项,但都无法解决我的问题。后来在Laravel文档中发现了一些真正有效的方法。

您可以尝试以下操作:

DB::table('table_one as t1')
    ->select(
        't1.field_id as id','t2.field_on_t2 as field'
     )->join('table_two as t2', function ($join) {
        $join->on('t1.field_id ', '=', 't2.field_id');
    })->get()

4
您可以使用更简洁的代码来实现相同的效果,如下所示:
    $users = DB::table('really_long_table_name')
       ->get(array('really_long_table_name.field_very_long_name as short_name'));

当然,如果你想选择更多的字段,只需要写一个","并添加更多内容:

 $users = DB::table('really_long_table_name')
       ->get(array('really_long_table_name.field_very_long_name as short_name', 'really_long_table_name.another_field as other', 'and_another'));

当您使用复杂的联接查询时,这非常实用。


1

还要注意,当使用DB门面时,您可以将别名作为table方法的第二个参数传递:

$users = DB::table('really_long_table_name', 'short_name')
           ->select('short_name.id')
           ->get();

我不确定这个功能是随 Laravel 的某个特定版本发布的还是一直集成在其中的。


别名参数是在2019年添加的,因此在提问时还不可用。 - Tony

1
你可以使用Eloquent模型来进行表别名,如下所示:
$myTable = app(MyModel::class)->getTable();
$table2 = app(Model2::class)->getTable();
$record = MyModel::from("{$myTable} as t1")
->join("{$table2} as t2", 't1.email', '=', 't2.email', 'left')
->select(t1.*,t2.name)->first();

0

和 AMIB 的回答一样,对于软删除错误 "Unknown column 'table_alias.deleted_at'", 只需添加 ->withTrashed() 然后自己处理,例如 ->whereRaw('items_alias.deleted_at IS NULL')


-1
在最新版本的Laravel 9中,您可以使用别名来命名列,例如:
$events = Booking::whereBetween('sessionDateTime', [$today, $nextMonth])->get(['bookings.sessionDateTime as start']); // start is an alias here

问题是关于长表名的别名,而不是列名! - Vinod K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接