Jump to content
proclnas

[PHP] Splat Operator

Recommended Posts

Olá guys, tudo em ordem?
Meu primeiro post aqui no mente binária, que inclusive foca em php e que provavelmente irá ajudar aqueles que se aventuram
na linguagem. Boa leitura! ;)

Em alguns momentos pode surgir a necessidade de se criar um método/função com argumentos variáveis. O próprio php possui funções que aceitam “n” argumentos, como por ex:

Entre outros. A partir da versão 5.6 do PHP é possível utilizar o “splat operator (…)” que nos da a capacidade de criar método/funções com argumentos variáveis, entre outras coisas. Ex:

<?php

function evaluateString($callback, ...$strings) {
    $myStr = 'INITIAL: ';
    foreach ($strings as $stringPiece) {
        $myStr .= $stringPiece;
    }
    return call_user_func($callback, $myStr);
}

$strAllUp = evaluateString(
    'strtoupper',
    'rodrigo',
    ' nascimento'
);

var_dump($strAllUp);
// Saída: string(27) "INITIAL: RODRIGO NASCIMENTO"

 

Ex de utilização:

<?php 

function soma(...$numbers) { 
    var_dump($numbers, count($numbers)); 
} 

soma(1, 2, 3, 4); // Saída
array(4) { 
    [0]=> int(1) 
    [1]=> int(2) 
    [2]=> int(3) 
    [3]=> int(4) 
} 

int(4) // Quantidade de parâmetros recebidos pela função

 

A partir dai podemos fazer algumas operações. Uma soma por exemplo utilizando o mesmo código acima:

<?php 

function soma(...$numberss) { 
    return array_sum($numbers); 
} 

var_dump(soma(5, 5, 5, 5)); 

// Saída
int(20)

 

E em alguns casos mais complexos podemos até fazer operações mais distintas:

Consulta de arquivos:

<?php 

function checkFiles(...$files) { 
    return array_map(function($file){ 
        return [$file => file_exists($file) ? 'Found' : 'Not found']; 
    }, $files); 
} 

$busca = checkFiles(
    '1.txt', 
    'about.md', 
    'ex.php', 
    'foo.php'
); 

foreach ($busca as $arquivos) { 
    foreach ($arquivos as $nomeArquivo => $status) 
        echo sprintf('%s => %s' . PHP_EOL, $nomeArquivo, $status); 
} 

// Saída
1.txt => Not found 
about.md => Found 
ex.php => Found 
foo.php => Not found

 

OBS: O exemplo acima é somente um exemplo e não visa substituir as capacidades nativas do php! (Não me diga…)
(Nativamente o php trabalha mto bem com arquivos: GlobIterator entre outros…)

Requisições http, gerar logs, etc:

<?php 

function gerarLogs(...$urls) { 
    array_walk($urls, function($url) { 
        // lógica aqui... Requisições http, etc
        echo sprintf('[+] Gerando logs para: %s' . PHP_EOL, $url); 
    }); 
} 

gerarLogs(
    'http://www.google.com', 
    'http://php.net', 
    'http://theuselessweb.com'
); 

// Output
[+] Gerando logs para: http://www.google.com 
[+] Gerando logs para: http://php.net 
[+] Gerando logs para: http://theuselessweb.com

 

Utilizando type hinting com splat operator

É possível especificar os tipos de argumentos esperados pela função utilizando type hiting normalmente:

<?php 

function expectCarObject(Car ...$cars) { 
    foreach ($cars as $car) { 
        var_dump($car); 
    } 
} 

class Car {} 
expectCarObject(new Car, new Car, new Car); 

// Saida
object(Car)#1 (0) {
} 
object(Car)#2 (0) {
} 
object(Car)#3 (0) {
}

 

Caso seja passado parâmetros diferentes do tipo “Car” um fatal error será emitido pelo php.

Unpacking de argumentos

Com splat operator é possível também fazer unpacking de argumentos, o que significa que é possível escrever algo como:

<?php 

function soma($numA, $numB) { 
    return $numA + $numB; 
} 

$nums = [1, 2]; 
var_dump(soma(...$nums)); 

// Saída:
int(3)

 

Os exemplos estão longe de serem algo definitivo. Da próxima vez que for criar uma classe útil que possui métodos flexíveis, de uma chance ao splat operator.
Dúvidas, sugestões, tomar uma breja? Deixe seu comentário!
Forte abraço!

Referências:

Share this post


Link to post
Share on other sites

Bem-vindo, @proclnas!

Incrível esse post. Não sabia que dava pra fazer isso em PHP. Em C sei que é possível (a própria printf() é um exemplo), no entanto.

Agora, consegue pensar em uma situação onde isso seria mais vantajoso que receber um array diretamente, na função?

Abraço.

Share this post


Link to post
Share on other sites

@Fernando Mercês, obrigado pelas boas vindas!

A utilização do splat operator ajuda mto na portabilidade do código, o que significa que tiramos a responsabilidade do "caller" e deixamos
por conta da função/método o tratamento dos dados.
Lembrando sempre que cada caso uma necessidade, então vale a pena dar uma rabiscada antes pra ver se vale realmente a pena.
Ahh... É muito comum vermos em frameworks esse tipo de prática. ;)
 

<?php

function validateMail(...$hosts) {
    return array_filter($hosts, 'isValidMail');    
}

// Chamadas
validateMail('foo@mentebinaria.com.br');
validateMail(['foo@mentebinaria.com.br'. 'bar@mentebinaria.com.br']);


Abraço

Share this post


Link to post
Share on other sites

Isso é extremamente útil para funções como o mysqli_stmt_bind_param, nativo do PHP.

$array = ['Um', 'Dois', 'Tres', 4];

$stmt = mysqli_prepare($link, "INSERT INTO Tabela VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', ...$array);

mysqli_stmt_execute($stmt);

 

Assim você pode usar um array direto no mysqli_stms_bind_param, devido ao uso do ...$array. ;)

  • Agradecer 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...