Eloquent ORM: Obtain a object, not an array of objects - laravel

I have this statement in Laravel 4:
$prepayment = Prepayment::where('hash', '=', $custom)->take(1)->get();
But this return an array of objects, and I want only one object, because there are only one result with the hash that I search.
How is the way to obtain only one object, not an array of objects?
Thanks!

Use the first() method instead of the get() method
$prepayment = Prepayment::where('hash', '=', $custom)->first();

This is a good article to learn more about how the eloquent orm works. http://laravel.io/topic/14/how-eloquent-relationship-methods-work It describes how the belongs to relationship will just give you one object whereas the has many relationship will give you an arrray of objects

Related

Error Call to a member function where() on array Laravel

I want to do filtering from the data that I display, but there is a problem when I add where to my data.
the plan in the future I want to add if isset $request name, date and others. but was constrained at this one point.
Thank you for helping to answer in advance
$matchs =Matchs::where('type', 'sparring')->where('status','Pending')->whereNull('deleted_at')->get()->toArray();
$data=[];
foreach ($matchs as $key) {
$lawan = Matchs::where('id', $key['id'])->first()->ToArray();
$pertandingan = Sparring::where('match_id', $key['id'])->first()->ToArray();
$dua_arah = MatchTwoTeam::where('match_id', $key['id'])->first()->ToArray();
$tim = Team::where('id', $dua_arah['home_team'])->first()->ToArray();
$transfer['name']=$tim['name'];
$transfer['city']=$lawan['city'];
$transfer['field_cost']=$pertandingan['field_cost'];
$transfer['referee_cost']=$pertandingan['referee_cost'];
$transfer['logo_path']=$tim['logo_path'];
$transfer['nama_lapangan']=$lawan['nama_lapangan'];
$transfer['date']=$lawan['date'];
array_push($data,$transfer);
array_push($data,$pertandingan);
}
$data->where('name', 'LIKE', '%'.'football'.'%')->get()->toArray();
$data = array_search('football', array_column($data, 'name'));
$tittle="Sparring";
return view('mode.sparring',[
'tittle' => $tittle,
'data' => $data,
]);
You are trying to call where in an array which is not possible.
As you can see in the first line of your code you are calling where method in your model class. Like Matchs::where('type', 'sparring'), this is possible because Matchs is a Model class.
Now you can run where even if you are using array. You can convert that day in collection and then use array on that collection.
As below:
collect($data)->where('name', 'football')->toArray();
Here collect() will convert the $data array to collectio and then run the where() method in collectio then toArray() will change it back to array. But unfortunately there is no like operator possible in collection class. See the list of available method in Laravel collection here: https://laravel.com/docs/8.x/collections#available-methods
There is a way to do what you are trying to do. As far as I understand you want to filter the Matches where the Team name has footbal in it. You can do it like this:
Matchs::where('type', 'sparring')
->where('status','Pending')
->whereNull('deleted_at')
->whereHas('team', function($team) {
return $team->where('name', 'LIKE', '%'.'football'.'%')
})
->get()
->toArray();
So, here we can get the only those Mathes that has the Team that has the name contains football.
Few suggestion for you as seems you are new in Laravel:
Model name should be singular instead of plural, so the model class Matchs should be Match. Your name for team's model is Team is correct.
Avoid using toArray() because you won't need it. When you call get() it will return object of collection which more readable and powerful then array in most cases.
The code I suggested to use the like using whereHas will only work if you have propery defined your team relation in your Matchs class. So, defining your relationships in model is also important. If you do so, you don't even need the for loop and all those where in other model in that loop. You can do it in one query with all the relationships.

Laravel: Getting the first item after querying a collection already?

I need access to an entire collection but I also want to pull out and use the first item on the collection. Can first() be used outside the context of a query like this to get the first item?
$items = Item::with(['name'])->where('prod_num', '=', $num)->get();
$firstItem = $items->first();
Where you query a Model using Eloquent, as you are doing, it returns a Eloquent Collection.
Eloquent Collections extend Collections (https://laravel.com/docs/6.x/eloquent-collections#method-intersect), which have first() method available. So, you can use it.
Ref: https://laravel.com/docs/6.x/collections#method-first
Yes, you call the first() method to get the first element in the collection.
Since you called ->get() in $items it will return a collection, so you can call the first() method in it.

How to dissociate elements from a HasMany relation?

There's the save and saveMany methods on the HasMany relation class, but where are the dissociate(Many)/detach(Many) methods? There's also no built-in way to get the inverse relationship method, so what's the best way to dissociate an array of id's/models from a HasMany relationship object.
Currently I'm using:
$hasMany = $parent->theRelationship(); // Get the relationship object.
$child = $hasMany->getRelated(); // Get an empty related model.
$key = $hasMany->getForeignKeyName(); // Get the name of the column on the child to set to NULL.
$child->findMany($IDs)->each(function($model) use ($key) {
$model->$key = NULL;
$model->save();
});
This could be alot shorter with something like:
$hasMany = $parent->theRelationship();
$hasMany->dissociate($IDs);
Bonus points if you have any official answers from Taylor as to why he hasn't implemented this, I've seen him close feature requests of this kind on GitHub.
I am not sure why there isn't a function, but to be more performant than your example, you could use the DB class like:
\DB::table('child_table')->where('parent_id', $parent->id)->update(['parent_id' => null]);
You could use detach like so;
$parent->theRelationship()->detach([1,2,3])
Where you pass an array of IDs.
From Laravel documentation:
"For convenience, attach and detach also accept arrays of IDs as input"
The performatic way (1 db update):
$partent->theRelationship()->update(['parent_id' => null]);
The readable way (multiple db updates):
$parent->theRelationship->each->parentRelationship()->dissociate();

ManyToMany with and whereIn

I have a ManyToMany relationship between AdInterest and AdInterestGroup models, with a belongsToMany() method in each model so I can use dynamic properties:
AdInterest->groups
AdInterestGroup->interests
I can find all the "interests" in a single group like this:
$interests = AdInterestGroup::find(1)->interests->pluck('foo');
What I need is a merged, deduplicated array of the related 'foo' field from multiple groups.
I imagine I can deduplicate with ->unique(), but first, as you'd expect, this:
AdInterestGroup::whereIn('id',[1,2])->interests->get();
throws:
Property [interests] does not exist on the Eloquent builder instance.
The advice seems to be to use eager loading via with():
AdInterestGroup::with('interests')->whereIn('id',[1,2])->get();
Firstly, as you'd expect that's giving me an array of two values though (one for each ID).
Also, if I try and pluck('foo') again, it's looking in the wrong database table: from the AdInterestGroup table, rather than the relationship (AdInterest).
Is there a nice, neat Collection method / pipeline I can use to combine the data and get access to the relationship fields?
Use pluck() and flatten():
$groups = AdInterestGroup::with('interests')->whereIn('id', [1, 2])->get();
$interests = $groups->pluck('interests')->flatten();
$foos = $interests->pluck('foo')->unique();

Laravel - When to use ->get()

I'm confused as to when ->get() in Laravel...
E.G. DB::table('users')->find(1) doesn't need ->get() to retrieve the results, neither does User::find(1)
The laravel docs say "...execute the query using the get or first method..."
I've read the Fluent Query Builder and Eloquent docs but don't understand when the usage of get() is required...
Thanks for the help
Since the find() function will always use the primary key for the table, the need for get() is not necessary. Because you can't narrow your selection down and that's why it will always just try to get that record and return it.
But when you're using the Fluent Query Builder you can nest conditions as such:
$userQuery = DB::table('users');
$userQuery->where('email', '=', 'foo#bar.com');
$userQuery->or_where('email', '=', 'bar#foo.com');
This allows you to add conditions throughout your code until you actually want to fetch them, and then you would call the get() function.
// Done with building the query
$users = $userQuery->get();
For find(n), you retrieve a row based on the primary key which is 'n'.
For first(), you retrieve the first row among all rows that fit the where clauses.
For get(), you retrieve all the rows that fit the where clauses. (Please note that loops are required to access all the rows or you will get some errors).
find returns one row from the database and represent it as a fluent / eloquent object. e.g. SELECT * FROM users WHERE id = 3 is equivalent to DB::table('users')->find(3);
get returns an array of objects. e.g. SELECT * FROM users WHERE created_at > '2014-10-12' is equivalent to DB::table('users')->where('created_at', '>', '2014-10-12')->get() will return an array of objects containing users where the created at field is newer than 4014-10-12.
The get() method will give you all the values from the database that meet your parameters where as first() gets you just the first result. You use find() and findOrFail() when you are searching for a key. This is how I use them:
When I want all data from a table I use the all() method
Model::all();
When I want to find by the primary key:
Model::find(1)->first();
Or
Model::findOrFail(1)->first();
This will work if there is a row with a primary key of one. It should only retrieve one row so I use first() instead of get(). Remember if you deleted the row that used key 1, or don't have data in your table, your find(1) will fail.
When I am looking for specific data as in a where clause:
Model::where('field', '=', 'value')->get();
When I want only the first value of the data in the where clause.
Model::where('field', '=', 'value')->first();
Basically what you need to understand is that get() return a collection(note that one object can be in the collection but it still a collection) why first() returns the first object from the result of the query(that is it returns an object)
#Take_away
Get() return a collection first() return an object
You can use get() method with latest() method to get the latest record that were recently added to your table
For example
$user=Student::latest()->get();
return all the data in descending order

Resources