jeudi 2 novembre 2017

Any PHP Design Patterns to Handle Command Line Arguments?

So I am writing a class that needs to accept arguments, some arguments are mandatory, others are optional.

For example: php test.php -a app1 -u username -p password --l --dump-data

The last two with double dashes are optional.

The -a arguments chooses an app, there are several apps such as app2, app3, app4 which are all classes that are in same directory. --l does a list mode which parses the data and its one function that will do that, --dump-data will be a dump of database data. List mode is the prettier version of --dump-data. So basically each argument is a function that shows data in a certain format.

I am using a Factory pattern to let the test.php main class choose which app to use. Not all the complete code but it should give you a good idea.

Class Test {
    public static function factory($app, $username, $password, $mode) {
        switch ($app) {
        case 'app1':
            $obj = new app1();
            $obj->login($username, $password, $mode);
            break;
        case 'test':
            $obj = new app2();
            $obj->login($username, $password, $mode);
            break;
        default:
            throw new Exception("Could not find that app '" . $integration . "'", 1000);
    }
    return $obj;
    }

}

// Code to handle arguments
$longopts  = array(
    "l",    
    "dump-data"
);
$options = getopt("a:u:p:", $longopts);

$mode = array();
foreach($options as $key => $value) {
    if($value == '') {
        $mode[] = $key;
    }
}

$test = Test::factory($options['a'], $options['u'], $options['p'],  $mode);

As you see i am passing $mode which contains an array of all the long opts. It will be something like this if i include --l and --dump-data

Array
(
[0] => l
[1] => dump-data
)

So the trick here is that if i pass $mode to $obj->login($username, $password, $mode); I will be then having to handle the logic on the app, means each app will have to have identical if statements. For example inside an app class:

if($mode[1] == 'dump-data') {
    print_r($data) // print non formatted data dump from database
} else {
    $this->listmode($data); // send dump data to list function so it can print it pretty.
}

So trying to find a way that I don't have to repeat this code on every single app class. Also don't want to repeat code on the switch statements which was my first thought, call a function if an argument is present or not. Any ideas or thoughts are welcome. thx

Aucun commentaire:

Enregistrer un commentaire