0

How do I convert the following into Eloquent syntax? I know there is a derived table in there, so unsure what's the right syntax in Laravel for this?

    SELECT firstname
, CONCAT_WS
( ', '
, CASE WHEN years = 0 THEN NULL ELSE CONCAT(years,' years') END
, CASE WHEN months = 0 THEN NULL ELSE CONCAT(months, ' months') END
, CASE WHEN days = 0 THEN NULL ELSE CONCAT(days, ' days') END
) lengthOfService
FROM
( SELECT firstname
, FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425) years
, FLOOR((DATEDIFF(CURDATE(),startdate)/365.2425 - FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12) months
, CEILING((((DATEDIFF(CURDATE(),startdate)/365.2425 - FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12)
- FLOOR((DATEDIFF(CURDATE(),startdate)/365.2425 - FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12))* 30) days
FROM users
) x
5
  • 1
    Eloquent is an ORM, it will translate physical relational tables into objects. I don't think it applies to derived tables. You can however add a scope in your users table to filter down to that derived table. Commented Jun 13, 2017 at 14:38
  • @apokryfos could I just wrap this into DB::raw() in theory? Commented Jun 13, 2017 at 14:38
  • 1
    Yes you can, but that's not really using Eloquent, that's just using the query builder. Commented Jun 13, 2017 at 14:39
  • Check out query scopes in case it helps (and in case you have a users model you can scope) Commented Jun 13, 2017 at 14:40
  • You could use hydrateRaw. It is not documented though: laravel.com/api/5.3/Illuminate/Database/Eloquent/… Commented Jun 13, 2017 at 14:45

3 Answers 3

1

Laravel does provide hydrateRaw

First make a model class, I will use App\Models\MyHydratedUser

$query = "SELECT firstname, CONCAT_WS ( ', '
, CASE WHEN years = 0 THEN NULL ELSE CONCAT(years,' years') END
, CASE WHEN months = 0 THEN NULL ELSE CONCAT(months, ' months') END
, CASE WHEN days = 0 THEN NULL ELSE CONCAT(days, ' days') END
) lengthOfService
FROM
( SELECT firstname
, FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425) years
, FLOOR((DATEDIFF(CURDATE(),startdate)/365.2425 - 
FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12) months
, CEILING((((DATEDIFF(CURDATE(),startdate)/365.2425 - 
FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12)
- FLOOR((DATEDIFF(CURDATE(),startdate)/365.2425 - 
FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12))* 30) days
FROM users
) x";

$users = App\Models\HydratedUser::hydrateRaw($query);

The $users variable will hold a Collection of HydratedUser models

Sign up to request clarification or add additional context in comments.

1 Comment

thanks. This works well. I wish this method was documented in the official Laravel docs.
1

Eloquent does not provide such specific methods. You will need to use DB::raw("...") (but that's not a solution I guess), or DB::select("SELECT ...");

Comments

1

Without Eloquent with Query Builder

Create sub query and using DB::table with DB::raw and selectRaw() method.

$subQuery = DB::table('users')
    ->selectRaw('firstname,
        FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425) years,
        FLOOR((DATEDIFF(CURDATE(),startdate)/365.2425 -
        FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12) months, 
        CEILING((((DATEDIFF(CURDATE(),startdate)/365.2425 - 
        FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12) - 
        FLOOR((DATEDIFF(CURDATE(),startdate)/365.2425 - 
        FLOOR(DATEDIFF(CURDATE(),startdate)/365.2425))* 12))* 30) days');

DB::table(DB::raw('('.$subQuery->toSql().') as tableName')
    ->selectRaw("firstname, CONCAT_WS(', ', 
        CASE WHEN years = 0 THEN NULL ELSE CONCAT(years,' years') END, 
        CASE WHEN months = 0 THEN NULL ELSE CONCAT(months, ' months') END, 
        CASE WHEN days = 0 THEN NULL ELSE CONCAT(days, ' days') END) lengthOfService")

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.