Executando verificação de segurança...
6

É basicamente uma função que retorna um objeto. Mas é feito de uma maneira, na minha opinião, desnecessariamente complicada (mais detalhes abaixo). Mas vamos por partes...


Função anônima

Primeiro o código cria uma função anônima - no caso, function ($name, $age) indica que ela recebe dois parâmetros (o nome e a idade).

Mas em PHP funções anônimas funcionam como closures (ver mais aqui e aqui), ou seja, ela pode "capturar" variáveis de um escopo externo. No caso, o use ($friend) indica que a função vai usar o valor da variável $friend, que foi declarada fora da função.

Esse ponto é importante: não importa se mudarmos o valor de $friend depois, a função continua usando o valor que a variável tinha no momento em que a closure foi criada. Por exemplo, se eu fizer:

$person = $getPerson("Gabriel", 19);
echo ($person->saudation()). "\n";

$friend = "Bob";
$person = $getPerson("Fulano", 42);
echo ($person->saudation()). "\n";

A saída será:

    Olá, meu nome é Gabriel, tenho 19 anos de idade
    e sou amigo da Allyce
    Olá, meu nome é Fulano, tenho 42 anos de idade
    e sou amigo da Allyce

Pois quando a função foi criada, ela usa o valor que $friend tinha naquele momento.

Como curiosidade, se eu quisesse que uma alteração no valor de $friend se refletisse dentro da closure (ou seja, no código acima o segundo caso imprimisse "Bob" em vez de "Allyce"), teria que mudar para use (&$friend) (o uso de & faz com que agora ele use uma referência).


Classe anônima

Dentro da função, é criada uma classe anônima, e uma instância desta é retornada. Ela basicamente usa o nome e idade que foram passados como argumentos, e a variável $friend declarada fora da função, como já explicado acima.

Ou seja, ao fazer $getPerson("Gabriel", 19);, a função retornará uma classe usando $name igual a "Gabriel", $age igual a 19 e $friend será "Allyce", que foi definido anteriormente, quando a função foi criada. Se eu quiser criar outra instância com dados diferentes, basta chamar a função com outros parâmetros - por exemplo, $getPerson("Fulano", 42) - o $friend continua sendo "Allyce", como já explicado.


Precisa ser assim?

Como eu disse no início, acho que o código é desnecessariamente complicado. Acho que funções e classes anônimas têm o seu uso (ver aqui e aqui), mas este caso não me parece ser um deles.

Seria mais simples criar uma classe e pronto:

class Person {
    // usando sintaxe de PHP >= 8
    function __construct(private $name, private $age, private $friend) {
    }

    public function saudation(): string {
        return <<<LABEL
            Olá, meu nome é {$this->name}, tenho {$this->age} anos de idade
            e sou amigo da {$this->friend}
        LABEL;
    }
}

$person = new Person("Gabriel", 19, "Allyce");
echo ($person->saudation()), "\n";

"Ah, mas agora não tem mais o valor default de $friend, tenho que passar como parâmetro toda hora."

Sim, mas será que fazia sentido este comportamento do código original? Se todas as pessoas só tem o mesmo amigo, vc pode usar um valor default para ele, como por exemplo:

function __construct(private $name, private $age, private $friend = null) {
    if ($this->friend == null) { // se não for informado o $friend, usa "Allyce"
        $this->friend = "Allyce";
    }
}

Ou simplesmente não coloque $friend como parâmetro do construtor, e inicialize-o sempre com o mesmo valor. Não vejo muito ganho da forma que estava no código original.

Carregando publicação patrocinada...
1

Parabéns cara, explicou excepcionalmente bem. Nem tinha avaliado o comportamento da variável $friend dentro da linha de execução do cód, achei simplesmente fenomenal. A idéia foi só mostrar um pouco do que se consegue fazer dentro do php, claro que o exemplo acima não seria aplicável em um cenário real, pois acaba por complicar demais as coisas. Mas nos mostra alguns dos inúmeros recursor que podem ser explorados em lógicas reais de negócios dentro de nossas aplicações.

1