Класс для аргументов командной строки

Discussion in 'PHP' started by ckpunmkug, 8 Apr 2019.

  1. ckpunmkug

    ckpunmkug Member

    Joined:
    20 Mar 2017
    Messages:
    72
    Likes Received:
    72
    Reputations:
    10
    Очень простой в применении, но тем не менее очень эффективный класс для работы с аргументами командной строки.

    Всегда запаривало делать хэлпник к консольному скрипту, наконец нашел простое решение для приёма параметров и что бы для них было легко задать короткие и длинные дефисные имена, описание, возможность быть флагом или параметром, быть обязательным или нет.

    Смотрите пример. Запуск php cli.php -h

    Класс Args.php
    Code:
    <?php
    class Args {
    	static $description = "";
    	static $config = [];
    	static function help() {
    		$text = "";
    		if (!empty(self::$description))
    			$text .= "\n".self::$description."\n\n";
    		$text .= "Usage: \n";
    		foreach (self::$config as $config) {
    			$text .= "  {$config[0]} {$config[1]}";
    			if ($config[2] !== null) {
    				$text .= " {$config[2]}\t\t{$config[3]}\n";
    			} else {
    				$text .= "\t\t\t{$config[3]}\n";
    			}
    		}
    		echo $text."\n";
    	}
    	static function apply() {
    		self::add();
    		global $argv;
    		array_walk(self::$config, function(array $config, int $index, array $argv) {
    			$c = count($argv);
    			for ($i = 1; $i < $c; $i++) {
    				if ($argv[$i] == $config[0] || $argv[$i] == $config[1]) {
    					if ($config[2] !== null) {
    						if (!isset($argv[($i+1)])) {
    							trigger_error("\"{$config[2]}\" is not set for \"{$config[0]}\" in command line", E_USER_ERROR);
    							exit(255);
    						}
    						$i += 1;
    						self::$config[$index][4]($argv[$i]);
    						return null;
    					} else {
    						self::$config[$index][4]();
    						return null;
    					}
    				}
    			}
    			if (self::$config[$index][5]) {
    				trigger_error("\"{$config[0]}\" is not set in command line", E_USER_ERROR);
    				exit(255);
    			}
    		}, $argv);
    		if (!defined('VERBOSE'))
    			define('VERBOSE', true);
    		if (!defined('DEBUG'))
    			define('DEBUG', false);
    	}
    	static function add(array $config = []) {
    		if (!empty($config)) {
    			array_push(self::$config, $config);
    			return null;
    		}
    		self::add([
    			'-q', '--quiet', null, "Do not output anything", 
    			function() {
    				define('VERBOSE', false);
    			}, false
    		]);
    		self::add([
    			'-d', '--debug', null, "Run in debug mode", 
    			function() {
    				define('DEBUG', true);
    			}, false
    		]);
    		array_unshift(self::$config, [
    			'-h', '--help', null, "Show help text and exit",
    			function() {
    				self::help();
    				exit(0);
    			}, false
    		]);
    	}
    }
    
    Пример cli.php
    Code:
    <?php
    require "Args.php";
    
    Args::$description = "Program description";
    
    Args::add([
    	'-o', '--optional', null, "Optional flag", 
    	function() {
    		define('OPTIONAL', true);
    	}, false
    ]);
    
    Args::add([
    	'-r', '--required', null, "Required flag", 
    	function() {
    		define('REQUIRED', true);
    	}, true
    ]);
    
    Args::add([
    	'-O', '--optional_parameter', 'PARAMETER', "Optional with parameter", 
    	function(string $parameter) {
    		echo "Optional parameter: {$parameter}\n";
    	}, false
    ]);
    
    Args::add([
    	'-R', '--required_parameter', 'PARAMETER', "Required with parameter", 
    	function(string $parameter) {
    		echo "Required parameter: {$parameter}\n";
    	}, true
    ]);
    
    Args::apply();
    
    По умолчанию константы DEBUG=false VERBOSE=true. Встроенные флаги меняют их значение.
     
  2. barnaki

    barnaki Elder - Старейшина

    Joined:
    2 Nov 2008
    Messages:
    676
    Likes Received:
    139
    Reputations:
    4
  3. b3

    b3 Banned

    Joined:
    5 Dec 2004
    Messages:
    2,174
    Likes Received:
    1,157
    Reputations:
    202
  4. failsafe

    failsafe Member

    Joined:
    1 Apr 2016
    Messages:
    35
    Likes Received:
    10
    Reputations:
    2
    Причем тут шаблон проектирования Команда? Если кто то и реализовал с помощью этого шаблона описанную выше задачу - ну замечательно , но это частный случай, и в общем эти вещи никак не связаны
     
    ckpunmkug likes this.
  5. ckpunmkug

    ckpunmkug Member

    Joined:
    20 Mar 2017
    Messages:
    72
    Likes Received:
    72
    Reputations:
    10
    Собрал в одну функцию и выкинул флаг обязательности параметра.

    args.php
    Code:
    <?php
    function args() {
        global $argc, $argv;
        $CONFIG = func_get_args();
        $description = array_shift($CONFIG);
                                            /// create parameter help string
        $info_string = function(
            $short = null,
            $long = null,
            $value = null,
            $description = null
        ) {
            $result = "";
            if (is_string($short))
                $result .= "  {$short}";
            else
                $result .= "    ";
            if (is_string($long))
                $result .= " {$long}";
            else
                $result .= "\t";
            if (is_string($value))
                $result .= " {$value}";
            else
                $result .= "\t";
            if (is_string($description))
                $result .= "\t{$description}";
            $result = rtrim($result);
            return $result;
        };
                                            /// check enabling parameter in argv
        $parameter_enabled = function(
            $short = null,
            $long = null,
            &$value = null
        ) {
            global $argc, $argv;
            for ($index = 1; $index < $argc; $index++) {
                if (
                    $short === $argv[$index] ||
                    $long === $argv[$index]
                ) {
                    if (is_string($value)) {
                        if(!is_string(@$argv[$index+1]))
                            return false;
                        $value = $argv[$index+1];
                    }
                    return true;              
                }
            }
            return false;
        };
                                            /// create and print help message
        if (@$argv[1] == "-h" || @$argv[1] == "--help") {
            $CONFIG["help"] = [
                "short" => "-h",
                "long" => "--help",
                "description" => "Print this help message"
            ];
            $message = "\n{$description}\n\nUsage: \n";
            foreach($CONFIG as $config) {
                $string = $info_string(
                    @$config["short"],
                    @$config["long"],
                    @$config["value"],
                    @$config["description"]
                );
                $message .= "{$string}\n";
            }
            $message .= "\n";
            echo $message;
            exit(0);
        }
                                            /// call function if parameter enabled
        foreach($CONFIG as $config) {
            $value = @$config["value"];
            if ($parameter_enabled(
                @$config["short"],
                @$config["long"],
                $value
            )) {
                if (!is_callable(@$config["function"]))
                    continue;
                if (is_string(@$config["value"]))
                    $config["function"]($value);
                else
                    $config["function"]();
            }
        }
    }
    
    example.php
    Code:
    <?php
    require "args.php";
    args(
        "Program decription",
        [
            "short" => "-f",
            "long" => "--flag",
            "description" => "Flag description",
            "function" => function() {
                echo "Flag\n";
            }
        ],
        [
            "short" => "-v",
            "long" => "--variable",
            "value" => "VALUE",
            "description" => "Variable description",
            "function" => function(string $variable) {
                echo "Value: {$variable}\n";
            }
        ]
        //, next parameter arrays ...
    );