Change collection to query builder in laravel - laravel-5

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.

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 How to pass parameter to Accessor method in model via where condition while query building?

I have a Accessor method in Collection Model getSizesAttribute, which returns array of available sizes eg: ['S','L'], Now I need to get Models with have size 'S'. like:
$collections = $collections->where('sizes','S');
But sizes is array, could I manipulate this anyhow so that I could check returns only if sizes have specific size.
I tried making another method getIsSizeAttribute, like:
public function getIsSizeAttribute($size){
return in_array($size,$this->sizes);
}
Now How could I user this in Where condition like
$collections = $collections->where('is_size','S');
Mutators and Accessors only run skin-deep, after the query's already been executed. You could use Collection::filter() as Bangnokia suggests, but that wouldn't give you any performance benefit of actually applying the condition to the initial request.
I think what you're looking for here is a Query Scope. Add something like this to your Model class:
public function scopeSize(\Illuminate\Database\Eloquent\Builder $query, $size)
{
return $query->whereIn('sizes', $this->sizes[$size]);
}
And access it like this:
$collection = $model->size('S')->get();
You should use filter on collection
$collections = $collections->filter(function($item, $index) {
return in_array('S', $item->sizes);
});

Eloquent relationships query building method returns empty

I have a one-to-many relationship, which works perfectly when using the relationship as a property on a query, but when i try to use it as a method it always return empty.
User Model
public function reports()
{
return $this->hasMany('App\Report', Report::COL_USER_ID, self::COL_ID);
}
Report Model
public function user()
{
return $this->hasOne('App\User', User::COL_ID, self::COL_USER_ID);
}
This Works
$reports = User::find($id)->reports;
This Doesn't and i need something like this
$reports = User::find($id)->reports()->orderBy(Report::COL_CREATED_AT, self::ORDER_BY_DESC);
According to the eloquent doc, "since all relationships also serve as query builders, you can add further constraints", so that should totally be retrieving the proper data, am I missing something? Thanks in advance for any help
You need to use get method to get actual results, so you should use:
$reports = User::find($id)->reports()->orderBy(Report::COL_CREATED_AT, self::ORDER_BY_DESC)->get();
instead of only:
$reports = User::find($id)->reports()->orderBy(Report::COL_CREATED_AT, self::ORDER_BY_DESC);
In your case, you only created query and haven't get any results from database. That's why you don't get any results.
And the reason why:
$reports = User::find($id)->reports;
works is because it's shortcut for:
$reports = User::find($id)->reports()->get();
If you try to use:
$reports = User::find($id)->reports();
only you won't get any results either.

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.

Doctrine Query Builder - How to select a many-to-many relationship?

I have a form in Symfony2 that needs to have an entity choice field filled with a collection of Players in a particular tournament. I create the form Type and pass the tournament ID to the query_builder property of the correct field. In the entity repository I have this method:
public function allPlayersInTournamentQuery($tournament_id)
{
$repo = $this->getEntityManager()->getRepository('GameBundle:Tournament');
$tournament = $repo->find($tournament_id);
$players = $tournament->getPlayers();
$playersIds = array();
foreach ($players as $player) {
$playersIds[] = $player->getId();
}
$playersQuery = $this->createQueryBuilder('p')
->in('p.id', $playersIds)
->orderBy('p.real_name', 'ASC');
return $playersQuery;
}
The function in() does not exist in the query builder. I hope the method shows what I am trying to do. Im tying to return the query builder that selects the correct players found in the given tournament.
How can I achieve this?
Thanks!
You can use the helper methods provided by the query builder $playersQuery->expr()->in('p.id', $playersIds)
Your query will be something like that:
$playersQuery = $this->createQueryBuilder('p');
$playersQuery->where($playersQuery->expr()->in('p.id', $playersIds))
->orderBy('p.real_name', 'ASC');
More information about the helper methods here

Resources