How to get article translations in comment relationship? - laravel

I have relationship between article and translations, but how can i get that in comment?
$comments = ArticleComments::orderBy('created_at','desc')->with('user')->with('article')->with('translations')->paginate(10);
I tried this also
$comments = ArticleComments::orderBy('created_at','desc')->with('user')->with('article')->with('translations')->whereHas('translations',function($query) use($default_language_id){
$query->where('language_id','=',$default_language_id);
})->paginate(10);
Any suggestion? I get articles but not theirs translations...
Models:
Comment:
public function article()
{
return $this->belongsTo('App\Models\Articles','article_id');
}
Article:
public function translations()
{
return $this->hasMany('App\Models\ArticleTranslations', 'article_id');
}

you should use this :
$comments = ArticleComments::orderBy('created_at','desc')->with('user')->with('article')->with('article.translations')->paginate(10);
for more information :
https://laravel.com/docs/5.3/eloquent-relationships
in Nested Eager Loading section
and if you want add where to query :
$comments = ArticleComments::orderBy('created_at','desc')->with('user')->with('article')->with('article.translations',function($query)
{
$query->where('ANY CONDITION');
})->paginate(10);

It should be like this
$comments = ArticleComments::orderBy('created_at','desc')->with('user')->with('article',function ($query) {
$query->with('translations')
})->paginate(10);

Related

retrieving related field in controller index function gives error but ok in show function

I define the relation in Company table (where I added the plural):
protected $table = 'companies';
public function country() {
return $this->belongsTo(Country::class, "country_id")->withDefault(['country' => 'unknown']);
}
I also did the same in the Country model.
When I use the following code in the controller show function it works:
public function show (Company $company) {
$company->country = $company->country()->pluck('country');
But if I use the same code in the index function in a loop, I get an error "Call to undefined method stdClass::country()":
public function index (Company $company) {
if (request('tag')) {
$companies = Tag::where('name',request('tag'))->firstOrFail()->companies;
$companies->page_title = "Businesses matching tag '".request('tag')."'";
} else {
$companies = DB::table('companies')
->where([['is_active', '=', '1']])
->orderBy('company')
->get();
}
foreach($companies as $key => $thisCompany) {
...
$thisCompany->country = $company->country()->pluck('country');
}
I guess it is due to the fact that $company is created in the loop and not passed through the function like in show(Company $company)... but I could not find how to solve this issue... so help will be appreciated.
I have added the model in the argument of the function and change the name of the $company variable in the loop by $thisCompany to avoid confusion with the $company model.
No error but the field $country->country does not contain the name of the country but "Illuminate\Support\Collection {#443 …1}"
Why is it so complicated? Please help...
Paul, sorry, I think I didn't explain myself well in the comments.
What I meant by "What about if you change DB::table('companies') by Company?", is to stop using DB Query Builder to use the Eloquent Company model.
Specifically in this segment of code:
$companies = DB::table('companies')
->where([['is_active', '=', '1']])
->orderBy('company')
->get();
So, it could be:
$companies = Company::where([['is_active', '=', '1']])
->orderBy('company')
->get();
The explanation is that in the first way (with DB Query Builder), the query will return a collection of generic objects (the PHP stdClass object) that do not know anything about the Company and its relationships.
On the other hand, if you use the Eloquent model Company, it will return a collection of Company objects, which do know about relationships, and specifically the relationship that you have defined as country.
Then, when you loop over the collection, you will be able to access the country relation of each Company object:
foreach($companies as $key => $company) {
//...
$company->country = $company->country()->pluck('country');
}
Finally, your code could looks like:
public function index () {
if (request('tag')) {
$companies = Tag::where('name',request('tag'))->firstOrFail()->companies;
$companies->page_title = "Businesses matching tag '".request('tag')."'";
} else {
$companies = Company::where([['is_active', '=', '1']])
->orderBy('company')
->get();
}
foreach($companies as $key => $company) {
//...
$company->country = $company->country()->pluck('country');
}
//...
}

How to paginate a relationship result in laravel

How do you paginate the following line
$posts = Category::where('name', request('category'))->firstOrFail()->posts;
in the function below
public function index()
{
$categories = category::all();
if (request('category')) {
$posts = Category::where('name', request('category'))->firstOrFail()->posts;
} else {
$posts = post::where('status', 1)->orderBy('created_at', 'DESC')->paginate(5);
}
return view('user.blog', compact('posts', 'categories'));
}
You have to use the actual relationship method to get access to the query builder:
$posts = Category::where('name', request('category'))
->firstOrFail()
->posts()
->paginate(5);
See the Eloquent docs on Relationship Methods Vs. Dynamic Properties for reference.

Eloquent `with()` with filtering based on relation

I have this tables.
And this model relations, this relations works fine.
class Item extends Model
{
public function translations()
{
return $this->hasMany(ItemTranslations::class);
}
}
class ItemTranslation extends Model
{
public function language()
{
return $this->belongsTo(Language::class);
}
}
I need to return a list of items with the translations, but only the translations related to a specific language.
I can't have this query working, im getting all translations of each item, not only the one filtered with this query. The language related to the translation is not needed on the result.
$query = Item::query();
$query->with('translations')->when('language',function($query) use ($ISOlanguage) {
return $query->where('languages.ISO_code', '=', $ISOlanguage);
});
return $query->paginate();
Any idea who i can have this working? Thanks!
So what you want to do is constraining eager loading
Item::with(["translations" => function ($query) use ($ISOlanguage) {
$query->where('language.ISO_code', $ISOlanguage);
}])->get();
https://laravel.com/docs/5.8/eloquent-relationships#constraining-eager-loads
I finally have it working
Item::with(['translations' => function($query) use ($ISOlanguage) {
$query->whereHas('language', function($query) use ($ISOlanguage) {
$query->where('ISO_code', '=', $ISOlanguage);
});
}])->get();
Thanks #julian-s for your help!

Laravel : Get all models that their last relationship have some condition

I have two models Post and Comment, i'd like to get all posts that their last comment is active:
// Model Post
public function comments()
{
return $this->hasMany('comments');
}
//Model Comment
public function post()
{
return $this->belongsTo('post');
}
i tried this solution :
public function lastComment()
{
return $this->hasOne('comment')->latest()
}
and in my controller :
$postsWithLastActiveComment = Post::whereHas('lastComment', function($q){
$q->where('active',1);
})->all();
but in this solution if the last comment is not active Previous comment will be taken
I am not sure if there's another simpler way of doing this, but maybe you can try it with a sub-query?
$lastComment = Comment::select('active')
->whereColumn('post_id', 'posts.id')
->latest()
->limit(1)
->getQuery();
$posts = Post::select('posts.*')
->selectSub($lastComment, 'last_comment_is_active')
->having('last_comment_is_active', 1)
->get();
->latest() only orders the posts by created_at so to get only the latest comment you need ->latest()->first()
I think the code below should work !
public function comments()
{
return $this->hasMany('comments');
}
public function lastComment()
{
return $this->comments()->latest()->first();
}
Shouldn't this
$postsWithLastActiveComment = Post::whereHas('lastComment', function($q){
$q->where('active',1);
})->all();
be
$postsWithLastActiveComment = Post::whereHas('lastComment', function($q){
$q->where('active',1);
})->get();
According to your question, the Post model has many Comments. And you want to get the comment from the post where active is one and must be the lastest id.
Get the last comment like the following
public function lastComment()
{
return $this->hasOne('comment')->latest()->take(1);
}
Get all posts which had the lastComment like the following
$latestCommentPosts = Post::whereHas('lastComment')->get()
And filter the latestCommentPosts like the following
$latestCommentPosts->where('active', 1)->get()
Or, you can archive by one query like the following as well.
Post::whereHas('comments', function($q) {
$q->where('active', 1);
})->get()
Like that, you got all the latest comment with active is 1.

Laravel Eloquent / keyBy doesn't work with related entity

Code:
public function getPosts(){
$posts = Post::with('meta','taxonomies.terms.termMeta')
->where('post_type','service')
->orderBy('post_name')
->get()
->keyBy('ID')
->toArray();
return $posts;
}
Question :
KeyBy() works when you want to change the entity(ex: Post) key but how to change the related entity key ex: I Want to key post related meta with meta_key.
screenshot
You may need to transform() each post and call the keyBy() method.
public function getPosts(){
$posts = Post::with('meta','taxonomies.terms.termMeta')
->where('post_type','service')
->orderBy('post_name')
->get()
->transform(function ($post) {
$meta = $post->meta;
$post->meta = $meta->keyBy('meta_key');
return $post;
})
->keyBy('ID')
->toArray();
return $posts;
}
Code 1 : doesn't work ,I have noticed that you can alter the $post but not the related entities (ex:meta) :
->transform(function ($post) {
$meta = $post->meta;
$post->meta = $meta->keyBy('meta_key');
return $post;
})
Code 2 : Works but it return only the meta array without the post information
->transform(function ($post) {
$meta = $post->meta;
$post->meta = $meta->keyBy('meta_key');
return $post->meta;
})

Resources