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

É amigos, o php me fascina, mas também me assusta.

DESAFIO: Consegue explicar esse cód?

$friend = "Allyce";
$getPerson = function ($name, $age) use ($friend): object {
    return new class($name, $age, $friend)
    {
        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 = $getPerson("Gabriel", 19);
echo ($person->saudation());
Carregando publicação patrocinada...
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.

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
3
2

Pelo que eu entendi, a funçao get person esta definindo os parametrôs, setando um objeto como retorno, e entao ele retorna uma classe que ele esta criando dentro da funçao

Você parece surpreso com isso então imagino que nao foi escrito por voce, de onde veio essa reliquia?

2

Esse código cria uma classe pessoa na variável "getPersona" com um nome e idade e usa a variável amigo "friend" que foi definida anteriormente. A pessoa pode fazer uma saudação falando o nome, quantos anos tem e de quem é amigo. E no final, é finalmente instaciado a pessoa "getPersona" com o nome Gabriel.

Esse código está de uma forma que nunca encontrei no PHP. Mas acredito que fique mais fácil de entender se você usar orientação a objeto e definir uma classe persona com as mesmas funções. Ai está atribuindo uma função a variável e usando objetos em método funcional. Fica bem confuso mesmo. Lembro que levei um tempo pra entender isso quando vi no javascript. E ainda hoje tem função que fico bugado kkkkk.

2

Faz tempo que não programo em PHP, mas não me parece nada muito complicado, pense de dentro pra fora:

Isso aqui é uma conceito chamado HEREDOC, não é exclusividade do PHP

    <<<LABEL
        Olá, meu nome é {$this->name}, tenho {$this->age} anos de idade
        e sou amigo da {$this->friend}
    LABEL;

Aqui está sendo retornado um novo objeto de uma classe anônima

return new class($name, $age, $friend)
    {
        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;
        }
    };

Aqui está criando uma função anônima que recebe 2 parâmetros e utiliza uma variável do escopo externo ao da função, no caso $friend que está declarado logo acima.
E essa funçõa anônima está sendo atribuída à uma variável chamada $getPerson.
Quem é de JS está bem acostumado a atribuir funções para variáveis.

$getPerson = function ($name, $age) use ($friend): object {
    ////
}

E aqui é apenas a chamada da função contida na variável

$person = $getPerson("Gabriel", 19);

Não tem nada demais nesse código, só é uma sintaxe pouco usada em cursos para iniciantes.
Outra forma de se fazer a mesma coisa, mas como uma sintaxe mais comum para que está aprendendo seria aglo mais ou menos assim:

class Person {

    private $name;
    private $age;
    private $friend;
	
	// Essa é a forma mais clássica, mas há formas mais modernas
	// de declarar atributos no construtor
    function __construct($name, $age, $friend) 
    {
        $this->name = $name;
        $this->age = $age;
        $this->friend = $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();

1

Diversas linguagens permitem obter o mesmo resultado de maneiras diferentes. Como já disseram, esse código usa uma sintaxe pouco convencional, que não é muito usada em tutoriais mais voltados pasa iniciantes.

Mesmo com linguagens que possuem uma sintaxe mais estrita como Java e C#, você encontrará exemplos de código mal escritos e isso não é necessariamente um problema da linguagem e sim do programador.

1

É uma das linguagem que eu mais tenho vontade de aprender, mas fico com receio de depois que terminar os estudos não ter muito mercado... nem sei por onde começar no backend.