How to work around a 'problem' with GOTO in PHP

0

I have a small package manager in the terminal of own use and that manages my Framework, and I'm giving an improvement in it, and it falls into a problem where I can not loop without using goto, as in the code below:

$stdin = fopen('php://stdin', 'r');
$rs_add_deps = fgetc($stdin);
$requires = [];
if ($rs_add_deps == 's') {
    add_req:
    echo "Digite o pacote completo:";
    $stdin = fopen('php://stdin', 'r');
    $countReq = count($requires);
    $requires[$countReq] = fgetc($stdin);
    goto test_add_req;
} else {
    end_add_req:
    var_dump($requires);
}
test_add_req:
echo "Adicionar outro pacote?";
$stdin = fopen('php://stdin', 'r');
$add_n_pack = fgetc($stdin);
if ($add_n_pack == 's') {
    goto add_req;
} else {
    goto end_add_req;
}

This script is adding the possible packages to array $requires[] according to what the user defines it wants, works perfectly, knowing that the interaction is via terminal and that I will never know how many packages are and (it does some tests to know if the package is valid but cleaned to make the example simpler), is there a less crooked way of capturing those values and adding them to the array?

Another second solution I have is this, but I found it much more complex than using goto:

$stdin = fopen('php://stdin', 'r');
$rs_add_deps = fgetc($stdin);
$requires = [];
$countReq = 0;
$ask = false;
if ($rs_add_deps == 's') {
    while (true) {
        if (is_numeric($countReq) === 0) {
            echo "Digite o pacote completo EX: 'gm/bv4fphp':";
            $stdin = fopen('php://stdin', 'r');
            $requires[$countReq] = fgetc($stdin);
            $ask = true;
            $countReq += 1;
        } elseif (is_numeric($countReq) > 0) {
            if ($ask == true) {
                echo "Adicionar outro pacote?";
                $stdin = fopen('php://stdin', 'r');
                $add_n_pack = fgetc($stdin);
                if ($add_n_pack == 's') {
                    $ask = false;
                } else {
                    $countReq = 'get-out';
                }
            } else {
                echo "Digite o pacote completo:";
                $stdin = fopen('php://stdin', 'r');
                $requires[$countReq] = fgetc($stdin);
                $ask = true;
                $countReq += 1;
            }
        } else {
            var_dump($requires);
            break;
        }
    }
}

NOTE: This project is structured, 0 orientation, did not want to leave this context in this project.

    
asked by anonymous 02.03.2018 / 20:48

1 answer

2

First, I do not really understand why so many fopen , one suffices, and the operation continues with fgetc within a while or in a recursion with functions, ie you are opening the php://stdin several times % no need, you could just use something like:

<?php
$stdin = fopen('php://stdin', 'r');

while (!feof($stdin)) {
    var_dump(fgetc($stdin));
}

Ready, you're in an infinite loop already, or you could simplify it even further and directly use the constant STDIN , like this:

<?php
while (!feof(STDIN)) {
    var_dump(fgetc(STDIN));
}

Now let's go to your code

Your problem was not even with while or goto , there are faults in your code that may or may not be the reason for not working as you want, for example:

echo "Digite o pacote completo EX: 'gm/bv4fphp':";
$stdin = fopen('php://stdin', 'r');

Here you are prompted to enter a path, but then use:

$requires[$countReq] = fgetc($stdin);

That will only return the first letter and not the full path, because fgetc returns only the first character of something typed

I think what you want is something close to this:

<?php
$requires = [];

function pegar_resposta()
{
    return trim(fgets(STDIN));
}

function adicionar_pacotes()
{
    global $requires;

    if (empty($requires) === false) {
        echo "Adicionar outro pacote?";
        $resposta = pegar_resposta();

        if ($resposta === 's') {
            return;
        }
    }

    echo "Digite o pacote completo EX: 'gm/bv4fphp':";

    $resposta = pegar_resposta();

    if ($resposta === 's') {
        return;
    }

    $requires[] = $resposta;

    adicionar_pacotes();
}

adicionar_pacotes();

print_r($requires);

It's very simplified even, the following function I created for you to have the settings only in one location:

function pegar_resposta()
{
    return trim(fgets(STDIN));
}

And trim is to remove spaces and line breaks, so you can get s when you want to finish.

With while would look like this:

<?php
$requires = [];

function pegar_resposta()
{
    return trim(fgets(STDIN));
}

while (true) {
    if (empty($requires) === false) {
        echo "Adicionar outro pacote?";
        $resposta = pegar_resposta();

        if ($resposta === 's') {
            break;
        }
    }

    echo "Digite o pacote completo EX: 'gm/bv4fphp':";

    $resposta = pegar_resposta();

    if ($resposta === 's') {
        break;
    }

    $requires[] = $resposta;
}

print_r($requires);
    
02.03.2018 / 22:35