Принимаем аргументы из командной строки

Вот как обычно бывает: Нам нужно написать малюсенький консольный скрипт бекапа, который, может запускаться из крона, и при этом скрипт должен принимать параметры для соединения с базой данных.

Функции argv и argc

Самое простейшее что мы начнём писать будет выглядеть примерно так:

cli-argv-argc.php

// Ожидаем что скрипт будет вызываться с такими параметрами:
// php backup.php dbuser dbpassword database host

if ($argc != 5) {
    die(PHP_EOL . 'Use: php backup.php dbuser dbpassword database host' . PHP_EOL);
}

$dbuser     = $argv[1];
$dbpassword = $argv[2];
$database   = $argv[3];
$host       = $argv[4];

$mysql = mysql_connect($host, $dbuser, $dbpassword);
mysql_select_db($database, $mysql);
// ...

Тут мы использовали системную переменную argс для получения количества всех параметров. Запомните, что нулевой параметр (имя скрипта) тут тоже учитывается.

И системную переменную argv с массивом всех параметров.

Для простейшего скрипта этого хватит, но что если мы захотим поддерживать и отдать этот скрипт другим разработчикам?

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

php backup.php dbuser database dbpassword host

Разбираем параметры с функцией getopt

Вот тут нам на помощь приходит крайне удобная функция разбора параметров: getopt

Основная мощь getopt в том, что она позволяет нам использовать флаги, обязательные и необязательные параметры в произвольном порядке.

Давайте напишем простой, но очень выразительный пример использования getopt, а потом, посмотрите как люди раньше мучались с регулярками, что бы разобрать командную строку :)

backup.php

// Тут показаны две формы записи аргументов: короткая и полная
// При этом, если после параметра стоит два двоеточия, значит параметр необязательный,
// а если одно двоеточие - значит обязательный.
// все параметры которые не указаны в конфигурации будут проигнорированы
$params = array(
    ''      => 'help',
    'h::'   => 'host::',
    'u:'    => 'user:',
    'p::'   => 'password::',
    'd:'    => 'database:',
);

// Default values
$host       = 'localhost';
$user       = 'root';
$password   = null;
$database   = '';
$errors     = array();

$options = getopt( implode('', array_keys($params)), $params );

if (isset($options['host']) || isset($options['h']))
{
    $host = isset( $options['host'] ) ? $options['host'] : $options['h'];
}

if (isset($options['user']) || isset($options['u']))
{
    $port = isset( $options['user'] ) ? $options['user'] : $options['u'];
}
else
{
    $errors[]   = 'user required';
}

if (isset($options['password']) || isset($options['p']))
{
    $socket = isset( $options['password'] ) ? $options['password'] : $options['p'];
}

if (isset($options['database']) || isset($options['d']))
{
    $database = isset( $options['database'] ) ? $options['database'] : $options['d'];
}
else
{
    $errors[]   = 'database required';
}

if ( isset($options['help']) || count($errors) )
{
    $help = "
usage: php backup.php [--help] [-h|--host=127.0.0.1] [-u|--user=root] [-p|--password=secret] [-d|--database]

Options:
            --help      Show this message
        -h  --host      Server hostname (default: localhost)
        -u  --user      User
        -p  --password  Password (default: no password)
        -d  --database  Database
Example:
        php backup.php --user=root --password=secret --database=blog
";
    if ( $errors )
    {
        $help .= 'Errors:' . PHP_EOL . implode("\n", $errors) . PHP_EOL;
    }
    die($help);
}

$mysql = mysql_connect($host, $user, $password);
mysql_select_db($database, $mysql);

// .... 

Теперь запустим наш скрипт с параметром –help и порадуемся что хорошо поддерживаемую и понятную программу так легко написать

php backup.php --help

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

Давайте ещё добавим последний штрих, который должен быть во всех наших скриптах:

  1. Можно убрать расширение php
  2. В начало каждого скрипта добавим опцию для интерпритатора #!/usr/bin/env php
  3. Сделаем наши скрипты исполняемыми chmod +x backup.php

После этого можно пользоваться получившимся скриптом как настоящей юникс-программой:

./backup --help

или

./backup --user=ukko --password=password --database=db1