\App\Post :
function PostMeta(){
return $this->hasMany('App\PostMeta');
}
And my Query : ( pluck is not working) -
I need to use less database queries
$query = \App\Post
::with(array('PostMeta'=>function($query){
$query->pluck('key','value');
}));
$query->get();
I need to get title_en , But I cant use pluck here!
New Update
solved:
function get_PostMeta(){
// print_r($this->relations['PostMeta']);
return $this->relations['PostMeta'];
}
$query = \App\Post::with('PostMeta')->get();
foreach ($query as $key => $post){
$post->meta = $post->get_PostMeta()->pluck('value', 'key');
}
You can't do this while eager loading the data, but you can use collection method with the same name pluck() in the view when accessing the relation data:
{{ $post->postMeta->pluck('value', 'key') }}
In this case, you'll avoid N+1 problem and get data in the format you want.
Update
Since you want to prepare data for Vue, here's a small example of how you could iterate over the collection:
foreach ($posts as $post) {
$post->meta = $post->postMeta->pluck('value', 'key');
unset($post->postMeta);
}
Related
I'm trying to loop through the items using eloquent in laravel but I'm getting 0. Please see my code below.
Model
Class Store{
public function products(){
return $this->hasMany('App\Product');
}
}
Controller
$products_count = 0;
foreach($store->products() as $product)
{
if($product->status == 1)
{
$products_count++;
}
}
dd($products_count);
Note: I have data in my database.
You can also use withCount method something like that
Controller
$stores = Store::withCount('products')->get();
or
$store = Store::where('id', 1)->withCount('products')->first();
WithCount on the particular status
$stores = Store::withCount(['products' => function ($query) {
$query->where('status', 1);
}
])
->get();
ref: withcount on relationship
That's because $store->products() returns an eloquent collection which doesn't contain the data from the database yet. You need to do $store->products instead.
If you need to get the count from the database then use
$store->products()->where('status', 1)->count()
With the function-annotation (i.e. products()) you are retrieving the \Illuminate\Database\Eloquent\Builder-instance, not the actual Eloquent-collection.
Instead, you would have to use $store->products – then you will get retrieve the related collection.
In Laravel $store->products() makes you access the QueryBuilder instance, instead there is the Laravel way of doing $store->products, which loads the QueryBuilder and retrieves the collection automatically and down the line is easy to optimise.
This is my table.i need all post in descending order.I want advertised posts in top.
result example
Code
$data=Post::get();
Relationship in model
public function isAdvertised()
{
return $this->hasOne('App\models\PostAdvertise', 'post_id');
}
You can use leftJoin
$data = Post::leftJoin('post_advertise', 'post.id', '=', 'post_advertise.post_id')
->orderBy('post_advertise.created_at')
->select('post.id', 'post.title', 'post.description')
->get();
try
$posts = Post::with('isAdvertised')->all();
$sorted_posts = $posts->sortBy(function ($post, $key) {
return (is_null($post->isAdvertised) ? 1 : 0);
});
This will order the collection.
$posts = Post::orderBy('created_at','desc')->get();
You can then add this to your view:
#foreach($posts as $post)
$post->post_advertise->title
#endforeach
If it does not work I would advise you to post exactly what you did, like your migration, model(relationship) and controller.
I am working on an API endpoint that returns a list of users that have all of the given services ID's.
In my case:
Users can have many services
Tables: 'users', 'services', 'service_user'
I am passing an array via Vue JS to my end point for example:
/endpoint/32,35,38
My query is currently:
$servicesArray = explode(',', $services);
$users = User::whereHas('services', function ($query) use ($servicesArray) {
foreach ($servicesArray as $key => $value) {
$query->where('id', $value);
}
})
->get();
The issue is that it seems to return now results, even if a user does have the correct services. My relationship is fine, and if I only pass one service to the endpoint it correctly returns a user that has that service assigned. I used whereIn before, but I need to only show users that have ALL of the services specified in the endpoint array.
Any obvious reason why what I have is not working as expected?
I would try something like this:
$q = User::query();
foreach ($servicesArray as $key => $value) {
$q->whereHas('services', function ($query) use ($value) {
$query->where('id', $value);
});
}
$users = $q->get();
You can also use laravel hasmany realationship function for getting multiple records from other table.
Example:
---In your Controller use query like.
$users = User::with('services')->where('id', $value)->get();
---And in your model's class use function services like this.
function services(){
return $this->hasMany('App\Service','user_id','id');
}
I have a problem because i make big relation through using join in laravel and I don't know how to use data in this query.
My model:
public function getrelationquery(){
return $this->hasMany('App\Modtwo',"modtwoforeign","id")
->join('Pmodel',"Pmodel.id",'=','Modtwo.pp')
->join("Cpmodel","Cpmodel.pr","=","Modtwo.id")
->join("Ccmodel","Ccmodel.id","=","Cpmodel.cc");
}
My controller:
$q = Mymodel::find($id)->with(array('getrelationquery'=>function($query) use ($id_other){
$query->where('secvar',$id_other);//id_other is the secound variable
}))->get();
$pd = $q;
print_r($pd);
return view('view/displaydata', compact('pd'));
When I use print_r I see all the data but I don't know how display it on view. I need to display data from Ccmodel and Pmodel.
$pd is collection of your object, so you can use foreach to extract your object
#foreach($pd as $data)
{{ $data->column_name }}
#endforeach
Is it possible to use an orderBy for an object's related models? That is, let's say I have a Blog Post model with a hasMany("Comments"); I can fetch a collection with
$posts = BlogPost::all();
And then run through each post, and display the comment's last edited date for each one
foreach($posts as $post)
{
foreach($post->comments as $comment)
{
echo $comment->edited_date,"\n";
}
}
Is there a way for me to set the order the comments are returned in?
This is the correct way:
BlogPost::with(['comments' => function ($q) {
$q->orderBy('whatever');
}])->get();
The returned object from the relationship is an Eloquent instance that supports the functions of the query builder, so you can call query builder methods on it.
foreach ($posts as $post) {
foreach ($post->comments()->orderBy('edited_date')->get() as $comment) {
echo $comment->edited_date,"\n";
}
}
Also, keep in mind when you foreach() all posts like this, that Laravel has to run a query to select the comments for the posts in each iteration, so eager loading the comments like you see in Jarek Tkaczyk's answer is recommended.
You can also create an independent function for the ordered comments like you see in this question.
public function comments() {
return $this->hasMany('Comment')->orderBy('comments.edited_date');
}
And then you can loop them like you did in your original code.
Create a JOIN and select just the column you want to order on:
$post = BlogPost::join('comments', function($j) {
$j->on('posts.id', '=', 'comments.post_id');
$j->select('comment_date_or_other_col');
})
->orderBy('comment_date_or_other_col', 'DESC')->first();
Yes:
$posts = BlogPost::with('comments')
->orderBy('comments_table_name.column_name')
->get();
And you can also set that in your relation:
public comments()
{
$this->hasMany("Comments")->orderBy('comments.column_name');
}