I have this PostgreSQL query which checks a value if it matches one of the string pattern in the table:
SELECT * FROM table WHERE 'value' LIKE column
I want to do this in Laravel 5.1 using Eloquent. But doing something like :
$prefix = 'value';
Model::where($prefix, 'LIKE', column)->firstOrFail();
returns an error. Apparently the first argument of where ($prefix) will always be treated as column name in Laravel (put between double quotes). Is there anyway to fix this or any better way to do it?
Use raw:
Model::whereRaw("'{$prefix}' LIKE column")->firstOrFail();
Replace:
Model::where($prefix, 'LIKE', "'%' || column_name || '%'")->firstOrFail();
With:
Model::where('.$prefix.', 'LIKE', "'%' || column_name || '%'")->firstOrFail();
Related
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 gets 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?
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'
// )
// )
To use aliases on eloquent models modify your code like this:
Item
::from( 'items as items_alias' )
->join( 'attachments as att', DB::raw( 'att.item_id' ), '=', DB::raw( 'items_alias.id' ) )
->select( DB::raw( 'items_alias.*' ) )
->get();
This will automatically add table prefix to table names and returns an instance of Items model. not a bare query result.
Adding DB::raw prevents laravel from adding table prefixes to aliases.
Here is how one can do it. I will give an example with joining so that it becomes super clear to someone.
$products = DB::table('products AS pr')
->leftJoin('product_families AS pf', 'pf.id', '=', 'pr.product_family_id')
->select('pr.id as id', 'pf.name as product_family_name', 'pf.id as product_family_id')
->orderBy('pr.id', 'desc')
->get();
Hope this helps.
To use in Eloquent.
Add on top of your model
protected $table = 'table_name as alias'
//table_name should be exact as in your database
..then use in your query like
ModelName::query()->select(alias.id, alias.name)
You can use less code, writing this:
$users = DB::table('really_long_table_name')
->get(array('really_long_table_name.field_very_long_name as short_name'));
And of course if you want to select more fields, just write a "," and add more:
$users = DB::table('really_long_table_name')
->get(array('really_long_table_name.field_very_long_name as short_name', 'really_long_table_name.another_field as other', 'and_another'));
This is very practical when you use a joins complex query
I have tried all these options and none works for me. Then I had found something in the Laravel documentation that really works.
You could try this:
DB::table('table_one as t1')
->select(
't1.field_id as id','t2.field_on_t2 as field'
)->join('table_two as t2', function ($join) {
$join->on('t1.field_id ', '=', 't2.field_id');
})->get()
Also note that you can pass an alias as the second parameter of the table method when using the DB facade:
$users = DB::table('really_long_table_name', 'short_name')
->select('short_name.id')
->get();
Not sure if this feature came with a specific version of Laravel or if it has always been baked in.
Same as AMIB answer, for soft delete error "Unknown column 'table_alias.deleted_at'",
just add ->withTrashed() then handle it yourself like ->whereRaw('items_alias.deleted_at IS NULL')
In the latest version of Laravel 9, you can use alias name for column as:
$events = Booking::whereBetween('sessionDateTime', [$today, $nextMonth])->get(['bookings.sessionDateTime as start']); // start is an alias here
Currently I'm working on a ajax search filters on Laravel, but I cannot get the correct info, this is the scenario:
I have 2 tables:
Table1: SoftwareRequest
Table2: DenyCategory
with a select option I get the name as Value
and I added that select option like in top of the query on the controller function:
$deniedReason = $request->get('deniedReason');
if($deniedReason == "All"){
$deniedReason = "";
}
So that means that every time I select "All" it will be empty so I can get all data like empty (this is the problem).
This is my current query:
$request_data = SoftwareRequest::leftJoin('DenyCategory', 'SoftwareRequest.DenyCategoryId', '=', 'DenyCategory.Id')->where('DenyCategory.Name', 'like', '%' . $deniedReason . '%')->paginate(20);
So the thing is that if I select another option rather than "All", for example "Already Available", I do get the excepted data, meaning all objects from table 1 joined with table 2 that has that option, but the problem comes when I select "All" it doesn't bring all the data it should and that's because not all objects have DenyCategoryId in Table1 meaning that some of those are Null/empty so it only brings the ones 'LIKE' Null/empty as I specified on the previous code block.
$deniedReason = $request->get('deniedReason');
if($deniedReason == "All"){
$deniedReason = "";
}
How can I get all data empty or not empty when I select the option All and as well as to get the data when I select another option? I bet it would have something to do with the query not being 'Like' but that's out of my knowledge scope.
Why not make the where clause optional?
$queryBuilder = SoftwareRequest::leftJoin('DenyCategory', 'SoftwareRequest.DenyCategoryId', '=', 'DenyCategory.Id')
// Only apply where-clause when denied reason has been provided.
if ($request->get('deniedReason') !== 'All') {
$queryBuilder = $queryBuilder->where('DenyCategory.Name', 'like', '%' . $deniedReason . '%');
}
$request_data = $queryBuilder->paginate(20);
I think you can improve your code a bit better but I'll leave that up to you with some pointers:
Eloquent relationships
Class Constants
So how i can add multi statement to query in ::where model.
Actually it lok like that:
certs::where('unique', '=', $newUnique )->get()
i need somethig like that:
certs::where('unique, num', '=', $newUnique,$key )->get()
so in sql look like that
Select * From certs Where unique = $newUnique AND num = $key
I need that to check if data need to be updated or inserted.
Just append another where clause
certs::where('unique', $newUnique)->where('num', $key)->get()
For example
App\User::where('first_name', 'John')->where('last_name', 'Doe')->toSql();
Would result in
"select * from `users` where `first_name` = ? and `last_name` = ?"
Hope this helps
It can become tricky if there will be OR instead of AND, so you should always prefer
for AND
Certs::where(function($query) use ([$newUnique, $key]){
$query->where('first_name', 'John')->where('last_name', 'Doe');
})->get();
for OR
Certs::where(function($query) use ([$newUnique, $key]){
$query->where('first_name', 'John')->orWhere('last_name', 'Doe');
})->get();
Laravel allows multi statements for "where" function of Model by passing array of conditions.
The below code can be used if you are applying "and" condition and "=" operation for each data.
$conditions = ['unique'=>$newUnique,'num'=>$key];
Certs::where($conditions)->get();
Else if you want to use different operations with "and" condition, use below code.
$conditions = [
['unique','=',$newUnique],['num','!=',$key]
];
Certs::where($conditions)->get();
Also, you can use below code for "and" and "or" conditions.
Certs::where(function($query) use ($newUnique, $key]){
$query->where('unique', $newUnique);
$query->orWhere('num', $key);
})->get();
Similarly, you can use orWhere(), whereColumn(), whereBetween() and other query builder functions.
You can do something like this:
certs::where(['unique'=>$newUnique, 'num' => $key])->get()
Currently I am having success with the following query:
if (isset($data->action_needed_status) && $data->action_needed_status != '') {
$query->where('status', 'like', '%'.$data->action_needed_status.'%');
$query_count->where('status', 'like', '%'.$data->action_needed_status.'%');
The complaint was this:
Since status is an ENUM field you know that any valid status value
passed should match exactly. There shouldn't be a need for using LIKE
in the where statements.
What would be the best way to have same result without using LIKE?
I have next query in Laravel Eloquent:
$buildings = Building::select('buildings.*')->join(
DB::raw('('.
(
IngameBuilding::select('buildings.building_id', 'buildings.level')
->join('buildings', 'buildings.id', '=', 'ingame_buildings.building_id')
->toSql()
).
') as `added_buildings`'), 'added_buildings.building_id', '=', 'buildings.building_id')
->where('buildings.level', '>', 'added_buildings.level')
->get();
This query returns all allowed rows from base, but one row more. When I added DB::raw() in where() return values is valid.
Good-working code:
$buildings = Building::select('buildings.*')->join(
DB::raw('('.
(
IngameBuilding::select('buildings.building_id', 'buildings.level')
->join('buildings', 'buildings.id', '=', 'ingame_buildings.building_id')
->toSql()
).
') as `added_buildings`'), 'added_buildings.building_id', '=', 'buildings.building_id')
->where('buildings.level', '>', DB::raw('`added_buildings`.`level`'))
->get();
Why first code workig, hmm.. Wrong?
I'm not a big fan of Laravel at all.
I've got only small experience with this framework but i'm almost sure that where function accepts only a 'constant' values to be checked against.
If you'll get an output of this query using toSQL method on the query object you will see that eloquent will convert it as something like:
(...) where buildings.level > 'added_buildings.level'
so the condition checks if the buildings.level (whatever the type is)
is greater than the given string and not the column value.
Using the DB::raw you're getting the proper sql as the eloquent won't parse/convert it.
You would need to use whereRaw method I suppose.
http://laravel.com/docs/4.2/queries#introduction