用Laravel 5 Eloquent连接多个列

34

把我看作 Laravel 初学者。

目标是:我有两列,现在我需要将同一行的 id 前缀更改为表格中的 component name

例如(有效)... 我有一个类似于 MySQL 的表格:

SELECT CONCAT(components.name," ", components.id) AS ID
FROM   `components` 

输出结果为

ID

|TestComp 40  |
 -------------
|component 41 |
 -------------
|test 42      |
我需要在 Laravel Eloquent 中使用相同的方法,这里的组件是模型名称。所以我尝试了以下代码:
$comp=Component::select("CONCAT('name','id') AS ID")->get()

但是它不起作用。
我认为是因为语法有误。
请帮我纠正正确的语法。使用laravelModels

注意:我是参考了互联网上的内容来提出上述查询的。

User::select(DB::raw('CONCAT(last_name, first_name) AS full_name'))

我不熟悉Eloquent,但从我的ORM框架经验来看,你不需要这样做,因为你可以像这样做:$entity = $model->getById(1);echo $entity->getLastName().$entity->getFirstName(); 这可能看起来有些繁琐,但ORM框架总是有些繁琐的。 - degr
7个回答

65

你需要用DB::raw将查询包装起来:

$comp = Component::select(DB::raw("CONCAT('name','id') AS ID"))->get()

另外,请注意因为您这样做查询,可能会使您的模型行为有所不同,因为此选择语句会从选择语句中删除所有其他字段。因此,除非进行新的查询,否则无法从模型中读取其他字段。因此,仅在读取数据而不是修改数据时使用此功能。

此外,为了使其成为漂亮的列表,我建议您将查询修改为:

$comp = Component::select(DB::raw("CONCAT('name','id') AS display_name"),'id')->get()->pluck('display_name','id');
// dump output to see how it looks.
dd($comp);// array key should be the arrray index, the value the concatted value.

1
$comp = Component::select(DB::raw("CONCAT(name,id) AS display_name"),'id')->get()->pluck('display_name','id'); // 将输出转储以查看其外观。 dd($comp);// 数组键应为数组索引,值为连接的值。这对我来说是有效的,可以进行修改。 - LetsCMS Pvt Ltd
5
它只显示名称和ID,而不是实际的名称和ID。 我这样做了。$comp = Component::select(DB::raw("CONCAT(name,id) AS ID"))->get() - Rajesh Chaudhary
1
@Tschallacka 在你的例子中,name 列名必须在 select 函数中传递,然后我们才能在 CONCAT 函数中使用它,否则它会提供空值。 $comp = Component::select(DB::raw("CONCAT('name','id') AS display_name"),'id','name')->get()->pluck('display_name','id'); - Bhavin Thummar
@BhavinThummar 这不应该是这种情况,因为它是一个原始查询。在您自己的代码中,在select中没有添加name字段的情况下,toSql()的输出是什么?laravel版本可能发生了一些变化,或者您的查询存在冲突。 - Tschallacka
@Tschallacka Laravel 版本为 8。 - Bhavin Thummar
显示剩余2条评论

14

我来到这篇文章是为了找答案。对我来说,唯一的问题是答案并没有真正解决我的情况。我有多个表关系设置,我需要一个子对象有一个连接字段。对我来说,DB::raw 的解决方案太麻烦了。我继续搜索并找到了我需要的答案,感觉这是一个更简单的解决方案。

与其使用DB::raw,我建议尝试一个Eloquent Accessor。访问器允许您检索模型属性,并创建原始模型未创建的新属性。

例如,假设我有一个基本的USER_PROFILE表。它包含 id, first_name, last_name。我需要连接两个名称属性以返回用户的全名。在USER_PROFILE Model中,我创建了 php artisan make:model UserProfile ,我会放置以下内容:

class UserProfile extends Model
{

  /**
   * Get the user's full concatenated name.
   * -- Must postfix the word 'Attribute' to the function name
   *
   * @return string
   */

  public function getFullnameAttribute()
  {
      return "{$this->first_name} {$this->last_name}";
  }

}
从这里开始,当我进行任何雄辩的调用时,我现在可以访问那个附加属性访问器。
| id | first_name | last_name |
-------------------------------
| 1  | John       | Doe       |


$user = App\UserProfile::first(); 

$user->first_name;   /** John **/
$user->fullname;    /** John Doe **/

我必须说,我遇到了一个问题。就是尝试创建一个与原属性同名的修改后的属性,就像你的例子中(id,ID)。我可以修改id的值本身,但由于声明了相同的名称,它似乎只允许访问该字段值而不是其他字段。

其他人说他们可以做到,但我无法解决这个问题确切的问题。


我必须为Laravel 5.8执行Answer1和Answer2中描述的两件事。 - Keyur
这个能和 eager loading 一起使用吗? - Skywarth

8

我正在使用PostgreSQL和MySQL:

DB::raw('CONCAT(member.last_name, \' \', member.first_name) as full_name')

5
$text = "other";
$limit = 100
public function get_data($text, $limit)
{
    
    $result = $this->select('titulo', 'codigo', DB::Raw("CONCAT(codigo, ' ', titulo_long) AS text_search"))
                ->where('tipo', '=', 2)
                ->having('text_search', 'LIKE', "%$text%")
                ->limit($limit)
                ->get();
    return $result;

}

}


4

这是 Laravel 中列拼接的示例。

我需要通过名称搜索用户,而我的用户名称有三个列(name_first、name_middle、name_last),因此我在 Laravel UserModel 中创建了一个作用域,该作用域将 $query用户名 作为第二个参数。

public function scopeFindUserByName($query,$name) {
    // Concat the name columns and then apply search query on full name
    $query->where(DB::raw(
            // REPLACE will remove the double white space with single (As defined)
            "REPLACE(
                /* CONCAT will concat the columns with defined separator */
                CONCAT(
                    /* COALESCE operator will handle NUll values as defined value. */
                    COALESCE(name_first,''),' ',
                    COALESCE(name_middle,''),' ',
                    COALESCE(name_last,'')
                ),
            '  ',' ')"
        ),
    'like', '%' . $name . '%');
}

您可以在任何需要按用户名搜索用户的地方使用此作用域,例如:

UserModel::findUserByName("Max Begueny");

或者

$query = UserModel::query();
$query->findUserByName("Max Begueny");

要查看此SQL查询的结果,只需按照此帖子中的步骤进行操作。 https://stackoverflow.com/a/62296860/11834856


2

这段代码应该可以正常运行:

User::select(\DB::raw('CONCAT(last_name, first_name) AS full_name)')

0

清洗数据:在使用 Laravel 和其他编程语言进行开发时,我经常会使用 CONCAT()。尽管这里的答案对一定程度上有用,但我仍然没有找到在 Laravel/Eloquent/Query Builder 中使用 CONCAT() 的优雅方式。

然而,我发现在返回结果后连接列通常很适合我,并且通常非常快速 - 清洗数据 -(除非您有一个巨大的结果,出于性能原因,应该“分块”处理)。

foreach($resultsArray AS $row){
    $row['fullname'] = trim($row['firstname']).' '.trim($row['lastname']);
}

当然,这是一种权衡,但就个人而言,我发现它更易于管理,并且不会限制我对 Eloquent 和查询构建器的使用。 (上面是伪代码-未经测试,因此根据需要进行调整)

还有其他解决方法,不会影响 Eloquent / 查询构建器功能,例如在表中创建一个连接列,在这种情况下为 full_name-插入/更新记录时保存全名。 这并不罕见。


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