Trying to Create dynamic laravel query string but getting error - laravel

$string='->get()';
$data_asset=DB::table('assets').$string;
Object of class Illuminate\Database\Query\Builder could not be converted to string

I've got something similar to what you're trying to achieve.
In your code, your $data_asset=DB::table('assets') returns a QueryBuilder, which builds a string in the background with your query parameters.
To do what you're after:
// Create a QueryBuilder instance with a table
$q = DB::table('users');
// I actually set this elsewhere, but for this example I've set it here
$params = ['email'=>'joe.bloggs#example.com','toSql'=>true];
// Use the QueryBuilder instance again, specifying a criteria
$q->where('users.email', '=', $params['email']);
if ( isset($params['toSql']) ):
// Returns my query as it's full SQL string (minus parameters)
return $q->toSql();
else:
// Returns a Collection
return $q->get();
endif;
This allows you to build a dynamic QueryBuilder builder.

Related

Eloquent how to pass parameters to relationship

The code I'm trying to fix looks like this. I have an Hotel class which is used in a query to get all hotels in an area but it doesn't discard those which are not available. There's a method inside which should be an accessor but it's not written the way I expected it to be:
public function isAvailableInRanges($start_date,$end_date){
$days = max(1,floor((strtotime($end_date) - strtotime($start_date)) / DAY_IN_SECONDS));
if($this->default_state)
{
$notAvailableDates = $this->hotelDateClass::query()->where([
['start_date','>=',$start_date],
['end_date','<=',$end_date],
['active','0']
])->count('id');
if($notAvailableDates) return false;
}else{
$availableDates = $this->hotelDateClass::query()->where([
['start_date','>=',$start_date],
['end_date','<=',$end_date],
['active','=',1]
])->count('id');
if($availableDates <= $days) return false;
}
// Check Order
$bookingInRanges = $this->bookingClass::getAcceptedBookingQuery($this->id,$this->type)->where([
['end_date','>=',$start_date],
['start_date','<=',$end_date],
])->count('id');
if($bookingInRanges){
return false;
}
return true;
}
I wanted to filter out hotels using this query. So this is the query from the controller:
$list = $model_hotel->with(['location','hasWishList','translations','termsByAttributeInListingPage'])->get();
Is it possible to pass the range of days to the function?
By the way the first thing I tried was to use the collection after the query and pass a filter function through the collection and after that paginate manually but although it does filter, but apparently it loses
the "Eloquent" result set collection properties and it ends up as a regular collection, thus it doesn't work for me that way.
Maybe the best approach for that is to create a query scope (source) and put all your logic inside of this function.
after that you can call this scope and pass the dates. Example you will create a query scope and paste your code inside of it.
public function scopeisAvailableInRanges($query, $start_date, $end_date) {
}
then you will invoke this query scope in your controller like this.
$list = $model_hotel::isavailableinranges($start_date, $end_date)->with(['location','hasWishList','translations','termsByAttributeInListingPage'])->get();
keep in mind that inside of your query scope you will return a collection. A collection of all your available hotels.

Laravel Scope with join query

What im trying to do is to make this join into a scope function
$workorders =\DB::table('users')->leftjoin('work_orders','users.id','=','work_orders.user_id')->select('users.id','users.name','users.email','users.status','work_orders.cod','work_orders.deadline'->where('users.id','=','1');
$workorders = $workorders->get();
This is what I've tried with no success...
public function scopeOrders($query){
return $query->join('work_orders','users.id','=','work_orders.user_id')
->select('users.id','users.name','users.email','users.status','work_orders.cod','work_orders.deadline')
->where('users.id','=','1');
}
Expected result using the scope in a query
$usersWO = User::Orders()->get();
The only difference between $workorders = $workorders->get(); and $usersWO = User::Orders()->get(); is the output format. They both are bug-free.
A dd() on the former outputs a collection of stdClass objects with record values as properties.:
A dd() on the latter outputs a collection of models:
To modify the output of the second to look exactly like the first, you'll have to modify the client code since scopes return collections of models.
$usersWO = User::Orders()->get()->map(function ($user) {
return (object) $user->getAttributes();
});

Change collection to query builder in laravel

I have a function with return type Builder
For some specific case, i need to change the value of collection (which i'll get from builder object) and return updated value as builder object.
Is there any way to convert a collection back to it's builder object?
Here is what i want to achieve in simpler form:
$users = DB::table('users')->where('is_human',1); // Builder obj
$isAlien = true;
$users = $users->get()->map(function($user) use ($isAlien) {
$user->is_human = $isAlien? 0 : 1;
return $user;
});
Now, the problem is when i execute this code, it will return a collection.
But i want to return $users as Builder Object.
I have searched through the laravel's API document to find a solution.
Please share your knowledge.

Retrieving records from database using eloquent with optional query parameters

i have the following block of code in my Resource Controller:
$travel_company_id = Input::get('travel_company_id');
$transport_type = Input::get('transport_type');
$route_type = Input::get('route_type');
$travelRoutes = TravelRoute::where('travel_company_id', $travel_company_id)
->where('transport_type', $transport_type)
->where('route_type', $route_type)
->get();
Now what this does is it gets travelRoutes based on the parameters supplied. What i want is for it to do is perform a search based on the available parameters, that way if $route_type is empty the search will be performed only on travel_company_id and transport type.
Also if all the parameters are empty then it will simply do a get and return all available records.
I know i can do this with lots of if statements but then if i add a new parameter on the frontend i will have to add it to the backend as well, I was wondering if there was a much simpler and shorter way to do this in laravel.
The where method accepts an array of constraints:
$constraints = array_only(Input::all(), [
'travel_company_id',
'transport_type',
'route_type',
]);
$routes = TravelRoute::where($constraints)->get();
Warning: do not use Input::only() instead of array_only(). They're not the same.
Input::only() fills in any missing items with null, which is not what you want here.
This is pretty hacky and if you spend some time developing a solution I'm sure it could be much nicer. This assumes all the fields in the getSearchFields() function match the input names from the form and database.
/**
* Search fields to retrieve and search the database with. Assumed they match the
* column names in the database
*/
private function getSearchFields()
{
return ['travel_company_id', 'transport_type', 'route_type'];
}
public function search()
{
// Get a new query instance from the model
$query = TravelRoute::query();
// Loop through the fields checking if they've been input, if they have add
// them to the query.
foreach($this->getSearchFields() as $field)
{
if (Input::has($field))
{
$query->where($field, Input::get($field));
}
}
// Finally execute the query
$travelRoutes = $query->get();
}

About the laravel eloquent model

The laravel API document: Illuminate\Database\Eloquent\Builder::first() description that:
Model|Builder|null first(array $columns = array('*'))
Execute the query and get the first result.
Parameters
array $columns
Return Value
Model|Builder|null
I can't understand the mean of the return value, In which case it will return Model and In which case it will return Builder?
When you have used eloquent model for retrieving first record it return response in Model, and not sure about builder but when you retrieve records using builder it return builder object.
for example, consider we have states table and we are going to retrieve first record using two different method
1) Query Builder
$state_builder = DB::table("states")->first();
2) Eloquent Model
$state_eloquent = State::first();
you can check the difference between both response, and when no record found it will return null.

Resources