Eloquent: Is chaining wheres (wrapped into functions) possible? - laravel

I have Project and Task models.
I want to do something like:
$project->tasks()->active()->get()
Where $project is a Project object, tasks() is a hasMany() relation, active() should be a function having return $this->whereCompleted(NULL);.
The question is if the whole idea is possible and where should I place the active() function?

You can use Query Scopes : http://laravel.com/docs/eloquent#query-scopes
You just have to put this method in your Task model :
public function scopeActive($query)
{
return $query->whereCompleted(NULL);
}

Related

Laravel nested `hasOne` relationship with `where` clause

I have Shop model which has multiple Content entries:
public function contents(): HasMany
{
return $this->hasMany(Content::class);
}
And I had hasOne relationship with one specific type of content like this:
public function widgetContent(): HasOne
{
return $this->hasOne(Content::class)->where('type', Content::WIDGET);
}
It was working fine but I moved Content's type into a new model called ContentType, and removed the type field from Content model, but instead added another hasOne relationship via content_type_id field.
Now, I'm trying to achieve the same widgetContent relationship but I can't. Here's my code:
public function widgetContent(): HasOne
{
return $this
->hasOne(Content::class)
->whereHas('contentType', fn ($q) => $q->where('type', ContentType::WIDGET));
}
What should I do to achieve this? Also, if this is not the best practice (that's how I feel), what is the best practice?
You could create a closure and use that in stead. So you would still have the relationship like this:
public function content(): HasOne
{
return $this
->hasOne(Content::class);
}
But then you add a closure in your model:
public function getWidgetContent()
{
return $this->content()->whereHas('contentType', function(Builder $q){
$q->where('type', ContentType::WIDGET)
})->get();
}
And then you just call the closure function when you need the results.

How to define multiple belongsTo in laravel

My table has many foreign key for example prefecture_id, gender_id and status_id.
And I made model for those table.
So I want to define multiple belongsTo method like following for get all data with query builder..
But In fact belongsTo can't use like this.
public function foreign(){
return $this->belongsTo([
'App/Prefecture',
'App/Gender',
'App/Status',
]
}
And if the only way is defining multiple method for belongs to.
How do I get all belongstos data in querybuilder.
Please give me advice.
As far as I am aware, there's not a way to get multiple belongsTo from a single method. What you have to do is make one method for each relationship and when you want to load the relationships you can do the following.
Model
public function prefecture()
{
return $this->belongsTo(\App\Prefecture::class);
}
public function gender()
{
return $this->belongsTo(\App\Gender::class);
}
public function status()
{
return $this->belongsTo(\App\Status::class);
}
Query
// This will get your model with all of the belongs to relationships.
$results = Model::query()->with(['prefecture', 'gender', 'status'])->get();

How can I make pagination of a findorfail method in laravel

I have this function in my controller which is the output of many animals and I would like to paginate it. How am I to do that
controller
public function show($id)
{
$farms = User::with(['animals'])->findOrFail($id);
return view('slaughter.show',compact('farms'));
}
Is there any other way of doing that because I have tried to add the paginate method at the end and I am getting an error
paginate() is a method on the Query Builder instance while findOrFail() returns an Eloquent model, and in this case a single instance, as it is for a single user by the given $id.
You can maybe query the animals through their own model, and paginate it, like this:
public function show($id)
{
$farms = Animal::where('user_id', $id)->paginate(10);
return view('slaughter.show',compact('farms'));
}
I would do this to get a paginated collection of animals for the User. Dependency Injection in the show method as well assuming you also require some user data on the slaughter page.
public function show(User $user)
{
$farms = Animals::where('user_id', $user->id)->paginate();
return view('slaughter.show',compact('farms', 'user'));
}
Your route will need updating, something like this...
Route::get('animals/{user}', 'AnimalsController#show')

Getting data from two separate models in laravel

I wanted to get data which is related to an id and I used the find($id) method to get those data, now I wanna get data from two tables which have one to many relationship.
How can I get data which is related to the same id from two table?
I try to this way but it hasn't worked:
public function show($id)
{
$post=Clients::find($id);
return view('pet.shw',['post'=>$post,'pets'=>$post->pets]);
}
Why you dont use with() I have simple solution but maybe not best solution:
Post::with('pets')->where('id',$id)->first();
Maybe below code is work to i dont test it:
Post::with('pets')->find($id);
Of course you should have comments method in your Post Object:
public function pets(){
return $this->hasMany(Pet::class);
}
hope help
You need to first define a relationship between your Client model and Pet model
So, in App\Client, you would have the following relationship:
public function pets()
{
return $this->hasMany(Pet::class);
}
and in App\Pet, you would have the following relationship:
public function client()
{
return $this->belongsTo(Client::class)
}
You should then be able to do this in your Controller:
public function show($id)
{
$post = Client::with('pets')->find($id);
return view('pet.shw')
->withPost($post);
}
and accesses your relationship like this in the pet.shw view:
foreach($post->pets as $pet) {}
For more information read about Eloquent Relationships

Laravel + Eloquent - Passing through custom function first

What I want to do is quite simple I think. In my controller I have the code:
$list = SiteCategory::where('type','=','A')->get();
Which returns a standard eloquent collection object. However, sometimes when I retrieve categories, I want them to be ordered in a specific way first. So can I have some function in my model like:
Class SiteCategory extends Eloquent {
public function mySpecialFunction(){
// retrieve all categories, manipulate them in some way and return.
}
}
How do I then call this function? I don't understand, and the tutorials and questions I've read do not help. For example, in this question on SO, he seems to imply he can call his function something like this:
SiteCategory->mySpecialFunction()
I don't get it?
You can use a scope method inside your Model like this
Class SiteCategory extends Eloquent {
public function scopeMySpecialFunction($query){
// retrieve all categories, manipulate them in some way and return.
}
}
Then you can call this function like normal built in Eloquent functions like
SiteCategory::mySpecialFunction();
If you want to pass any arguments into this function then you can add parameters like this
public function scopeMySpecialFunction($query, $param1, $param2){
// retrieve all categories, manipulate them in some way and return.
}
Notice the first $query parameter, it's the first parameter of a scope method and $query is an instance of Illuminate\Database\Eloquent\Builder, you can use $this inside that function and can chain methods like
SiteCategory::mySpecialFunction()->find(1);
In this case you have to return the $query from your function to chain other methods, like:
public function scopeMySpecialFunction($query, $param1, $param2){
// do something
return $query;
}

Resources