Viewed   578 times

Lets say we are using Laravel's query builder:

$users = DB::table('really_long_table_name')
           ->select('really_long_table_name.id')
           ->get();

I'm looking for an equivalent to this SQL:

really_long_table_name AS short_name

This would be especially helpful when I have to type a lot of selects and wheres (or typically I include the alias in the column alias of the select as well, and it get's used in the result array). Without any table aliases there is a lot more typing for me and everything becomes a lot less readable. Can't find the answer in the laravel docs, any ideas?

 Answers

3

Laravel supports aliases on tables and columns with AS. Try

$users = DB::table('really_long_table_name AS t')
           ->select('t.id AS uid')
           ->get();

Let's see it in action with an awesome tinker tool

$ php artisan tinker
[1] > Schema::create('really_long_table_name', function($table) {$table->increments('id');});
// NULL
[2] > DB::table('really_long_table_name')->insert(['id' => null]);
// true
[3] > DB::table('really_long_table_name AS t')->select('t.id AS uid')->get();
// array(
//   0 => object(stdClass)(
//     'uid' => '1'
//   )
// )
Friday, October 28, 2022
3

With straight SQL you could give each joined table an alias - e.g.

SELECT flights.*
FROM flights as f
 JOIN cities as fromCity on fromCity.pana = f.from_city
 JOIN cities as toCity on toCity.pana = f.to_city
WHERE f.id = 3 --

With Eloquent, use select() to specify select fields. Also use DB::raw() to use raw SQL (e.g. giving an alias to table like DB::raw('cities as toCity').

public function scopePrintQuery($query, $id)
{
  $join = $query
    -> join(DB::raw('cities as fromCity'), 'fromCity.pana', 'flights.from_city')
    -> join(DB::raw('cities as toCity'), 'toCity.pana', 'flights.to_city')
    -> where('flights.id', $id)
    ->select([
        'flights.*',
        DB::raw('fromCity.name as from_city')
        DB::raw('toCity.name as to_city')
    ]);
    return $join->get();
}
Saturday, October 29, 2022
 
5

It looks like you are not relating objects correctly. Let's break that down:

If a Garage Has Many Car then a Car Belongs To Garage, Lets proceed with this idea in mind.

  • Garage Has Many Car
  • Car Has Many Security
  • Security Belongs To Car
  • Garage Has Many Security Through Car

In Eloquent you can just go ahead and clap those relations in, it should work given the schema you posted above.

class Garage extends Eloquent
{
    public function cars()
    {
        return $this->hasMany('cars');
    }

    public function securities()
    {
        return $this->hasManyThrough('Security', 'Car');
    }
}

class Car extends Eloquent
{
    public function securities()
    {
        return $this->hasMany('Security');
    }

    // ADDED IN SECOND EDIT

    public function garage()
    {
        return $this->belongsTo('Garage');
    }       
}

class Security extends Eloquent
{
    public function car()
    {
        return $this->belongsTo('Car');
    }
}

And that should be it.

EDIT: You can access all these relations from any model as long as there is a path you can draw from one model to another using a combination of these relations. Check this out for example:

$security = Security::with('car.garage')->first();

will retrieve first Security record and load Car relation on it, then it goes one more step and load all Garage relations on every Car object loaded under Security model.

You can access them using this syntax:

$security->car->garage->id

// Other examples
$garage = Garage::with('cars.securities')->first();

foreach($garage->cars as $car)
{
    foreach($cars->securities as $security)
    {
        echo "Car {$car->id} has {$security->id} assigned to it";
    }
}

Furthermore, notice that the relationship objects are an instance of Collection so you have all the fancy methods such as ->each(), ->count(), ->map() available on them.

Monday, December 5, 2022
 
3

Here's an odd work-around (didn't want to extend the Builder and JoinClause classes):
Notice: This will break query chaining with -> so notice the where was seperated below.

$query = DB::table('awards')
         ->leftJoin('winners', function($join)
               {
                    $join->on('awards.id','=','winners.award_id');
                    $join->on('winners.year','=',DB::raw('?'));  
               }
         ->setBindings(array_merge($query->getBindings(),array($year)));

$query->where('awards.type','color');

$awards = $query->get();

UPDATE: Taylor added joinWhere, leftJoinWhere... he says that "if you have a function join just use ->where and ->orWhere from within the Closure." I've yet to try this though.

Wednesday, October 26, 2022
 
jimmy_z
 
1

I can think of three methods. For example, let's say you want to get the difference between the columns c and e.

Select with raw expressions

With raw expressions you can use all available SQL functions and ordinary math operators as well. Basically you can do everything what you could in a normal SQL select because Laravel will insert the string directly into the query.

$result = DB::table('a')
    ->join('b')
    ->where('c')
    ->orderBy('d')
    ->select('e', DB::raw('c - e AS differenceCE'));

Now the result will have a differenceCE property containing the result of the division.

Attribute accessors

This only works with Eloquent Models!

You can create a new dynamic attribute in your model, that will be calculated the moment you access it

class MyModel extends Eloquent {
    protected $appends = array('difference');

    public function getDifferenceAttribute(){
        return $this->attributes['c'] - $this->attributes['e'];
    }
}

Access the property:

$mymodel->difference;

for(each)

You can also use a simple loop like:

foreach($result as $model){
    // do math
}

Or if you're using Eloquent there's the each method you can call on a collection

$result->each(function($model){
    // do math
});

Just be aware that method 1 and 2 may result in (slightly) better performance. SQL just because it has to go through every record anyways and the method with the attribute accessor has the advantage that it will be lazy loaded. Meaning the calculation only happens when you use it (when you access the property)

Sunday, August 14, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :