Imran Imran - 6 months ago 24
PHP Question

Traversing through collection and updating records using Eloquent

I am using eloquent to pull a list of

App\Post
's from my database and deleting their file contents from my server.
I am traversing through the list and processing a delete action, on success I want to store a value to the respective App\Post but I am getting this error:

Method save does not exist.


Here is my code:

$posts_to_purge = Post::where('post_date', '<', \Carbon\Carbon::now()->subDays(7)->toDateString())->get();

if(count($posts_to_purge) > 0)
{
foreach ($posts_to_purge as $post) {
$directory = storage_path() . '/' . $post->post_date;

$deleted_folder = File::deleteDirectory($directory);

if($deleted_folder)
{
// 'purged' is a column in my Post table
$post->purged = 1;
}
else
{
Log::error('Unable to delete \''.$directory.'\' directory');
}

} // end foreach loop

// Update collection with purged posts
$posts_to_purge->save();

}


A side question to this... is this the most efficient way to do this? As I only want to update SOME records in the collection.. should I create a separate collection and save that only?

Answer

Collections don't have really have the power to interact with the database in Laravel. You are able to define a custom collection class with a save() method however there is a simple way to do what you want.

$posts_to_purge = Post::where('post_date', '<', \Carbon\Carbon::now()->subDays(7)->toDateString())->get();

if(count($posts_to_purge) > 0)
{
    foreach ($posts_to_purge as $post) {
    $directory = storage_path() . '/' . $post->post_date;

    $deleted_folder = File::deleteDirectory($directory);

    if($deleted_folder)
    {
        // 'purged' is a column in my Post table
        $post->purged = 1;
        $post->save ();
    }
    else 
    {
        Log::error('Unable to delete \''.$directory.'\' directory');
    }

} // end foreach loop

// Update collection with purged posts
$posts_to_purge->save();

}

Yes this does do one query per updated model, however updates by primary key are very fast.

If you were super committed to using one query, you could simply save each updated Post's ID to an array and do something like Post::whereIn ('id', $updated_ids)->update(['purged' => 1]);

Comments