Hey, so I have a site all built already and I'm doing some maintenance and updating a few things. We have user profiles on the site and admin users can upload a couple of files to these profiles (like a contract type document and a DBS/CRB check document). However we've found that sometimes there are other documents the admins want to upload and rather than adding a new field each time we come across one of these we decided we will just have 1 field which allows multiple uploads and the admins can upload any documents they need to.
I have a migration adding a new field to the database to store this new list of uploaded files but for existing users we want to move the files saved in other database fields in to this new field and then we can remove those old fields from the database. I'm not sure of the best way to do this though.
There is lots of talk about seed data and such but I can't find much about dealing with migrations and user-generated content. Has anyone else run in to a similar situation? My only thought is to edit the data as part of the migration, moving the value of our previously used fields in to the new field, and then ending the migration by dropping the columns we used to use. Does that sound like a reasonably course of action or can anyone suggest a better way to handle this?
I normally write a small script and add an artisan command to run it.
You can then use eloquent commands that you know and iterate over the collection extracting and rewriting the data.
Sure, this is probably quicker as a SQL query, but I prefer safety from knowing what I am doing over the efficiency of a single, not to be repeated task.
Just one tip, if there are a lot of records to process, this
You can also use eloquent within a migration.. for example, this was a migration I had back in May when I added a field to a table:
<?php
use App\Models\Log;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddMonthStampToLogs extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('logs', function (Blueprint $table) {
$table->date('month_stamp')->nullable();
});
$logs = Log::with('loggable')->get();
foreach ($logs as $log) {
$log->month_stamp = $log->loggable->month_stamp;
$log->save();
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('logs', function (Blueprint $table) {
$table->dropColumn('month_stamp');
});
}
}
@Snapey: I'm wondering what you perceive to be the risk of having this within the migration? I like the idea of putting this in to an artisan command, but an artisan command that I only ever run once seems a little bit like overkill.
You could add a command like I describe in this post that lets you run an arbitrary script file.. might make more sense than implementing a dedicated one-off artisan command.
@caAsh If you’re adding a new column, and you need to move legacy data to this new column, then that’s part of the migration, so place it in your migration file. It’s fine to put arbitrary commands like this in a migration. You don’t want to separate it out into a separate Artisan command as you then have to remember to run that. If you’re just running php artisan migrate then it’s not going to know when to stop for you to run the other Artisan command. Plus, it can lead to corrupting your schema and data if you run it out of sequence.
It’ll also mean new or other teams members need to remember it, and if there’s one thing that’s a constant, it’s human error. So mitigate this by just including the moving of data in your migration itself. Migrations can include moving data as well as creating/renaming/dropping columns and tables.
I agree with @martinbean , but be careful if the old data is removed because you would not be able to roll the migration back. No difference here to running it as a separate command, but migrations imply rollback is possible.
I've put this in to my migrations before and will keep doing that. I was just wondering if that's what everyone else does too. Sounds like it is! Thanks everyone!