Laravel 5 eloquent 的 CONCAT 列

Posted

技术标签:

【中文标题】Laravel 5 eloquent 的 CONCAT 列【英文标题】:CONCAT columns with Laravel 5 eloquent 【发布时间】:2017-08-01 18:47:50 【问题描述】:

将我视为 laravel 初学者

目标是:我有两个列,现在我需要在id 前面加上表中同一行的component name

例如(工作中)...我有 mysql 之类的

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

输出是

身份证

|TestComp 40  |
 -------------
|component 41 |
 -------------
|test 42      |

我需要同样的 laravel 雄辩的方式,因为这里的组件是模型名称。所以我尝试了类似的东西

$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框架总是开销。 【参考方案1】:

您需要将查询包装在DB::raw

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

另外,请注意,因为您正在执行这样的查询,您的模型可能会有不同的行为,因为此 select 会从 select 语句中删除所有其他字段。 因此,如果没有新查询,您将无法从模型中读取其他字段。所以只能用它来读取数据而不是修改数据。

另外,为了使它成为一个不错的列表,我建议您将查询修改为:

$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.

【讨论】:

谢谢。这是因为我有一个下拉菜单。它将显示来自两个表的组合列表。我使用了联合查询。在此之前,我计划在项目前加上前缀.. 这样我就可以区分哪个是组件和产品表。例如,如果用户选择属于产品的 5 个项目和属于组件表的 2 个项目。然后我可以取以 p.. 为前缀的项目。所以我将得到这 5 个项目.. 然后我可以在保存时删除该前缀。并且还要注意,在为用户显示时,它的值将被隐藏.. 所以用户只能看到项目而不是它的值,我也通过删除前缀来保存 $comp = Component::select(DB::raw("CONCAT(name,id) AS display_name"),'id')->get()->pluck('display_name', 'ID'); // 转储输出以查看它的外观。 dd($comp);// 数组键应该是数组索引,值是连接值。这适用于我的修改 它只显示姓名和身份证,而不是显示实际姓名和身份证。我确实喜欢这个。 $comp = Component::select(DB::raw("CONCAT(name,id) AS ID"))->get() @RajeshKChaudhary 可能是您的数据库引擎。当您开始使用原始 sql 时,您必须注意您的数据库系统语法。 @Tschallacka 在您的示例中,必须在 select 函数中传递 name 列名,然后我们可以在 CONCAT 函数中使用它,否则它提供空白值。 $comp = Component::select(DB::raw("CONCAT('name','id') AS display_name"),'id','name')->get()->pluck('display_name','id');【参考方案2】:

我自己来此帖子寻求答案。对我来说唯一的问题是答案并没有真正适合我的情况。我有许多表关系设置,我需要其中一个子对象来连接字段。 DB::raw 解决方案对我来说太乱了。我不断搜索并找到了我需要的答案,并觉得这是一个更简单的解决方案。

我建议尝试使用Eloquent Accessor,而不是DB::raw。访问器允许您检索模型属性并创建不是由原始模型创建的新属性。

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

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 值本身,但因为我声明了相同的名称,它似乎只允许访问该字段值而不允许访问其他字段。

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

【讨论】:

对于 Laravel 5.8,我必须同时做 Answer1 和 answer2 中描述的事情。 这是否适用于急切加载?【参考方案3】:

我正在研究 posgresql 和 mysql:

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

【讨论】:

【参考方案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://***.com/a/62296860/11834856

【讨论】:

【参考方案5】:

清理数据:在使用 Laravel 之前和现在,在使用其他语言进行开发时,我会定期使用 CONCAT()。这里的答案在一定程度上有效,但在 Laravel/Eloquent/Query Builder 中仍然没有一种优雅的方式来使用 CONCAT() 我已经找到了。

但是,我发现在返回结果后连接列对我来说效果很好,而且通常非常快 - 清理数据 - (除非你有一个巨大的结果,出于性能目的可能应该“分块”)。

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

这当然是一种权衡,但就我个人而言,我发现它更易于管理,并且不会限制我按预期使用 Eloquent 以及 Query Builder。 (以上是伪代码 - 未经测试,因此根据需要进行调整)

还有其他不与 Eloquent/Query Builder 功能混淆的解决方法,例如在表中创建连接的 col,在本例中为 full_name - 在插入/更新记录时保存全名。这并不少见。

【讨论】:

以上是关于Laravel 5 eloquent 的 CONCAT 列的主要内容,如果未能解决你的问题,请参考以下文章

php Laravel 5 Eloquent CheatSheet #laravel #eloquent

原始查询中的 Laravel 选择计数

Laravel 5 - 使用 Mockery 模拟 Eloquent 模型

5 个 Laravel Eloquent 小技巧

Laravel 5 eloquent 的 CONCAT 列

使用 Laravel 5.5 接收 [Illuminate\Database\Eloquent\MassAssignmentException] 电子邮件