lundi 20 janvier 2020

Reusing Code In Commands, i.e. Creating a BaseCommand to reuse "use" statements, arguments, and common variables

I'm writing many import commands in Laravel 5.8 that all take the same argument and import a section of the data. For example, I have an ImportUsersCommand.php, ImportFilesCommand.php, and ImportNotesCommand.php that all take a location_id argument (there are a ton more commands, but I'm trying to keep this example simple). The scripts all connect to an external MS SQL Server database specific to that location and then run some code to import the data into a MySQL database.

I've noticed that I'm reusing a lot of the same come, and I'd like to refactor it out to something like a BaseImportCommand.php.

Example Command - ImportUsersCommand.php (What I Currently Have)

<?php

namespace App\Console\Commands\Imports;

use Illuminate\Console\Command;

// Models
use App\Models\Location;
use App\Models\Files;
use App\Models\Notes;
use App\Models\User;
// ... and the list continues with many more models!

use DB;
use Hash;
use Schema;
use Carbon\Carbon;
// ... and the list continues with many more!    

class ImportUsers extends Command
{
    protected $signature = 'import:users {location_id}';
    protected $description = 'Import users from another data source';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        $this->info($this->description);
        ini_set('memory_limit', '4000M');            
        $location = Location::findOrFail($this->argument('location_id'));
        Config::set("database.connections.chirotouch", [
            'driver' => env('SQLSERVER_DB_CONNECTION'),
            'host' => env('SQLSERVER_DB_HOST'),
            'port' => env('SQLSERVER_DB_PORT'),
            'database' => 'location_'.$location->id,
            'username' => env('SQLSERVER_DB_USERNAME'),
            'password' => env('SQLSERVER_DB_PASSWORD'),
        ]);
        // ... and the code continues just for setting up the command...

        // Only after about 100 lines of code do we actually get to the 
        // specifics of what this particular command does.

        foreach ($location->users as $user) {
            // Do what I need to do
        }
    }
}

What I'd like ImportUsersCommand.php to look like

<?php

namespace App\Console\Commands\Imports;

use App\Console\Commands\Imports\BaseImportCommand;

class ImportUsers extends BaseImportCommand
{
    protected $signature = 'import:users {location_id}';
    protected $description = 'Import users from another data source';

    public function __construct()
    {
        parent::__construct();
    }

    public function handle()
    {
        foreach ($location->users as $user) {
            // Do what I need to do
        }
    }
}

But I'm having trouble drafting my BaseImportCommand.php. How can I extract the use statements, the connecting to the external DB, the $this-info() statements, the configuration statments such as increasing the memory limit, and the assignment of the $location variable to another file that can be reused for every import command?

Any help would be much appreciated!



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire