массивы — любые шаблоны проектирования PHP для обработки аргументов командной строки?

Поэтому я пишу класс, который должен принимать аргументы, некоторые аргументы являются обязательными, другие необязательными.

Например: php test.php -a app1 -u имя пользователя -p пароль —l —dump-data

Последние два с двойными черточками необязательны.

Аргументы -a выбирают приложение, есть несколько приложений, таких как app2, app3, app4, которые все классы находятся в одном каталоге. —l выполняет режим списка, который анализирует данные, и его единственная функция, которая это сделает, —dump-data будет дампом данных базы данных. Режим списка является более красивой версией —dump-data. Таким образом, в основном каждый аргумент является функцией, которая показывает данные в определенном формате.

Я использую шаблон Factory, чтобы позволить главному классу test.php выбрать, какое приложение использовать. Не весь полный код, но он должен дать вам хорошую идею.

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 '" . $app . "'", 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);

Как вы видите, я передаю $ mode, который содержит массив всех длинных опций. Это будет что-то вроде этого, если я включу —l и —dump-data

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

Итак, хитрость в том, что если я передаю $ mode в $ obj-> login ($ username, $ password, $ mode);
Тогда мне придется обрабатывать логику приложения, значит, каждое приложение должно иметь одинаковые операторы if. Например, внутри класса приложения:

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.
}

Поэтому я пытаюсь найти способ, которым мне не нужно повторять этот код в каждом классе приложения. Также не хочу повторять код в операторах switch, который был моей первой мыслью, вызывать функцию, если есть аргумент или нет. Любые идеи или мысли приветствуются. Спасибо

0

Решение

Пусть каждое приложение расширяет базовый класс абстрактного приложения, а затем помещает общий код в абстрактный. $mode параметр, вероятно, не принадлежит в качестве аргумента на login() класс, кажется, не имеет ничего общего с этим конкретно. Я бы переместил это в конструктор.

abstract class AbstractApp
{

protected $mode = null;

public function __construct($mode)
{
$this->mode = $mode;
}

// put your login method here if it's the same for every app
public function login($user, $pass)
{
}

public function process($data)
{
if ($this->mode) === 'dump-data') {
print_r($data);
} else {
$this->listmode($data);
}
}

}

class App1 extends AbstractApp
{
// put your listmode method here if it's custom to this app
public function listmode($data)
{
}
}

Вам также не нужно добавлять оператор case для каждого приложения, вы можете просто использовать само имя приложения. Просто убедитесь, что имя приложения совпадает с именем класса, которое его определяет. Например:

class Test
{
public static function factory($app, $user, $pass, $mode)
{

// I'd recommend putting the app classes in their own namespace
// so that you can easily whitelist them just by their existence.
$class = '\\MyProject\\App\\' . $app;
if (!class_exists($class)) {
throw new Exception('No such app.');
}

$obj = new $class($mode);
$obj->login($user, $pass);
return $obj;

}
}
0

Другие решения

Значительное количество хорошо известных инструментов используют Symfony / консоли компонент для обработки синтаксического анализа и вывода командной строки. Инструмент Composer является одним из таких примеров.

Его даже не нужно использовать как часть приложения Symfony — документация показывает, как его можно использовать самостоятельно для одной или нескольких команд, как вам нравится.

<?php

# example code snippets taken from https://symfony.com/doc/current/console/input.html
# defining arguments in a command
protected function configure()
{
$this
// ...
->addArgument('name', InputArgument::REQUIRED, 'Who do you want to greet?')
->addArgument('last_name', InputArgument::OPTIONAL, 'Your last name?')
;
}

# Using arguments
protected function execute(InputInterface $input, OutputInterface $output)
{
$text = 'Hi '.$input->getArgument('name');

$lastName = $input->getArgument('last_name');
if ($lastName) {
$text .= ' '.$lastName;
}

$output->writeln($text.'!');
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector