Eloquent Laravel sort paginate query by related model - laravel

I have the following Eloquent query.
Company::has('cars')->with([
'cars', 'location' => function ($q) {
$q->nearBy(); // *** See futher
}
])->take(40)->paginate(10);
How can I order the Companies by distance?
*** This is the NearBy Scope in the Location-model:
public function scopeNearBy($query)
{
$location = json_decode(request()->cookie('location'));
$query->distance($location->lat, $location->lng); // ** Using package
return $query->orderBy('distance');
}
** Which uses this package.
The calculation of the distances is OK and works when I call the following.
\App\Address::nearBy()->get()

You have to join location table to Company query, and then you can order by distance.

In my opinion, the only way is to store the distance of each location when they are added. Then, of course, you can order them by distance.

if you can find distance using that package . Append the distance to your Company Model.
Then you can easily sort the collection in controller
refer https://laravel.com/docs/5.8/collections#method-sortby

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.

In Laravel Eloquent, how to check for multiple relationship existence in one "has"?

So, in order to check the existence of a relationship on a model, we use the has function on the relationship like model1->has('relationship1').
While it is possible to supply the model1->with() function with an array of relations to eager load them all, both has and whereHas functions do not accept arrays as parameters. How to check for the existence of multiple relationships?
Right now, I am running multiple has functions on the same model (The relations are not nested):
model1->has('relationship1')
->has('relationship2')
->has('relationship3')
But that is tedious and error-prone. Solution anyone?
There unfortunately isn't a way to pass an array of relationships to has() or whereHas(), but you can use a QueryScope instead. On your Model, define the following:
public function scopeCheckRelationships($query){
return $query->has("relationship1")->has("relationship2")->has("relationship3");
}
Then, when querying your Model in a Controller, simply run:
$result = Model::checkRelationships()->get();
The function name to use a Scope is the name of the function, minus the word scope, so scopeCheckRelationships() is used as checkRelationships().
Also, it's actually possible to pass the relationships you want to query as a param:
public function scopeCheckRelationships($query, $relationships = []){
foreach($relationships AS $relationship){
$query->has($relationship);
// Might need to be `$query = $query->has(...);`, but I don't think so.
}
return $query;
}
...
$result = Model::checkRelationships(["relationship1", "relationship2", "relationship3"])->get();
In case you need this to be dynamic.
Here's the documentation for Query Scopes if you need more info: https://laravel.com/docs/5.8/eloquent#query-scopes

Why does collection->where() return index number?

I'm sure this may be a simple solution, but I can't seem to work it out.
I am trying to use Laravel's where() clause to build an array of $courses that belong to each $student. I cycle through each $student and filter the $courseRecords to find matching courses based on their StudentCode.
Here is my sample code snippet:
// Cycle through the students and add their relevant course details
foreach( $students as $student ) {
// Find matching courses to the student
$courses = $courseRecords->where( 'StudentId', $student->StudentCode );
// Add the course array to the student record
$student->Courses = $courses;
}
However, the result I get, gives me each student's course, but with a leading index number (as shown below in random results):
I can't seem to work out why this is happening. The first entry (Id 0) is the result I am expecting, but for some reason, every other result seems to give me the matching index number of $courseRecord.
I have tried using $courses->all(); and $courses->toArray(); but this doesn't make any difference. From the Laravel documentation (that I have read), it doesn't mention this behaviour which makes me think I have something incorrect.
$students and $courseRecords are both a collection.
Use values():
$courses = $courseRecords->where('StudentId', $student->StudentCode)->values();

Sort by key in Eloquent

This is my Matrix model:
Matrix -> Finding -> Norm -> Normtype
(finding_id) (norm_id) (normtype_id)
I'd like to fetch Matrixes, sorted first by finding_id, then by normtype_id.
From what I've read, orderBy only applies to keys in the actual model, such as:
public function findings() {
return $this->hasMany('App\Finding')->orderBy('finding_id');
}
How can I do this in Eloquent?
Just to clarify, a matrix has many findings, and each finding belongs to a norm, and each norm has a normtype.
When you put the orderBy call on a relation definition, you only change how the related models are sorted. If you want to sort by related model's attributes, you'll need to build a proper join yourself.
The following should do the trick in your case:
Matrix::join('findings', 'finding_id', 'findings.id')
->join('norms', 'findings.norm_id', 'norms.id)
->orderByRaw('finding_id, norms.normtype_id')
->get();

How do I define relation between users and points in Eloquent ORM

I have 3 tables:
Users - for storing users
User_point - for associacion between users and points(has only user_id and point_id)
Points for description of points(id, amount, description)
How do I define a relation between these? I tried
public function points(){
return $this->belongsToMany('\App\Point', 'user_point');
}
but when I do
return $user->points()->sum('amount');
it returns just one
Edit:
At first I tried making it like this as it makes more sense:
public function points(){
return $this->hasMany('\App\Point');
}
But it wouldn't work
SUM is an aggregate function and so it should only return one row.
$user->points will be a collection of points attached to that user.
$user->points() is a query that you can do additional work against (i.e. $user->points()->whereSomething(true)->get()).
As user ceejayoz pointed out, using user->points() is going to return a builder which you can do additional work on. I believe using sum() on that will look at the first row returned which is what you indicated is actually happening.
Likely, what you really want to do is $user->points->sum('amount');
That will get the sum of that column for the entire collection.

Resources