Updating rows in laravel mysql database - php

I've set up a database and want to update the column status for each row in my UsersController:
I started with this:
User::where('id', '=', 1)->update(['status' => $status]);
This is working, but I need some loop to change all the rows, something like this:
foreach $id from the table
run some code to change individual $status variable
set individual $status value in the 'status' column in each row:
User::where('id', '=', $id)->update(['status' => $status])
end foreach
So for me its unclear how to go through the table via the foreach. Then save the calculated status from my code to each individual id?

#Serge solution is fine for few records but you should be able to use chuck as #ceejayoz suggested
User::chunk(100, function ($users) {
$users->each(function ($user) {
$user->status = getStatus($user);
$user->save();
});
});

Unless the table contains millions of rows... a simple procedural way of doing it is...
$users = Users::get(); // Gets a collection of all users...
foreach ( $users as $user ) {
//compute your status
$user->status = get_your_user_status($user->id);
$user->save();
}
You could also consider using a more functional approach with map for example...

Related

How do I remove duplicate rows with same column values in Laravel?

I'm trying to make a artisan command in Laravel to remove all venues that have the same address and leave the one with the lowest ID number (so first created).
For this I need to check 3 fields: 'street', 'house_number', 'house_number_addition'
This is how far I've got:
$venues = Venue::select('street', 'house_number', 'house_number_addition', DB::raw('COUNT(*) as count'))
->groupBy('street', 'house_number', 'house_number_addition')
->having('count', '>', 1)
->get();
foreach ($venues as $venue) {
$this->comment("Removing venue: {$venue->street} {$venue->house_number} {$venue->house_number_addition}");
$venue->delete();
}
Only the delete is not working but is also not giving an error.
To be able to delete an item, Eloquent needs to know it's id. If you make sure your models' id is queried, you can call delete() without issues.
In your query, however, that won't work because you have a GROUP_BY statement, so SQL doesn't allow you to select the id column (see here).
The easiest solution here is to utilize Eloquent's Collection class to map over the models, something like:
$uniqueAddresses = [];
Venue::all()
->filter(function(Venue $venue) use (&$uniqueAddresses) {
$address = sprintf("%s.%s.%s",
$venue->street,
$venue->house_number,
$venue->house_number_addition);
if (in_array($address, $uniqueAddresses)) {
// address is a duplicate
return $venue;
}
$uniqueAddresses[] = $address;
})->map(function(Venue $venue) {
$venue->delete();
});
Or, to make your delete query a little more efficient (depending on how big your dataset is):
$uniqueAddresses = [];
$duplicates = [];
Venue::all()
->map(function(Venue $venue) use (&$uniqueAddresses, &$duplicates) {
$address = sprintf("%s.%s.%s",
$venue->street,
$venue->house_number,
$venue->house_number_addition);
if (in_array($address, $uniqueAddresses)) {
// address is a duplicate
$duplicates[] = $venue->id;
} else {
$uniqueAddresses[] = $address;
}
});
DB::table('venues')->whereIn('id', $duplicates)->delete();
Note: the last one will permanently delete your models; it doesn't work with Eloquent's SoftDeletes functionality.
You could, of course, also write a raw query to do all this.

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';
}
}

Updating record in Laravel from a select using laravel's lists not working

In one of my laravel pages I am updating a record. The form is bound to the model, and all fields are updating properly except those where I am presenting a select using lists that populates the select from the database:
{{ Form::select('resume_id', $resume_lists) }}
I just have no idea why these will not update. They are pulling the appropriate values from mySQL. Any ideas?
Thank you.
I have my code in routes, not in a controller
Route::get('application/edit/{id}', array('as' => 'application.edit', function($id)
{
$user = Auth::user();
$company_lists = Company::where('user_id', '=', $user->id)->get()->lists('company', 'id');
$resume_lists = Resume::where('user_id', '=', $user->id)->get()->lists('name', 'id'); //changed resume to name
$companies = Company::where('user_id', '=', Auth::user()->id)->get(); //just added
//$currentintdate=$application['followupBy']; /////
Session::put('appid', $id); /////
return View::make('application-edit', array('company_lists' => $company_lists), array('resume_lists' => $resume_lists))
->with('application', Application::find($id));
}));
try this:
$resume_lists = YourResumeModel::lists('title', 'id');
{{ Form::select('resume_id', $resume_lists) }}
frist column is your text for dropdown
and next column is your row id
just var dump the resume list data in controller, make sure its available at the controller, so after you initialize the variable/array
return var_dump($resume_lists); // check if its valid array with id as key and label as value, if available, go view and do the same
Use: $resume_lists = Resume::all()->where('user_id', '=', $user->id)->lists('name', 'id');
Or: $resume_lists = Resume::where('user_id', '=', $user->id)->lists('name', 'id')->toArray();
well, my records were not updating because I had a column as not nullable and I was not passing any value while testing. I got no error at all about this so I had no idea.

Laravel4: Chunk function not working with model save()

I have a query to select all users and hash the password and save that model. Because it times out as there is large data in the DB, I thought I will try chunk() function. My query looks like,
$users = User::where('password','!=','0')->select(array('password'))->chunk(50,function($users){
foreach ($users as $user) {
$user->password = Hash::make($user->password);
$user->save();
}
});
This doesn't save a model. when I try to dump the $user variable after save() it displays the updated values but when I look into DB it is still unaltered. I tried using try catch and transaction just to see if it hits any exception during the process, nothing helped. Any help will be appreciated. Also, I don't have $guarded on the password field.
You're just doing it wrong. Can you tell which row should be updated in that loop? No? Eloquent doesn't know it either, so it runs update ... where id is null ;)
Simply add id to the select clause and it will work (unless you have some magic happening in the saving event etc):
$users = User::where('password','!=','0')
->select(array('id', 'password'))
->chunk(50,function($users){
foreach ($users as $user) {
$user->password = Hash::make($user->password);
$user->save();
}
});

Laravel Join Returning odd values

Just come across a bug on my Join query.
I am echoing out data in a foreach, and showing the username. On other pages it works fine and each username matches the username from the ID in the row. However, in the example below the username return is ALWAYS the name of the logged in user.
Hope the below makes some more sense. Thanks.
The query is:
$query = DB::table('blogs')
->join('followers', 'blogs.id', '=', 'followers.blogid')
->where('followers.userid', Auth::user()->id)
->where('frontpage', '1')
->latest('lastupdated');
This is called via:
Route::get('following', array('before' => 'auth', function()
{
$slug = Route::getCurrentRoute()->uri();
$builds = Blog::findBuilds($slug);
return View::make('pages/home', compact('builds'), array('pageTitle' => 'Builds You Are Following'));
}));
And then on the pages/home I am showing the data like so:
foreach ($builds as $build)
{
$usernameOfOwner = User::usernameFromID($build->userid);
}
And then... the function for getting the username from ID is:
public static function usernameFromID($id) {
$user = DB::table('users')->where('id', $id)->first();
return $user->username;
}
Everywhere else on my website when I run a query similiar to the top one but not a join so e.g.:
$query = static::where('frontpage', '1')->latest('lastupdated');
It works fine, so my only guess is that its down to the Join as thats the only different part of the code.
The problem is that you have multiple columns named userid. followers.userid and blogs.userid. Now in this case, unfortunately followers.userid gets returned when you use $build->userid
You can change that by only selecting the columns you want in your result.
$userid = Auth::user()->id;
$query = DB::table('blogs')
->join('followers', function($q) use ($userid){
$q->on('blogs.id', '=', 'followers.blogid');
$q->where('followers.userid', '=', $userid);
})
->select('blogs.userid', 'other-column')
->where('frontpage', '1')
->latest('lastupdated');
By the way: * works too, so you can do select('blogs.*') if you want

Categories