I has two table, post and post_tag. Structure of the two tables is like this :
--Post--
id|Content|user_id
--Post_tag
id|post_id|tag( type = var char / tag name)
I use query like this :
post::whereHas('post_tag', function ($query) use ($tags) {
$query->where('tag', $tags);
});
I want to get all post based tags (ex : tags php and its return all post that have tag php ) but it returned error undefined whereHas method , is any reference should I read? Thanks in advance
Add relationships to your models
//Post
public function tags()
{
return $this->hasMany(Post_tag::class);
}
// Post_tag
public function posts()
{
return $this->belongsTo(Post::class);
}
then you can get all posts based on a tag like
$posts = Post_tag::with('posts')->where('tag','php')->get();
Related
I have three models that are related: Article, ArticleBlock, ArticleBlockImage
ArticleBlock is related with Article and ArticleBlockImage is related with ArticleBlock
Here are the relations
Article
public function article_blocks()
{
return $this->hasMany('App\Models\ArticleBlock');
}
ArticleBlock
public function article()
{
return $this->belongsTo('App\Models\Article');
}
public function article_block_images()
{
return $this->hasMany('App\Models\ArticleBlockImage');
}
ArticleBlockImage
public function article_block()
{
return $this->belongsTo('App\Models\ArticleBlock');
}
Further in the ArticleBlockImage model I have one function with which I need to get the ID of the current Article in the form of type $article->id
I am trying to do something like this, but I get the error
$article = article_block_images()->article_block()->article()->get();
"message": "Call to undefined function App\Models\article_block_images()",
$article = articleBlockImages()->article_block()->article()->get();
when you load your relation this way you load the relation type class, not the database records, relation classes like (HasMany, HasOne ...)
to get article_id you can a function like this:
public function article_id()
{
return $this->article_block->article_id; // without brackets
}
You wrote that ArticleBlock is related to Article and to ArticleBlockImage. Then you have the related Article ID inside the ArticleBlock.
That means if you have the ArticleBlockImage $articleBlockImage then you can write:
$articleId = $articleBlockImage->article_block()->article_id;
I have a model "Post" which has a field "daily" in the database.
$table->integer('daily'); // could be anything
The Model "Post" has a relationship to the model "Comments".
public function comments() {
return $this->hasMany(Comment::class);
}
public function completed() {
return $this->hasMany(Comment::class)->completed();
}
Comments model
public function scopeCompleted($query) {
return $query->....?
}
I want to get all user's posts where it's comments count are equal to the post's 'daily' field. For example: if the post's daily field is '5' and there are 5 comments to this posts, I want to see this post in the returned lists, otherwise don't return it.
I know I can get all of them and do it with loop, but I wanna know if there is any way to do this with eloquent only.
Try this
$user=User::with('posts','posts.comments')
->whereHas('posts.comments',function ($query){
//if any additional filters
},'=',DB::raw('posts.daily'))
->get();
or if not needed additional query then
$user=User::with('posts','posts.comments')
->whereHas('posts.comments',null,'=',DB::raw('posts.daily'))
->get();
Got it working like this
public function scopeCompleted($query) {
return $query->has('comments', '=', DB::raw('posts.comments'));
}
I'm using Laravel 5.8 to build a babysitting site. I have 4 tables with different relationships as below:
please see this image
The relationships are:
Babysitter->hasMany(session)
Sessions->hasOne(Review)
Sessions->hasOne(Kids)
Sessions->hasOne(Babysitter)
Sessions->hasOne(Parent)
I want to achieve 2 things:
First one
I want to show this result when listing all babysitters. I'm showing this information for each babysitter:
plsease see this image
See here what I couldn't achieve
plsease see this image
This is my code
Sitters::where('Status', 'active')->where('Verified', 1)->get();
Second one
Also, I've tried to show kids name with parent review as shown here:
plsease see this image
This is what i'm using
Sessions::select('Reviews.*', 'Sessions.Parent_id')->join('Reviews', 'Reviews.Session_id', '=', 'Sessions.id')->with('owner')->where('Trainer_id', session('user')->Id)->where('Status', '=', 'complete')->with('owner')->orderBy('Sessions.id', 'DESC')->get();
Here is Session.php Model
public function owner(){
return $this->belongsTo('App\Models\Parents', 'Parent_id');
}
As discussed change the relations:
Babysitter->hasMany(sesstion)
Sessions->hasOne(Review)
Sessions->belongsTo(Kids)
Sessions->belongsTo(Babysitter)
Sessions->belongsTo(Parent)
First one
in Babysitter.php declare the following attributes
class Babysitter extends Model
{
public function reviews()
{
$this->hasManyThrough(Review::class, Session::class);
}
public function getAverageReviewAttribute()
{
return $this->reviews()->avg('Rating');
}
}
Then you just need to call it on the model instance.
$babysitter = Babysitter::first();
return $babysitter->average_review;
Second one
Just use the relation
$babysitter = BabySitter::with(['sessions' => public function ($session) {
$session->with(['review','parent','kids']);
})->where('trainer_id', '=', session('user')->Id) //did not understand this condition
->first();
This assumes you have parent, kids and review relation declared on Session::class. (change the names if needed)
After a few days of searching & testing, this is what worked for me:
Inside (Sitters) Model, put this relation
public function sessions()
{
return $this->hasMany(Sessions::class, 'sitter_id')
->withCount('reviews')
->withCount(['reviews as review_avg' => function($query){
$query->select(DB::raw('AVG(Rating)'));
}]);
}
Also, inside (Sessions) Model, put this relation
public function reviews()
{
return $this->hasOne(Reviews::class, 'Session_id');
}
Now you query like this
return $sitters = Sitters::with('sessions')->get();
I hope this can help someone :)
I am building a small application on Laravel 5.6 where I am having two models Project and Status. In this I am having a relation as such:
In Project Model I am having:
public function statusUpdate()
{
return $this->hasMany('App\Status','project_id','id');
}
and to retrieve latest status I have:
public function latestStatus()
{
return $this->hasOne('App\Status','project_id','id')->latest();
}
In status I have columns: date, status, sub_status, comments.
I want to retrieve Status where I am having latest status by date mentioned in the column
I tried doing this in my model:
public function latestStatus()
{
return $this->hasOne('App\Status','project_id','id')->latest('date');
}
But this thing is not working out, help me out in this. Thanks
edit
I am using this relation in eager loading something like this:
Project::when( $request->name , function( $q) use( $request ) {
$q->where('name', 'like', '%' . $request->name .'%');
})->with('latestStatus')
->orderBy($request->sort_by_col, $request->order_by)
->paginate(30);
You can use orderBy in the relationship.
public function latestStatus()
{
return $this->hasOne('App\Status','project_id','id')->orderBy('date', 'desc');
}
Try it out.
You got your models wrong. This is what should be in the Project model
public function statuses() //plural because a project has many statuses
{
return $this->hasMany('App\Status','id','project_id');
}
If you want the latest status, call this in your controller:
Project::where('name', 'like', "%{$request->name}%")->with('statuses', function($q) {
return $q->orderBy('date', $request->order_by);
})->paginate(30);
If you want the latest project where the status has changed, first the Status model:
public function project()
{
return $this->hasOne('App\Project','project_id','id');
}
And in your controller:
$project = Status::latest()->first()->project;
Add first to the end of the query.
public function latestStatus()
{
return $this->hasOne('App\Status','project_id','id')->latest()->first();
}
This is how it works
The statusUpdate method builds the query and does the setup for has many relationship
The latest method adds the order by clause
The first methods adds the limit 1 clause, then executes the query and returns the first result
Im making a search functionality where users can type in a name. This is the query im doing:
public function api(Request $request)
{
$query = request()->get('query');
$results = Listing::searchAndCache($query);
return $results;
}
Which hits this:
public static function searchAndCache($query)
{
return self::where('name','like','%'.$query.'%')->where('live',true)->paginate(15);
}
I also need to search 'location' along with this query, the problem is its in a diffrent table. The models name is Location. My question is how would I attach the model Location to this query?
So ideally, I would want to do this for the query:
public static function searchAndCache($query)
{
return self::where('name','like','%'.$query.'%')->where('region','like','%'.$query.'%')->where('live',true)->paginate(15);
}
For search you can use searchable trait. so you can do this :
Listing::where('live',true)->search($query)->paginate(15);
if there is a relation between Listing And Location, you can use Laravel realations to do something like this
Listing::where('live',true)
->search($query)
->location
->search($query2)
->paginate(15);