Search code examples
phpeloquentlaravel-5query-builderphp-carbon

Laravel 5: Convert query builder to eloquent


Is there a way to transform this query builder to eloquent?

$users = DB::table('connections')
        ->join('locations','connections.to_user','=','locations.user_id')
        ->join('users','connections.to_user','=','users.id')
        ->select(
            DB::raw("*, IF((
                    3959 * acos(
                    cos(radians(".$lat."))
                    * cos(radians(latitude))
                            * cos(radians(longitude) - radians(".$lng."))
                            + sin(radians(".$lat."))
                            * sin(radians(latitude)))
                    ) < ".$distance.",true,false) near,(
                    3959 * acos(
                    cos(radians(".$lat."))
                    * cos(radians(latitude))
                            * cos(radians(longitude) - radians(".$lng."))
                            + sin(radians(".$lat."))
                            * sin(radians(latitude)))
                    ) AS distance")
        )
        ->where('status',3)
        ->orderBy("distance")
        ->get();

Connection model

public function getCreatedAtAttribute()
{
  return \Carbon\Carbon::parse($this->attributes['created_at'])->diffForHumans();
}

Because using query builder is not possible to return the created_at attribute in "diffForHumans" of Carbon.


Solution

  • If all you want is Carbon::diffForHumans, you can just convert (cast) created_at to Carbon.

    Some of the possible usage:

    • $dt = ( (Carbon) $row->created_at ) // Casting
    • $dt = Carbon::instance($row->created_at)

    And I would suggest on keeping Fluent queries instead of converting to Eloquent, as Eloquent is really only good for simple CRUD and simple relations.

    Hope this helps :)

    EDIT More example:

    /* $rows = (Fluent queries)->get() */
    
    foreach ($rows as $row) {
        $row['created_at'] = Carbon::parse($row['created_at']);
    }
    

    Use a variation of the above if you want to continue using Fluent.

    If you insist on using Eloquent for whatever reason, you cannot set an accessor that exist as an attribute in the model.

    e.g.:

    getIdAttribute will never be called because there's already $model->attributes['id'].

    If instead you define a getHumanCreatedAtAttribute, it will be called
    because there is no $model->attributes['human_created_at']