Call to a member function first() on double - php

I got an error in
Call to a member function first() on double
this is query builder in laravel
$player = DB::table('players')
->join('stats', 'players.username', '=', 'stats.player')
->sum('stats.winpot');
->first();

of course. it's obvious. the sum() function return sum of the selected column. a single value (not a collection of values)
the first() is for Collections, to get the first element from a collection.
Since the sum function returns the sum of the column values (A single value, not a Collection), you cant call first() function on it.
And Most importantly You Don't Have To.
NOTE
If you want to get both 'player' and the 'sum' you can execute two queries and bind those two results together.
Possible solution.
$player = DB::table('players')
->join('stats', 'players.username', '=', 'stats.player')
->first();
$player->sum = DB::table('players')
->join('stats', 'players.username', '=', 'stats.player')
->sum('stats.winpot');
now there is an attribute in retrieved 'player' as 'sum'. you can access it as $player->sum

Related

Eloquent queries work separately but not together in a subquery

I'm trying to fetch some data with a subquery using Eloquent but dding returns nothing. Separately, this
$discountArticles = $discountTableItemIdIn
->where('recipient_type', '=', 'article')
->toArray();
or this
$discountArticles = $discountTableItemIdIn
->where('recipient_id', '=', $articleId)
->toArray();
work fine.
However when I try something like this, it fails (or rather, returns nothing):
$discountArticles = $discountTableItemIdIn->where(function ($subQuery) {
$subQuery
->where('recipient_type', '=', 'article')
->where('recipient_id', '=', $articleId);
})->toArray();
I know I can do separate queries on the same collection and do an array_merge but I'd like to get this way working instead. Not sure what's happening.
So $discountTableItemIdIn is a collection of the entire table? That means you're gonna need a different function, as the ->where() logic on a collection is different from how it functions on a builder (eloquent) instance.
Try using filter():
$discountArticles = $discountTableItemIdIn->filter(function ($item) use($articleId) {
return $item->recipient_type == "article" && $item->recipient_id == $articleId;
})->toArray();
What this will do is filter your $discountTableItemIdIn collection for records that have a type of article and a recipient_id of whatever $articleId contains, return a new collection and convert that to an array.
Just a note, this is quite inefficient; you should try to avoid loading the whole table into a collection and just query the table directly using the subquery logic in your question.

How to get an array result set from Laravel where condition

I am trying to get a result set from a laravel eloquent query whereby I match a column against a list of values in an array.
$authenticated_operation_ids = AccessControl::where('user_id', '=', $user_id)
->where('entity_type_id', '=', $operation_entity_id)
->pluck('entity_access_id')->toArray();
$authenticated_operations = Operation::whereIn('id', $authenticated_operation_ids);
return view('page.index')->withOperations($authenticated_operations);
You can try it as:
$authenticated_operation_ids = AccessControl::where('user_id', '=', $user_id)->where('entity_type_id', '=', $operation_entity_id)->pluck('entity_access_id')->toArray();
$authenticated_operations = Operation::whereIn('id', $authenticated_operation_ids)->get();
return view('page.index')->withOperations($authenticated_operations);
Add get() at the end of the query.
1) pluck returns a single value from a single row. You want lists to get a single column from multiple rows. toArray may not be needed, as it returns an array of values
$authenticated_operation_ids = AccessControl::where('user_id', '=', $user_id)
->where('entity_type_id', '=', $operation_entity_id)
->lists('entity_access_id');
2) You're forgetting to actually retrieve the rows in your second line:
$authenticated_operations = Operation::whereIn('id', $authenticated_operation_ids)
->get();
You have to call get() function on the result set to obtain results. The modified code will be like
$authenticated_operation_ids = AccessControl::where('user_id', '=', $user_id)->where('entity_type_id', '=', $operation_entity_id)->get()->pluck('entity_access_id');
$authenticated_operations = Operation::whereIn('id', $authenticated_operation_ids)->get();
return view('page.index')->withOperations($authenticated_operations);
or you can use a cursor to process it.

Laravel fetch data from model where the condtions is from another model

I have a table called List which i planned to be displayed into view with this command : $lists= List::with('user', 'product.photodb', 'tagCloud.tagDetail')->get();. But, i want the data displayed is only those that has TagID equal to the one user inputted. Those data can be retrieved from TagCloud table.
What i am currently doing is :
$clouds = TagCloud::select('contentID')
->where('tagDetailID', '=', $tagID)
->get();
$lists = List::with('user', 'product.photodb', 'tagCloud.tagDetail')
->where('id', '=', $clouds->contentID)
->get();
But when i tried to run it, it only return a null value, even though when i am doing return $clouds, it does returned the desired ID.
Where did i do wrong ? Any help is appreciated !
A couple of gotchas with your current solution.
Using get() returns an Illuminate\Database\Eloquent\Collection object. Hence you can't use $clouds->contentID directly since $clouds is a collection (or array if you prefer). See Collection Documentation.
where(...) expects the third parameter to be a string or integer, aka single value. Instead, you are passing a collection, which won't work.
The correct way is to use whereHas() which allows you to filter through an eager loaded relationship.
Final Code:
$lists = List::with('user', 'product.photodb', 'tagCloud.tagDetail')
->whereHas('tagCloud',function($query) use ($tagID) {
return $query->where('contentID','=',$tagID);
})
->get();
See WhereHas Documentation.
What you want is whereHas()
$list = List::with(...)
->whereHas('relation', function($q) use($id) {
return $q->where('id', $id);
})->get();
Apply Where condition in you tagCloud model method tagDetail
public function tagDetail(){
return $q->where('id', $id);
}

Different values when use DB::raw() in second param on where()

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

How to count and fetch data query in laravel?

How to merge this two queries ?
$data = DB::table('category_to_news')
->where('category_to_news.name', ucwords($category))
->remember(1440)
->count();
and
$data = DB::table('category_to_news')
->where('category_to_news.name', ucwords($category))
->remember(1440)
->get();
So, as far as I understand from your comment, you simply want to get all records from the table category_to_news and you want to know how many records are in there, right?
MySQL's count is an aggregate functions, which means: It takes a set of values, performs a calculation and returns a single value. If you put it into your names-query, you get the same value in each record. I'm not sure if that has anything to do with 'optimization'.
As already said, you simply run your query as usual:
$data = DB::table('category_to_news')
->where('name', ucwords($category))
->remember(1440)
->get(['title']);
$data is now of type Illuminate\Support\Collection which provides handy functions for collections, and one them is count() (not to be confused with the above mentioned aggregate function - you're back in PHP again, not MySQL).
So $data->count() gives you the number of items in the collection (which pretty much is an array on steroids) without even hitting the database.
Hi DB class dont return collection object it give error "call member function on array" but eloquent return collection object. for above code we can use collect helper function to make it collection instance then use count and other collection methods https://laravel.com/docs/5.1/collections#available-methods .
$data = DB::table('category_to_news')
->where('name', ucwords($category))
->remember(1440)
->get();
$data = collect($data);
$data->count();
You my get it using:
$data = DB::table('category_to_news')
->where('name', ucwords($category))
->remember(1440)
->get();
To get the count, try this:
$data->count();
Why you are using DB::table(...), instead you may use Eloquent model like this, create the model in your models directory:
class CategoryToNews extends Eloquent {
protected $table = 'category_to_news';
protected $primaryKey = 'id'; // if different than id then change it here
}
Now, you may easily use:
$data = CategoryToNews::whereName(ucwords($category))->get();
To get the count, use:
$data->count();

Categories