Retrieving data with Array values - laravel - php

My task is to display all contacts for selected groups. When i select two gorups like facebook and instagram, i have to display all contacts belonging to both group.
When i select multiple groups like below and do return $explode_groups, i get the id's of both groups like 1,2.
But my issue is, when i am displaying the contact as return $selected_contacts i get only contacts for group 1.
Why is this happening?
Group
public function customers()
{
return $this->belongsToMany('App\Customer','customer_group','group_id','customer_id')
->withTimestamps();
}
Customer
public function groups()
{
return $this->belongsToMany('App\Group','customer_group','customer_id','group_id')
->withTimestamps();
}
Controller
$get_selected_groups = $request->get('group');
$explode_groups = implode(', ', $get_selected_groups);
$selected_groups = Group::where('id',$explode_groups)->first();
$selected_contacts = $selected_groups->customers()->get();
response
{"id":2,"title":"test","no_of_contacts":0,"user_id":1,"created_at":"2018-04-15 23:55:30","updated_at":"2018-04-15 23:55:30","customers":[{"id":1,"name":"Benson Jones Thomson","phone":"0247878234","group_id":null,"user_id":1,"created_at":"2018-04-16 00:14:20","updated_at":"2018-04-16 05:31:05","pivot":{"group_id":2,"customer_id":1,"created_at":"2018-04-16 05:33:08","updated_at":"2018-04-16 05:33:08"}},{"id":2,"name":"Lawrence Pitcher","phone":"0244371112","group_id":null,"user_id":1,"created_at":"2018-04-16 07:59:15","updated_at":"2018-04-16 07:59:15","pivot":{"group_id":2,"customer_id":2,"created_at":"2018-04-16 07:59:15","updated_at":"2018-04-16 07:59:15"}}]}

You should be using whereIn() to select multiple ids from the given array and to load the relation of each model use with() method.
Like:
$get_selected_groups = $request->get('group');
return Group::whereIn('id', $get_selected_groups)->with('customers')->get();

Try this
$selected_contacts = Customer::whereHas('groups', function($q) use ($explode_groups){
$q->whereIn('id', $explode_groups);
})->get();

You should try this
$selected_groups = Group::whereIn('id',$get_selected_groups)->get();
$selected_contacts = array();
foreach($selected_groups as $selected_group){
$selected_contacts[] = $selected_group->customers()->get();
}

Related

How Laravel generates SQL queries

I have created a one-to-many relationship. Here are the model classes.
class Photo extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
}
class User extends Authenticatable
{
public function photos(){
return $this->hasMany('App\Photo');
}
}
Then I try to retrieve photos:
$photos = User::find(1)->photos->where('photo', 'ut.jpg')->first();
Here is a query log I got. I do not see the photo='ut.jpg'. So how laravel generate SQL?
select * from `photos` where `photos`.`user_id` = 1 and `photos`.`user_id` is not null
Try this
$photos = User::find(1)->photos()->where('photo', 'ut.jpg')->first();
must be use ->photos() instead of ->photos.
For see sql query use
$sql = User::find(1)->photos()->where('photo', 'ut.jpg')->toSql();
You queried all photos by using this:
$photos = User::find(1)->photos->where('photo', 'ut.jpg')->first();
By using User::find(1)->photos you receive a Laravel Collection. Those collections have a where method as well. So basically, you are running SQL to get all photos of User 1 and then you just filter that collection to only show you the item with photo ut.jpg.
Instead, you can use brackets to get the relationship, and then query that.
Your query then becomes
$photos = User::find(1)->photos()->where('photo', 'ut.jpg')->first();
Instead of naming it $photos you should name it $photo, as you are querying with first - which will result only in one object (or null).
Can you please try this:
$photo = 'ut.jpg';
$photos = User::find(1)->whereHas('photos', function ($query) use($photo){
return $query->where('photo', $photo);
})->first();
your query $photos = User::find(1)->photos->where('photo', 'ut.jpg')->first(); is incorrect, laravel didnt see the where condition if you do this
User::whereHas('photos', function($q) {
$q->where('photo', 'ut.jpg');
})->where('id',1)->first();
thats the correct query to get the user photo
You could:
Run A Select Query
$photos = DB::select('select * from photos where id = ?', [1]);
All this is well-documented in :
--https://laravel.com/docs/5.0/database

Fetching has many relationship data Laravel and using avg function

I am using Laravel 5 with vue js. Basically i am fetching data using axios and trying to display on the webpage using vue js v-for directive.
i have tables in database like this:
ratings Table
id review_id rating
Then i have a
reviews table
id review
They have one to many relationship between. so here in my Review Model i have method
public function ratings()
{
return $this->hasMany('App\Rating')
->selectRaw('review_id,AVG(rating) AS average_rating')
->groupBy('review_id');
}
so here i want to fetch list of reviews with their average ratings. so in my controller i am doing this:
public function getAllReviews(Request $request)
{
$reviews = Review::with('ratings')->get();
return $reviews;
}
So i am getting result but the problem is every review doesnt have ratings record so it is returning null? maybe...
when i try to render in vue template it throws an error undefined because in our collection some reviews do not have ratings.
Now my question is: Can i do something like if there is no record in the ratings for a particular review is it possible to add an array with value 0?? so in my frontend it wont see as undefined.
I hope i am successful to explain i am trying.
Thank you.
You may do it this way:
public function getAllReviews(Request $request)
{
$reviews = Review::selectRaw('*, IFNULL((SELECT AVG(rating) FROM ratings where ratings.review_id = reviews.id), 0) as avg_rating')->get();
return $reviews;
}
I would suggest using the basic relationship and a modified withCount():
public function ratings() {
return $this->hasMany('App\Rating');
}
$reviews = Review::withCount(['ratings as average_rating' => function($query) {
$query->select(DB::raw('coalesce(avg(rating),0)'));
}])->get();
public function showProduct($id)
{
$data = Product::where('category_id',$id)
->selectRaw('*, IFNULL((SELECT AVG(value) FROM ratings where ratings.product_id = products.id), 0) as avg_rating')
->get();
return view('ecommerce.web.productsOfcategory',compact('data'));
}
$avgQuery = "IFNULL((SELECT AVG(ratings.rating) FROM ratings WHERE ratings.review_id = reviews.id),'No Ratings') as avg_rating";
$reviews = Review::query()->selectRaw("reviews.*, $avgQuery")->get();
//SQL Query
$sqlQuery = "select reviews.*, IFNULL((SELECT AVG(ratings.rating) FROM ratings where ratings.review_id= ratings.id), 'No ratings') as avg_rating FROM reviews";

How to join table with req->id

public function getTourDetail(Request $req)
{
//Get link detail
$tour = Tour::where('id',$req->id)->first();
//I want to take location.city of the location table
$detail = Tour::join('location','tour.id_location','=','location.id')
->whereColumn([
['tour.id_location','=','location.id']
])
->get(array(
'tour.id as id_tour',
'location.image',
'tour.name',
'tour.id_location',
'location.city'
));
return view('page.tour-detail',compact('tour','detail'));
}
I would like to be able to combine two query statements to get information from the location table ($ detail) like the id of the link request ($ tour).
Since you use models, you can use Eloquent relationships to load related data. First, define a relationship in the Tour model:
public function location()
{
return $this->belongsTo(Location::class, 'id_location')
}
Then load Tour and get related location:
$tour = Tour::find($req->id);
$relatedLocation = $tour->location;
First thing, if you are using model then using eloquent relationship will be a better idea to deal with the situation like yours. But if you want to join your table then this will be the way:
public function getTourDetail($id)
{
$tour = Tour::where('id',$id)->first();
//I want to take location.city of the location table
$detail = DB::table('location')
->join('tour','tour.id_location','=','location.id')
->select(
'tour.id as id_tour',
'location.image',
'tour.name',
'tour.id_location',
'location.city'
)->get();
return view('page.tour-detail',compact('tour','detail'));
}
Note: if you are getting id from submitted form then replace first portion of the code with:-
public function getTourDetail(Request $request)
{
$tour = Tour::where('id',$request->id)->first();

Exclude items from a collection in Laravel

In my Laravel app, I have the concept of users, friends, and groups. A user can create and sort friends into groups.
A user can have many friends:
function friendsOfMine()
{
return $this->belongsToMany('App\User', 'helpers', 'user_id', 'helper_id')
->wherePivot('accepted', '=', 1);
}
A group can have many users:
public function groupMembers()
{
return $this->belongstoMany('App\User')->withTimestamps();
}
In the UI for adding friends to a group, I want to show the full list of a user's friends, but exclude those friends that have already been added to the group. My Groups Controller function looks like this, though I'm positive I'm off-base.
public function add($id)
{
$group = Group::findOrFail($id);
$helpers = $group->groupMembers;
$id = $helpers->lists('id');
$invitees = $this->user
->friendsOfMine()
->where('helper_id', '!=', $id)
->Paginate(5);
return view('groups.add', compact('group','helpers','invitees'));
}
Ideally, what I'd love is some way to write:
$helper = $group->friendsOfMine->not->groupMembers->Paginate(5);
Is there anyway to filter data using functions from two different models?
With your approach you would have to use whereNotIn() since you have an array of ids:
$id = $helpers->lists('id');
$invitees = $this->user
->friendsOfMine()
->whereNotIn('helper_id', $id)
->Paginate(5);
However you probably could something like this as well (assuming the relation group)
$invitees = $this->user
->friendsOfMine()
->whereDoesntHave('group', function($q) use ($id){
$q->where('group_id', $id); // Note that id is the group id (not the array of ids from the helper)
})
->Paginate(5);
For a nicer syntax (like in your example) you should look into Query Scopes

Laravel 4 whereIn and many to many

I have a tag system, where you can add tags to photos and users.
I have a function where the users are able to add their favorite tags, and select images based on those tags
But my problem i am a really big beginner with php and laravel and i do not know how to pass the values to the whereIn function
Model
public function tag()
{
return $this->belongsToMany('Tag', 'users_tag');
}
Controller
// get the logged in user
$user = $this->user->find(Auth::user()->id);
// get tags relation
$userTags = $user->tag->toArray();
// select photos based on user tags
$photos = Photo::whereHas('tag', function($q) use ($userTags)
{
$q->whereIn('id', $userTags);
})->paginate(13);
$trendyTags = $this->tag->trendyTags();
$this->layout->title = trans('tag.favorite');
$this->layout->content = View::make('main::favoritetags')
->with('user', $user)
->with('photos', $photos)
->with('trendyTags', $trendyTags);
When i pass i get an error
preg_replace(): Parameter mismatch, pattern is a string while replacement is an array
than i tried to use array_flatten() to clean my array
// get the logged in user
$user = $this->user->find(Auth::user()->id);
// get tags relation
$userTags =array_flatten($user->tag->toArray());
// select photos based on user tags
$photos = Photo::whereHas('tag', function($q) use ($userTags)
{
$q->whereIn('id', $userTags);
})->paginate(13);
$trendyTags = $this->tag->trendyTags();
$this->layout->title = trans('tag.favorite');
$this->layout->content = View::make('main::favoritetags')
->with('user', $user)
->with('photos', $photos)
->with('trendyTags', $trendyTags);
This way it works but not returning the correct tags.
Could please someone could lend me a hand on this?
Sure thing and I'll make a couple recommendations.
To get the user model, you simply have to use $user = Auth::user().
To use whereIn(), it's expecting a 1 dimensional array of user id's. The toArray() function is going to return an array of associative arrays containing all the users and their properties, so it's not going to work quite right. To get what you need, you should use lists('id').
And one last thing that has really helped me is when you are setting up a relation that's going to return a collection of objects (hasMany, belongsToMany()), make the relation name plurual, so in this case you would modify your tag() function to tags().
So with all that in mind, this should work for you.
// get the logged in user
$user = Auth::user();
// get tags relation
$userTags = $user->tags()->lists('id');
// select photos based on user tags
$photos = Photo::whereHas('tags', function($q) use ($userTags)
{
$q->whereIn('id', $userTags);
})->paginate(13);
$trendyTags = $this->tags->trendyTags();
$this->layout->title = trans('tag.favorite');
$this->layout->content = View::make('main::favoritetags')
->with('user', $user)
->with('photos', $photos)
->with('trendyTags', $trendyTags);
And I'd suggest to modify your relation to... though not hugely important.
public function tags()
{
return $this->belongsToMany('Tag', 'users_tag');
}

Categories