7

I'm trying to concat two columns from different tables into one single column.

$user = User::with(array('Person'=>function($query){
    $query->selectRaw('CONCAT(prefix_person.name, " - ", prefix_user.code) as name, prefix_user.id');
}))->lists('name', 'id');

In my person class I have this method:

public function User()
{
    return $this->hasOne('User');
}

And in my user class I have this one:

public function Person()
{
    return $this->belongsTo('Person', 'person_id');
}

I get the following error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'name' in 'field list' (SQL: select `name`, `id` from `prefix_user`)

When I tried

$user = User::with(array('Person'=>function($query){
    $query->selectRaw('CONCAT(prefix_person.name, " - ", prefix_user.code) as name, prefix_user.id')->lists('name', 'id');
}));

I got this error:

error


I have used the selectRaw a couple of times, but never needed it into a with (join).

3
  • Can't you use an acessor that will concat it instead? It would make your logic easier to understand and to scale. Commented Apr 8, 2015 at 19:22
  • @Ravan Acessors are nice, but I don't know how these would work with lists and joins. Could you provide some example? Commented Apr 8, 2015 at 19:26
  • Oh, I see the issue now, let me think about it for a while. Commented Apr 8, 2015 at 19:37

3 Answers 3

12

The issue is that Eloquent will first query the users table, and only after, the persons table, so one query is not aware of the other and thus concatenating will not work.

You can use the Query Builder to do this using a join. It will be something like it:

$user = DB::table('users as u')
    ->join('persons as p', 'p.id', '=', 'u.person_id')
    ->selectRaw('CONCAT(p.name, " - ", u.code) as concatname, u.id')
    ->lists('concatname', 'u.id');

EDIT: And, as suggested by @michel-ayres comment, as long as you have an acessor to the field:

public function getFullNameAttribute() { 
    return $this->attributes['name'] . ' - ' . $this->attributes['code'];
}

you can use your own model to perform the join and listing:

User::join('person','person.id','=','user.person_id')
    ->select('person.name', 'user.code', 'user.id')
    ->get()
    ->lists('full_name', 'id');
Sign up to request clarification or add additional context in comments.

6 Comments

Eeyup, you got to the root of my problem :/ I followed your first suggestion and create an acessor within my class, following this example at laravel's forum. I still think is a little ugly (if this work as linq does, then it calls 2x the query), but uses Eloquent at least. Here is the final:
User::join('person','person.id','=','user.person_id')->orderBy('person.name', 'ASC')->select('person.name', 'user.code', 'user.id')->get()->lists('full_name', 'id'); and in the Model I have a method public function getFullNameAttribute() { return $this->attributes['name'] . ' - ' . $this->attributes['code']; }
If possible, add (don't change) to your answer the comment too =) thanks
@MichelAyres I guess that you can get rid of the ->get() entirely. Can you test it to see if it's correct so that I can update the answer?
I tested without the ->get() and got an error saying that I don't have full_name. I think it needed it to fill up the function getFullNameAttribute, so I can use it on the lists.
|
2

You can solve it simply by using simple query,

User::join('persons as p', 'p.id', '=', 'users.person_id')
       ->get([
            'id',
            DB::raw('CONCAT(p.name,"-",users.code) as name')
        ])
       ->lists('name', 'id');

Or, see another way

User::join('persons as p', 'p.id', '=', 'users.person_id')
      ->select(
          'id',
          DB::raw('CONCAT(p.name,"-",users.code) as name')

        )
       ->lists('name', 'id');

Comments

0

You can solve it by using this sample query

->when($request->value != null, fn ($q) => $q->where(DB::raw("CONCAT(col1,'',col2)"), '=', '' . $request->value. ''))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.