Work with foreach in Laravel: delete same values - php

I found way to delete duplicate values in the result but it doesn't work correctly. How to fix it?
I have next code:
public function getListPositionByApplication($app_id){
// $app_id = \Request::input('app_id');
$list = SparePartApplicationPositionProvider::where('app_id',$app_id)->with(['provider','application_position'])->orderBy('apos_id')
->get();
$aa=0;
foreach ($list as $value) {
if($value->apos_id==$aa){
$value->application_position->name_detail='----';
}
$aa = $value->apos_id;
Log::info($value->apos_id);
}
return $list;
}
Log::info give next information: 26,26,26,26,26,26,27,27,27,27,27,27,28
but $value->application_position->name_detail have '----' in all cases with the exception of last value

#Hussein is right, group by the common column and don't do a foreach. Let the Eloquent DB do the heavy lifting. Notice the callback where you include your second table.
$list = SparePartApplicationPositionProvider::where('app_id',$app_id)
->with(['provider','application_position' => function ($query){
$query->groupBy('name_detail');
}])
->orderBy('apos_id')
->get();

You can try collection unique() method.
https://laravel.com/docs/master/collections#method-unique

Related

Access to multilevel relationships in laravel

can someone help me on getting data from multi level relationships in laravel?
I want to do something like
BagageAnnouncement->Announcement->user->profile->"name of the field"
$data = $request->text;
$filter = BagageAnnouncement::whereHas('announcement',function ($query) {
})->whereHas('user', function ($query) {
})->whereHas('profile',function($query){
$query->where('level',$data)
})->get();
Thank you guys for you answers I finally figure out a solution
$data = $request->text;
$filter = BagageAnnouncement::whereHas(
'announcement.user.profile',
function ($q2) use ($data) {
$q2->where('level',$data);
}
)->get();
Not sure what you want as the result, but if you want a single result, you can do like this:
$bagage = BagageAnnouncement::where(specify_your_condition)->first();
$filter = $bagage->user->profile->name_of_the_field;
If you want an array of results, change the first() to get() and make use of foreach
Of course, you will need to set up the relationships in your models first.

How to delete multiple row from DB table by laravel?

I want to delete all comments from comments table.I did that by doing this but this is not the laravel way. Anyone answer the correct steps please .
$comments = Comment::where('post_id',$id)->get();
if(count($comments)>1)
{
$comment_id= [];
foreach ($comments as $i)
{
$comment_id[] = $i->id;
}
for($i=0;$i<count($comments);$i++)
{
Comment::find($comment_id[$i])->delete();
}
}
elseif (count($comments)==1)
{
$comments->delete();
}
Since each Eloquent model serves as a query builder, try this, all in one line:
Comment::where('post_id',$id)->delete();
Tested in tinker, works as expected, returns count of deleted rows.
Documentation: https://laravel.com/docs/5.3/queries#deletes
You can try the following approach:
public function deleteAll(Request $request)
{
$ids = $request->ids;
Comment::whereIn('id',explode(",",$ids))->delete();
}
DB::table('users')->whereIn('id', $ids_to_delete)->delete();
or
$org-products()->whereIn('id', $ids)->delete();
Collect only ids from your command like below and destroy by model.
$yourRaws = YourModel::where('name', 'Enver')->get();
...
YourModel::destroy($yourRaws->pluck('id')->toArray());
Enjoy Your Coding !

Laravel - get the only item properties from collection without the foreach loop

I wonder is there a way to get an only item properties without a foreach loop. Since I have a query where in most of the cases there will be only one item in collection, and I need to change the status in the pivot table for only that case, I wonder is there some elegant way of doing this without the foreach loop. This is the case I am talking about:
$opponents = $quiz
->players()
->where('id', '!=', $player->id)
->get();
if ($opponents->count() < 2) {
$quiz->status = 'finished';
$quiz->save();
foreach ($opponents as $opponent) {
$quiz->players()->updateExistingPivot($opponent->id, ['status' => 'dropped']);
}
}
You can use the function first() like this:
$quiz->players()->updateExistingPivot($opponents->first()->id, ['status' => 'dropped']);

How can I use array_push to add a key value pair in a foreach loop through database query results in PHP/Laravel to flag each row returned?

I have a function which retrieves all comments for a post when a show posts button is clicked. The comments are then displayed using Javascript and what I am looking to do is to add a key value pair to the array which will tell my javascript if the comment owner is the logged in user or not, thus allowing me to then add edit and delete buttons to that user's posts only.
This may or may not be the best way to make this comparison but it's a way I cooked up in my infinite inexperience so I can use javascript to show the comments and allow editing/deletion of the comment. I know I could add a column my_posts to the DB table and keep this empty, then use array_push to add the appropriate value to this field but is the way I've tried here possible?
my function is here:
public function postGetComments(Request $request) {
$post = $request['postid'];
$comments = DB::table('comments')
->join('users', 'users.id', '=', 'comments.user_id')
->select('comments.*', 'users.username')
->where('post_id', '=', $post)
->orderby('created_at', 'desc')
->get()
;
foreach ($comments->get() as $comment) {
$user = Auth::user();
if ($user->id == $comment->user_id) {
$comment['my_post'] = 'true';
} else {
$comment['my_post'] = 'false';
}
}
return response()->json(['commentsForPost' => $comments]);
}
I am getting an error as there is a problem with my foreach loop at the end. Without this loop the query retrieves and displays all comments as designed. I'm very new to Laravel (using 5.2) and I'm wondering what I've done wrong while trying to push the key my_post, compare the comments.user_id to the user.id and add the value true/false as appropriate to the array? Thanks!
You have already run the get() method on your $comments query. Change your foreach loop to this
foreach ($comments as $comment) {
$user = Auth::user();
if ($user->id == $comment->user_id) {
$comment['my_post'] = 'true';
} else {
$comment['my_post'] = 'false';
}
}

Laravel whereIn with a where clause on each array item

Say I have a user object (which belongsToMany groups) and I'm doing a whereIn with an array of their respected ids like so:
whereIn('user_id', $group->users->modelKeys())
I need to, however, set a condition where I only pull data from each array item based on a condition of the group_user pivot table, "created_at" (which is basically a timestamp of when that user was added to the group).
So I need something like this:
whereIn('user_id', $group->users->modelKeys())->whereRaw('visits.created_at > group_user.created_at')
That doesn't work though because it's not doing the whereRaw for each array item but it's doing it once for the query as a whole. I might need to do something like a nested whereIn but not sure if that'll solve it either. Thoughts?
My full query as it is now:
$ids = $group->users->modelKeys();
return DB::table('visits')->whereIn('user_id', function($query) use ($ids) {
$query->select('user_id')->from('group_user')->whereIn('group_user.user_id', $ids)->whereRaw('visits.created_at > group_user.created_at');
})->sum("views");
Ok got it to work using nested loops instead:
$visits = DB::table('visits')->whereIn('user_id', $group->users->modelKeys())->get();
$sum = 0;
foreach($group->users as $user) {
foreach($visits as $visit) {
if($visit->user_id == $user->id) {
if($visit->created_at >= $user->pivot->created_at) {
$sum += $visit->views;
}
}
}
}
return $sum;
Would still like to see if it's possible to do it in a single query, no array looping.
Solved it! The foreach loop approach was making calls take waaaay too long. Some queries had over 100k records returning (that's a lot to loop through) causing the server to hang up. The answer is in part a big help from Dharmesh Patel with his 3rd edit approach. The only thing I had to do differently was add a where clause for the group_id.
Here's the final query (returns that 100k results query in milliseconds)
//Eager loading. Has overhead for large queries
//$ids = $group->users->modelKeys();
//No eager loading. More efficient
$ids = DB::table('group_user')->where('group_id', $group->id)->lists('user_id');
return DB::table('visits')->join('group_user', function ($query) use ($ids) {
$query->on('visits.user_id', '=', 'group_user.user_id')->on('visits.created_at', '>=', 'group_user.created_at');
})->whereIn('group_user.user_id', $ids)->where('group_id', $group->id)->sum('views');
Have you considered using a foreach?
$users = whereIn('user_id', $group->users->modelKeys());
foreach ($users as $user) {
// do your comparison here
}
I guess you need to use JOINS for this query, following code may take you in right direction:
$ids = $group->users->modelKeys();
return DB::table('visits')->join('group_user', function ($query) use ($ids) {
$query->on('visits.user_id', '=', 'group_user.user_id')
->whereIn('group_user.user_id', $ids)
->whereRaw('visits.created_at > group_user.created_at');
})->sum("views");
EDIT
$ids = $group->users->modelKeys();
return DB::table('visits')->join('group_user', function ($query) use ($ids) {
$query->on('visits.user_id', '=', 'group_user.user_id');
})->whereIn('group_user.user_id', $ids)
->whereRaw('visits.created_at > group_user.created_at')->sum("views");
EDIT
$ids = $group->users->modelKeys();
return DB::table('visits')->join('group_user', function ($query) use ($ids) {
$query->on('visits.user_id', '=', 'group_user.id') // group_user.id from group_user.user_id as per the loop
->on('visits.created_at', '>=', 'group_user.created_at');
})->whereIn('group_user.user_id', $ids)
->sum("views");

Categories