What is the simplest way to create a mask for numbers in PHP?

Asked

Viewed 2,129 times

5

I have two ways to create masks for numbers in PHP, but I don’t know if it’s the most elegant and effective, so I would like to have some options to improve the code.

I need the function to behave as follows:

  • Format numbers with less than 8 numbers by filling them with zero.
  • Create a separator (can be a hyphen) in the middle of these 8 numbers. That is, 11112222 will transform into 1111-2222.

I already have these two examples:

Example 1:

implode('-', str_split(sprintf('%08s', $numero), 4));

Example 2

$formatado = sprintf('%08s', $numero);

substr($formatado, 0, 4) . '-' . substr($formatado, 4, 8);

Someone knows a better way, in terms of performance and elegance, without having to call multiple functions to create a PHP mask?

3 answers

8


One way to solve this is to combine str_pad() to fill the left zeros* if the string is less than 8 characters long, chunk_split() to insert the hyphen every 4 characters and the Trim() to remove the added hyphene at the end.

<?php

function mascaraTelefone($numero){
    $numero = str_pad($numero, 8, '0', STR_PAD_LEFT);
    return trim(chunk_split($numero, 4, '-'), '-');
}

echo mascaraTelefone('9999') .PHP_EOL;
echo mascaraTelefone('99998888') .PHP_EOL;
echo mascaraTelefone('77') .PHP_EOL;
echo mascaraTelefone('666') .PHP_EOL;

Example - ideone

Based on: Insertion of a dot every 5 characters

A variant of this code is to exchange chunck_split() for substr_replace() replacing a copy of the character at position X(third argument) with the hyphen in the case.

function mascaraTelefone($numero){
    $numero = str_pad($numero, 8, '0', STR_PAD_LEFT);
    return substr_replace($numero, '-', 4, 0);
}

* The standard behavior of str_pad() is to add the characters to the right, this can be modified by informing the fourth argument of the function who possessed the values:

STR_PAD_RIGHT|Adiciona a direita(padrão caso o quarto argumento seja omitido
STR_PAD_LEFT |Adiciona a esquerda
STR_PAD_BOTH |Adiciona na esquerda e na direita
  • who is this guy chunk_split!? I don’t remember him

  • Ooooh! That’s cool! Very cool, this one chunk_split!

  • I think I’m gonna adopt the str_pad also. Every time I have to stay using the sprintf with that ugly concatenation "0{$size}s%".

  • In case you should not have specified in str_pad the pad_type as STR_PAD_LEFT? By default it will be filled to the right of the value.

  • @Marcelodeandrade well remembered, I changed the code and the explanation of the answer xD

6

Generic formatting with dynamic mask:

function format_string($mask, $str, $ch = '#') {
    $c = 0;
    $rs = '';

    /*
    Aqui usamos strlen() pois não há preocupação com o charset da máscara.
    */
    for ($i = 0; $i < strlen($mask); $i++) {
        if ($mask[$i] == $ch) {
            $rs .= $str[$c];
            $c++;
        } else {
            $rs .= $mask[$i];
        }
    }

    return $rs;
}

$str = '05055344410'; // Exemplo para telefone
echo format_string('###-####-####', $str);
$str = '20150827'; // Exemplo para datas
echo '<br />' . format_string('####-##-##', $str);
  • 1

    At first I thought it would be too much code (regarding the @rray code). But I noticed that its functionality is similar to the jQuery.mask, and that’s very good

  • 5

    The most interesting point is flexibility. It allows formatting strings for multiple purposes, not just localized phone numbers. The inspiration does not come from Jquery, it is a script that I use since 2000 or 1999. I do not remember. At that time there was no stack, google, jquery. It was in the same race. In many cases, code size does not mean better performance. In the first response there is the use of 3 functions. Within these 3 functions there is a whole processing, loop repetition, maybe also use of ER, etc. Theoretically it uses much more code. This costs more processing and memory.

1

It is already very well answered, but I would like to leave here a small technique that uses vsprintf and str_split together.

The function vsprintf is intended to format a string, based on past arguments. But different from sprintf, instead of passing n parameters, you pass a array. Therefore, we could use the function str_split to separate the strings and, with vsprintf, apply the formatting.

In this example, I passed a second argument to str_split, that will cause the string to be divided from 4 to 4, as is the case of phones.

function formatar_telefone($telefone) {
     return vsprintf('%s-%s', str_split($telefone, 4));
}

Of course there will be problems if the phone number does not contain 8 digits. Then in this case, it can be add a check inside the function, with a launch of an error or exception. Or just fill in the numbers with 0, as @rray suggested.

In that case, we could fill in sprintf to fill with zeros, using the expression %08d:

function formatar_telefone($telefone) {
     vsprintf('%s-%s%', str_split(sprintf('%08d', $telefone)));
}

The expression %08d means that you want to format a number, forcing it to be recognized as a digit, and if you have less than 8 characters, you will be filled with 0.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.